From 290445435558edcfb0eb5540b301490d06b4578f Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Sat, 21 Apr 2012 21:18:00 -0400 Subject: [PATCH] Add article on the jQuery object as requested in issue #95 --- content/using-jquery-core/jquery-object.md | 188 +++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 content/using-jquery-core/jquery-object.md diff --git a/content/using-jquery-core/jquery-object.md b/content/using-jquery-core/jquery-object.md new file mode 100644 index 00000000..8f64bce6 --- /dev/null +++ b/content/using-jquery-core/jquery-object.md @@ -0,0 +1,188 @@ +--- +level : beginner +title : The jQuery Object +attribution: Mike Pennisi +github : jugglinmike +--- +Presumably, if you're reading this, you are curious about the thing that jQuery returns when you create new elements (or select existing ones). +This curiosity is a great first step, because a first glance, the jQuery object may seem to be an array of DOM elements. +It has a collection of DOM elements, some familiar array functions, and a `length` property, after all. +Actually, the jQuery object is more complicated than that. + +### What is a DOM element, anyway? + +A DOM element is a "piece" of a web page. +It can contain text and/or other DOM elements. +It is described by a type (i.e. "div", "a", "p", etc.) and any number of attributes (i.e. "src", "href", "class", etc.). +For a more thorough description, please refer to [the office specification from the W3C](http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-745549614). + +Elements have properties like any JavaScript object. +Among these properties are attributes like `tagName` and methods like `appendChild`. +These properties are the only way to interact with the web page via JavaScript. + +### So why not just put the elements in an array? + +It turns out that working directly with DOM elements can be quite awkward. +The jQuery object defines [a ton](http://api.jquery.com/) of methods to smooth out the experience for developers. +For example: + +*Compatability* +The implementation of element methods varies across browser vendors and versions. +Imagine that you wanted to set the inner HTML of a `tr` element stored in `target`. You might write: + + +var target = document.getElementById("target"); +target.innerHTML = "Hello World!"; + + +This works in most cases, but it will fail in most versions of Internet Explorer. +In that case, the [recommended approach](http://www.quirksmode.org/dom/w3c_html.html) is to use pure DOM methods instead. +By wrapping the `target` element in a jQuery object, these edge cases are taken care of, and the expected result is acheived in all supported browsers: + + +var target = document.getElementById("target"); +$( target ).html( "Hello World!"); + + +*Convenience* +There are also a lot of common DOM manipulation use cases that are awkward to accomplish with pure DOM methods. +For instance, if you want to insert the element stored in `newElement` after the element stored in `target`, you have to write: + + +var target = document.getElementById("target"); +var newElement = document.createElement("div"); +target.parentNode.insertBefore( target.nextSibling, newElement ) + + +By wrapping the `target` element in a jQuery object, you can accomplish the same task in a much simpler manner: + + +var target = document.getElementById("target"); +var newElement = document.createElement("div"); +$( target ).after( newElement ); + + +If you're in the business of getting things done (and I suspect that you are), then these details are simply "gotchas" that stand between you and your goals. + +### Sounds good. Now how do I get stuff in there? + +If you pass a CSS selector to the jQuery function, the result will be a jQuery object wrapping any element(s) that match this selector. +For instance, by writing + + +var allHeaders = $("h1"); + + +`headers` is now a jQuery element containing *all* the `

` tags already on the page. +You can convince yourself by checking the `length` property of `headers`: + + +var allHeaders = $("h1"); +alert( allHeaders.length ); + + +If the page has more than one `

` tag, this number will be greater than one. +Likewise, if the page has no `

` tags, the `length` property will be zero. +Checking the `length` property is a common way to ensure that the selector described something on the page. + +To make sure we only have the first header element, we have to take one more step. +There are a number of ways to accomplish that, the most straight-forward may be the `eq()` function. + + +var headers = $("h1"); +var firstHeader = headers.eq(0); + + +Now we can be assured that `firstHeader` is a jQuery object containing only the first `

` element on the page. +And because `firstHeader` is a jQuery object, you can use methods like `html()` or `after()`. +jQuery also has a method named `get()` which provides a related function. +Instead of returning a jQuery-wrapped DOM element, it returns the DOM element itself. + + +var firstHeaderElem = $("h1").get(0); + + +You can also treat the jQuery object like a true JavaScript array and use brackets to retrieve the DOM element you want, like so: + + +var firstHeaderElem = $("h1")[0]; + + +In either case, `firstHeaderElem` contains the "native" DOM element. +This means it has DOM properties like `innerHTML` and methods like `appendChild()`, but *not* jQuery methods like `html()` or `after()`. +As discussed earlier, the element is more difficult to work with, but there are certain instances where you will need it. +One such instance is making comparisons. + +### Not all jQuery objects are created `===` + +An important detail regarding this "wrapping" behavior is that each wrapped object is unique. +This is true *even if the object was created with the same selector*. + + +var logo1 = $("#logo"); +var logo2 = $("#logo"); + + +Although `logo1` and `logo2` are created in the same way (and wrap the same DOM element), they are not the same object. +For example: + + +alert( $("#logo") === $("#logo") ); // alerts 'false' + + +However, both objects contain the same DOM element. +The `get` method is useful for testing if two jQuery objects have the same DOM element. + + +var logo1 = $("$logo"); +var logo1Elem = logo1.get(0); + +var logo2 = $("#logo"); +var logo2Elem = logo2.get(0); + +alert( logo1Elem === logo2Elem ); // alerts 'true' + + +Many developers prefix a `$` to the name of variables that contain jQuery objects in order to help differentiate. +There is nothing magic about this practice--it just helps some people to keep track of what different variables contain. +We could re-write the previous example to follow this convention: + + +var $logo1 = $("$logo"); +var logo1 = $logo1.get(0); + +var $logo2 = $("#logo"); +var logo2 = $logo2.get(0); + +alert( logo1 === logo2 ); // alerts 'true' + + +This code functions identically to the example above, but it is a little more clear to read. + +### jQuery objects are not "live" + +Given a jQuery object with all the paragraph elements on the page: + + +var allParagraphs = $("p"); + + +...you might expect that the contents will grow and shrink over time as `

` elements are added and removed from the document. +This is *not* actually the case. +The set of elements contained within a jQuery object will not change unless you modify it in your code. +This means that the collection is not "live"--it does not automatically update as the document changes. +If you expect the document may have changed from when you created the jQuery object, then update your collection by creating a new one! +It can be as easy as re-running the same selector: + + +allParagraphs = $("p"); + + +### Wrapping up + +Although DOM elements provide all the functionality one needs to create interactive web pages, they can be a hassle to work with. +The jQuery object wraps these elements to smooth out this experience and make common tasks easy. +When creating or selecting elements with jQuery, the result will always be wrapped in a new jQuery object. +If you do need the native DOM elements, you can always use the `get()` method and/or array-style subscripting to get at them. + +These dinstinctions may not be immediately obvious, but understanding them is an important step in fully utilizing jQuery as it was intended.