2012年5月23日 星期三

Learning jQuery, Third Edition

Bear在這裡買的
amazon的參考

jQuery基礎教程(第3版)/圖靈程序設計叢書
作者:(美)查弗//斯威德伯格|譯者:李松峰
出版社:人民郵電
ISBN:9787115275851
出版日期:2012/04/01
頁數:318
人民幣:RMB 59 元


P.6(原文P.15)
這裡要注意的是引用jQuery庫文件的<scripe>標籤,必須放在引用自定義腳本文件的<scripe>標籤之前。否則,在我們編寫的代碼中將引用不到jQuery框架。

After the stylesheet is referenced, the JavaScript files are included. It is important that the script tag for the jQuery library be placed before the tag for our custom scripts; otherwise, the jQuery framework will not be available when our code attempts to reference it.

P.7(原文P.17)

jQuery中基本的操作就是選擇文檔中的某一部份,這是通過$()函數來完成的。通常,該函數需要一個字符串參數,參數中可以包含任何CSS選擇符表達式。

The fundamental operation in jQuery is selecting a part of the document. This is done with the $() function. Typically, it takes a string as a parameter, which can contain any CSS selector expression. In this case, we wish to find all of the <div> elements in the document that have the poem-stanza class applied to them, so the selector is very simple. However, we will cover much more sophisticated options through the course of the book. We will step through many ways of locating parts of a document in Chapter 2, Selecting Elements.

P.8(原文P.17)
前面我們提到過,jQuery在.addClass()等方法中使用了隱式迭代機制,因此一次函數調用就可以完成對所有選擇的文檔部份的修改。

Note that no iteration is necessary to add the class to all the poem stanzas. As we discussed, jQuery uses implicit iteration within methods such as .addClass(), so a single function call is all it takes to alter all of the selected parts of the document.

P.8(原文P.17~18)
1.儘可能使用瀏覽器原生的DOM就緒實現,並以window.onload事件處理程序作為後備。
可以多次調用$(document).ready()並按照調用它們的順序執行。
2.即使是在瀏覽器事件發生之後通過$(document).ready()添加函數,這些函數也會被被調用。
3.異步處理事件的預定,必要時腳本可以延遲執行。
4.通過重覆檢查一個幾乎與DOM同時可用的方法,在較早版本的瀏覽器中模擬DOM就緒事件。

1. Uses the browser's native DOM ready implementations when available and adds a window.onload event handler as a safety net Allows for multiple calls to $(document).ready() and executes them in the order in which they are called
2. Executes functions passed to $(document).ready() even if they are added after the browser event has already occurred
3. Handles the event scheduling asynchronously to allow scripts to delay it if necessary
4. Simulates a DOM ready event in some older browsers by repeatedly checking for the existence of a DOM method that typically becomes available at the same time as the DOM

P.8(原文P.18)
這個方法也可以接收一個匿名函數(有時也叫做lambda函數)

However, as demonstrated in the original version of the script, and repeated in Listing 1.2, as follows, the method can also accept an anonymous function (sometimes also called a lambda function), as follows:

P.9(原文P.18)
這種匿名函數的寫作在jQuery中十分方便,特別適合傳遞那些不會被重用的函數。而且,與此同時創建的閉包也是一種非常高級和強大的工具。

This anonymous function idiom is convenient in jQuery code for methods that take a function as an argument when that function isn't reusable. Moreover, the closure it creates can be an advanced and powerful tool. However, it may also have unintended consequences and ramifications on memory use, if not dealt with carefully. The topic of closures is discussed fully in Appendix A, JavaScript Closures.

P.10(原文P.20)
1. 正確地處理其他window.onload事件處理程序。
2. 在DOM就緒後馬上執行。
3. 利用較新的DOM方法來檢索元素和執行其他任務,從優化代碼性能。

1. Properly respecting other window.onload event handlers
2. Acting as soon as the DOM is ready
3. Optimizing element retrieval and other tasks with modern DOM methods

P.16(原文P.28)
負責任的jQuery開發者應該在編寫自已的程序時,始終堅持漸進增強(progressive enhancement)和優雅降級(graceful degradation)的理念,做到在沒有JavaScript禁用時,頁面仍然能夠與啟用JavaScript時一樣準確地呈現,即使沒有那麼美觀。

Progressive enhancement
Responsible jQuery developers should always apply the concepts of progressive enhancement and graceful degradation to their code, ensuring that a page will render as accurately, even if not as beautifully, with JavaScript disabled as it does with JavaScript turned on. We will continue to explore these concepts throughout the book.

P.19(原文P.31)
屬性選擇符使用一種正則表達式中借鋻來的通配符語法,以^表示值在字符串的開始,以$表示值在字符串的結尾。而且,也是用星號*表示要匹配的值可以出現在字符中的任意位置,用驚嘆號!表示對值取反。

Attribute selectors accept a wildcard syntax inspired by regular expressions for identifying the value at the beginning (^) or ending ($) of a string. They can also take an asterisk (*) to indicate the value at an arbitrary position within a string or an exclamation mark (!) to indicate a negated value.

P.22(原文P.34)
注意,因為JavaScript數組採用從0開始的編號方式,所以 eq(1) 取得的是集合中的第2個元素。而CSS則是從1開始的,因此CSS選擇符 $('div:nth-child(1)') 取得的是作為其父元素第1個子元素的所有div元素。

Note that :eq(1) selects the second item in the set because JavaScript array numbering is zero-based, meaning that it starts with 0. In contrast, CSS is one-based, so a CSS selector such as $('div:nth-child(1)') would select all div selectors that are the first child of their parent (in this case, however, we would probably use $('div:first-child') instead).

P.24(原文P.36)
等一等!為什麼針對奇數行使用:even選擇符呢?很簡單, :eq() 選擇符、:even 和 :odd 選擇符都使用JavaScript內置從0開始的編號方式,因此,第一行的編號為0(偶數),第二行的編號為1(奇數),依此類推。

But wait! Why use the :even selector for odd-numbered rows? Well, just as with the :eq() selector, the :even and :odd selectors use JavaScript's native zero-based numbering. Therefore, the first row counts as 0 (even) and the second row counts as 1 (odd), and so on. With this in mind, we can expect our simple bit of code to produce tables that look similar to the following screenshot:

P.25(原文P.37)
值得一提的是,:nth-child() 是 jQuery 中唯一從1開始計數的選擇符。

As before, note that :nth-child() is the only jQuery selector that is one-based. To achieve the same row striping as we did above—except with consistent behavior for the second table—we need to use odd rather than even as the argument. With this selector in place, both tables are now striped nicely, as shown in the following screenshot:

P.26(原文P.38)
必須注意,:contains()選擇符區分大小寫。

It's important to note that the :contains() selector is case-sensitive. Using $('td:contains(henry)') instead, without the uppercase "H," would select no cells.

誠然,不使用jQuery(或任何客戶端編程語言)也可以通過其他方式實現這種行條文和突出顯示效果。然而,在內容由程序動態生成,而我們又無權改動HTML和服務器端代碼的情況下,jQuery加上CSS對這種樣式化操作提供了優秀的替換方案。

Admittedly, there are ways to achieve the row striping and text highlighting without jQuery—or any client-side programming, for that matter. Nevertheless, jQuery, along with CSS, is a great alternative for this type of styling in cases where the content is generated dynamically and we don't have access to either the HTML or server-side code.

P.27(原文P.40)
同樣,.filter()的功能也十分強大,因為它可以接受函數參數。

For the most part, however, the two ways of selecting elements complement each other. Furthermore, the .filter() method in particular has enormous power because it can take a function as its argument. The function allows us to create complex tests for whether elements should be kept in the matched set. Let's suppose, for example, we want to add a class to all external links. jQuery has no selector for this sort of case. Without a filter function, we'd be forced to explicitly loop through each element, testing each one separately. With the following filter function, however, we can still rely on jQuery's implicit iteration and keep our code compact:

P.30(原文P.44)
連綴就像是一口氣說出一大段話~雖然效率很高,但對別人來說可能會難以理解。而將它分開放到多行並添加明確的注釋,從長遠來看則可以節省更多的時間。

Chaining can be like speaking a whole paragraph's worth of words in a single breath—it gets the job done quickly, but it can be hard for someone else to understand. Breaking it up into multiple lines and adding judicious comments can save more time in the long run.

P.32(原文P.47)
雖然這也意味著所有元素對腳本而言都是可以訪問的,但是,卻不意味著所有關聯的文件都已經下載完畢。

On the other hand, a handler registered using $(document).ready() is invoked when the DOM is completely ready for use. This also means that all elements are accessible by our scripts, but does not mean that every associated file has been downloaded. As soon as the HTML has been downloaded and parsed into a DOM tree, the code can run.

P.33(原文P.49)
如果帶著圖括號,函數會被立即調用;沒有圖括號,函數名稱就只是函數的標識符或函數引用,可以用於在將來再調用函數。

To be fair, jQuery doesn't have a monopoly on workarounds to this issue. We can write a JavaScript function that forms a new function that calls the existing onload handler, then calls a passed-in handler. This approach avoids conflicts between rival handlers like $(document).ready() does, but lacks some of the other benefits we have discussed. In modern browsers, including Internet Explorer 9, the DOMContentLoaded event can be triggered with the W3C standard document.addEventListener() method. However, if we need to support older browsers as well, jQuery handles the inconsistencies that these browsers present so that we don't have to.

P.34(原文P.)
雖然這種語法更短一些,但作者推薦使用較長的形式,因為較長的形式能夠更清楚地表明代碼在做什麼。

$(document).ready(function() {
// Our code here...
});
We can also write the following code:
$(function() {
// Our code here...
});
While this other syntax is shorter, the longer version makes code more descriptive about what it is doing. For this reason, we will use the longer syntax throughout this book.

P.37(原文P.54)
多次調用 .bind() 也沒有任何問題,即可以按需求為同一個事件追加更多的行為。
(Bear: 意即單一個事件可以同時綁定多個行為,就像是C#的事件綁定一樣)

That's all there is to binding a behavior to an event. The advantages we discussed with the .ready() method apply here, as well. Multiple calls to .bind() coexist nicely, appending additional behaviors to the same event as necessary.

P.39(原文P.55)
當觸發任何事件處理程序時,關鍵字 this 引用的都是攜帶相應行為的DOM元素。前面我們談到過,$()函數可以將DOM元素作為參數,而 this 關鍵字是實現這個功的關鍵。通過在事件處理程序中使用 $(this) ,可以為相應的元素創建jQuery對象,然後就如同使用CSS選擇符找到該元素一樣對它進行操作。

When any event handler is triggered, the keyword this refers to the DOM element to which the behavior was attached. Earlier we noted that the $() function could take a DOM element as its argument; this is one of the key reasons that facility is available. By writing $(this) within the event handler, we create a jQuery object corresponding to the element, and can act on it just as if we had located it with a CSS selector.

P.42(原文P.59)
而之所以能夠做的到這一點,是因為jQuery總是按照我們註冊的順序來觸發事件處理程序。最後,可以通過再次利用事件的執行環境來完全除特殊的處理程序。因為環境關鍵字this引用的是DOM元素,而不是jQuery對象,所以可以使用原生的DOM屬性來確定被單擊元素的ID。因而,就可以對所有按鈕都綁定相同的處理程序,然後在這個處理程序內部針對按鈕執行不同的操作。

Note that we need to move the general handler above the specific ones now. The .removeClass() needs to happen before the .addClass(), and we can count on this because jQuery always triggers event handlers in the order in which they were registered. Finally, we can get rid of the specific handlers entirely by, once again, exploiting event context. As the context keyword this gives us a DOM element rather than a jQuery object, we can use native DOM properties to determine the ID of the element that was clicked. We can, thus, bind the same handler to all the buttons and within the handler perform different actions for each button, as follows:

P.49(原文P.67)
事件對象是一種DOM結構,它會在元素獲得處理事件的機會時傳遞給被調用的事件處理程序。

To solve this problem, we need access to the event object. This is a DOM construct that is passed to each element's event handler when it is invoked. It provides information about the event, such as where the mouse cursor was at the time of the event. It also provides some methods that can be used to affect the progress of the event through the DOM.

P.54(原文P.73)
不過有必要在這裡提醒一下大家,其實可以直接使用 .live() 替換 .bind() ,從而獲得使用事件委托的很多好處。
(Bear:1.7版後就全部改用.on()了,所以這裡的資訊是過時的)

As event delegation can be helpful in so many situations, jQuery includes a set of methods specifically for using this technique. We'll fully examine these methods— .live(), .die(), .delegate(), and .undelegate()—in Chapter 10, Advanced Events. It's worth mentioning now, however, that .live() can be used as a drop-in replacement for .bind() while providing much of the benefit of event delegation. For example, to bind a live click handler to the style-switcher buttons, we can write the following code snippet:

P.57(原文P.76)
在此需要強調一點,使用命名函數時,必須省略函數名稱後面的圖括號。圖括號會導致函數被調用,而非被引用。

Also, recall that .bind() takes a function reference as its second argument. It is important to remember when using a named function here to omit parentheses after the function name; parentheses would cause the function to be called, rather than referenced.

P.58(原文P.78)
對於只需觸發一次,隨後要立即解除綁定的情況也有一種簡寫方法~ .one()

A shortcut is also available for the situation in which we want to unbind an event handler immediately after the first time it is triggered. This shortcut, called .one(), is used as follows:

P.59(原文P.79)
如果想知道用戶按了那個鍵,應該監聽keyup 或 keydown 事件;如果想知道用戶輸入的是什麼字符,應該監聽 keypress 事件。

There are two types of keyboard events: those that react to the keyboard directly (keyup and keydown) and those that react to text input (keypress). A single character entry event could correspond to several keys: for example, the Shift key in combination with the X key creates the capital letter X. While the specifics of implementation differ from one browser to the next (unsurprisingly), a safe rule of thumb is as follows: if you want to know what key the user pushed, then you should observe the keyup or keydown event; if you want to know what character ended up on the screen as a result, then you should observe the keypress event. For this feature, we just want to know when the user presses the D, N, or L key, so we will use keyup.

事實上,鍵盤事件的目標是當前擁有鍵盤焦點的元素。元素的焦點可會在幾種情況下轉移,包括單擊鼠標和按下 Tab 鍵。

Next, we need to determine which element should watch for the event. This is a little less obvious than with mouse events, where we have an obvious mouse cursor to tell us about the event's target. Instead, the target of a keyboard event is the element that currently has the keyboard focus. The element with focus can be changed in several ways, including mouse clicks and presses of the Tab key. Not every element can get the focus either; only items that have default keyboard-driven behaviors such as form fields, links, and elements with a .tabIndex property are candidates.

P.66(原文P.87)
同樣,在需要多次使用某個 jQuery 對象時,最好也把這個對象保存到一個變量中,從而達到緩存數據的目的。

Next, the font size can be easily discovered by using the .css() method: $('div.speech').css('fontSize'). However, the returned value is a string, containing both the numeric font size value and the units of that value (px). We'll need to strip the unit label off in order to perform calculations with the numeric value. Also, when we plan to use a jQuery object more than once, it's generally a good idea to cache the selector by storing the resulting jQuery object in a variable.

注意變量名 $speech 中的 $。由於$是JavaScript變量中合法的字符,因此可以利用它來提醒自已該變量中保存著一個jQuery對象。

The first line inside $(document).ready() now creates a variable containing a jQuery object pointing to <div class="speech">. Notice the use of a $ in the variable name, $speech. As $ is a legal character in JavaScript identifiers, we can use it as a reminder that the variable is storing a jQuery object.

P.77(原文P.101)
這些屬性值的單位後綴是可選的,如果不指定,就會預設以px作為單位。最後,height屬性使用我們以前沒有遇到過的語法,其中屬性值前面的+=操作符表示相對值。在這里表示的意恩不是以動畫方式變化到20像素,而是在原來基礎上再以動畫方式變化20像素。因為涉及特殊字符問題,所以必須以字符串形式指定相對值,也就是說必須把值放到一對括號內。

It is worth examining these animated properties in detail. The borderWidth property is straightforward, as we are specifying a constant value with units, just as we would in a stylesheet. The left property is a computed numeric value. The unit suffix is optional on these properties; as we omit it here, px is assumed. Finally, the height property uses a syntax we have not seen before. The += prefix on a property value indicates a relative value. So, instead of animating the height to 20 pixels, the height is animated to 20 pixels greater than the current height. Because of the special characters involved, relative values must be specified as a string, so must be enclosed in quotes.


P.85(原文P.109)
可靠地引用 $(this) 的一種簡單方法,就是在.click()方法內部把它保存到一個變量中,例如var $clickedItem = $(this).

A simple way to keep the $(this) reference stable is to store it in a variable right away within the click handler, like var $clickedItem = $(this).

P.92(原文P.)
這種HTML屬性與對應的DOM屬性名字不相同的情況並不多,而這裡就是一個例子。

The Firebug inspector shows us that the highlighted <p> element has an attribute called class with a value of square. In the right panel, we can see that this element has a corresponding property called className with a value of square. This illustrates one of the rare situations in which an attribute and its equivalent property have different names.

大多數情況下,HTML屬性與對應的DOM屬性的作用都是一樣的,jQuery可以幫我們處理名字不一致的問題。可是,有時我們的確需要留意這兩個屬性的差異~特別數據類型的差異,比如HTML的checked屬性是一個字符串,而DOM中的checked屬性則是一個布林值。對於布林值屬性,最後是測試DOM屬性而不是HTML屬性,以確保跨瀏覽器的一致行為。

In most cases, attributes and properties are functionally interchangeable, and jQuery takes care of the naming inconsistencies for us. However, at times we do need to be mindful of the differences between the two. In particular, data types may differ: the checked attribute has a string value, while the checked property has a Boolean value. For these Boolean attributes, it is best to test and set the property rather than the attribute to ensure consistent cross-browser behavior.

P.93(原文P.)
再次重申,無論什麼時候都不應該忘記,我們添加的所有功能、視覺效果或是文本性的信息,只有在可以使用(並啟用了)JavaScript的WEB瀏覽器中才能正常有效。

Accessibility reminder
We should keep in mind, once again, the inherent danger in making certain functionality, visual appeal, or textual information available only to those with web browsers capable of (and enabled for) using JavaScript. Important information should be accessible to all, not just people who happen to be using the right software.

P.102(原文P.130)
在預設情況下,.clone()方法不會複制匹配的元素或其後代元素中綁定的事件。不過可以為這個方法傳遞一個布林值參數,將這個參數設置為true,就可以連同事件 一起複制,即 .clone(true) 。這樣一來就就可以避免每次複制之後還要手工重新綁定事件的麻煩。

Clone with events
The .clone() method, by default, does not copy any events that are bound to the matching element or any of its descendants. However, it can take a single Boolean parameter that, when set to true, clones events as well: .clone(true). This convenient event cloning allows us to avoid having to deal with manually rebinding events, as was discussed in Chapter 3.

P.105(原文P.134)
在此要注意傳入的HTML必須是有效的,而且要對特殊字符進行轉義。
(Bear: 這裡要看範例程式會比較清楚)

When called without arguments, .html() returns a string representation of the HTML inside the matched element. With an argument, the contents of the element are replaced by the supplied HTML. Take care to only specify valid HTML, escaping special characters properly, when using this technique.

P.113(原文P.143)
當新HTML片段插入相應的CSS規則也會立即應用到它的標簽上。

Note that the HTML is now styled, whereas before it was plain. This is due to the CSS rules in the main document; as soon as the new HTML snippet is inserted, the rules apply to its elements as well.

P.114(原文P.144)
對於必須要延遲到加載完成才能繼續的操作,jQuery提供了一個回調函數。我們在第4章就已經使用過回調函數了。通過回調函數可以在某些效果完成之後執行操作。AJAX回調的功能與此類似,只不過是在數據從服務器返回後執行操作。

If actions must be delayed until the load has been completed, jQuery provides a callback for this. We've already used callbacks in Chapter 4, Styling and Animating, using them to execute actions after an effect has completed. Ajax callbacks perform a similar function, executing after data arrives from the server. An example will be provided below.

P.115(原文P.145)
JSON規定所有對象鍵以及所有字符串值,都必須包含在雙引號中。而且,函數也不是有效的JSON值。

While based on JavaScript object literals and array literals, JSON is more prescriptive about its syntax requirements and more restrictive about the values it allows. For example, JSON specifies that all object keys, as well as all string values, must be enclosed in double quotes. Furthermore, functions are not valid JSON values. Because of its strictness, developers should avoid hand-editing JSON and instead rely on a server-side language to format it properly.

P.117(原文P.148)
這種方式要求數據中包含可以直接用來建構HTML的安全內容,例如,數據中不能包含任何<字符。

Safe HTML
This approach presumes that the data is safe for HTML consumption; it should not contain any stray < characters, for example.

P.130(原文P.162)
在代碼清單6-13中,我們把event對象傳入了submit處理程序,並使用event.preventDefault()而不是return false結束該處理程序。當預設動作是重新加載頁面或打開新頁面時,我們推薦這做法。例如,如果submit處理程序中包含JavaScript錯誤,那麼在第一行代碼中阻止預設動作就能確保不會提交表單,而且瀏覽器的錯誤控制台也會收到錯誤報告。第3章曾介紹過,return false 意味著同時調用 event.preventDefault() 和 event.stopPropagation()。因此要想停止事件冒泡,我們還得再調用後者。

Return false or prevent default?
In Listing 6.13, we have chosen to pass the event object into the submit handler and use event.preventDefault() rather than ending the handler with return false. This practice is recommended when the default action would otherwise reload the page or load another page. If our submit handler, for example, contains a JavaScript error, then preventing default on the handler's first line ensures that the form will not be submitted and our browser's error console will properly report the error. Remember from Chapter 3, Handling Events, however, that return false calls both event.preventDefault() and event. stopPropagation(). In order to stop the event from bubbling, we would need to call the latter as well.

P.138
由於在動態注入的<script>標籤中,腳本可以來源於任何一個域(src屬性可以指向任何第三方站點),也就意味著可以通過該腳本中的XMLHttpRequest對象取得任何其它域中的信息,因而就繞過了"同源策略"的安全限制。Google Map的Google Maps API(http://google.com/apis/maps)就採用了這種動態生成<script>標籤的技術。

P.192(原文P.237)
開發人員中有一條經驗法則,那就是人的時間總比機器的時間更值錢~除非應用程序確實明顯反應遲鈍。

Therefore, a good rule of thumb is to consider developers' time more valuable than the computer's time, unless we notice slowness in our application.

P.194(原文P.240)
告訴大家一條通用的經驗法則:要盡可能使用CSS規範中規定的選擇符,除非沒有可使用jQuery的自定義選擇符。同樣,在修改選擇符之前,也要記住只在確實有必要提升性能的情況下再去提升。

As a general rule of thumb, we should prefer selectors that are part of the CSS specification over jQuery's custom selectors whenever possible. Still, before changing our selectors, it makes sense to first confirm that there is a need to increase performance and then test just how much the change would boost performance with a benchmarking tool such as http://jsperf.com.

P.317
總結一下,調用.on()方法的對象任何時候都是實際綁定處理程序的對象,負責處理事件。在不給.on()提供選擇符參數的情況下,就是普通的事件綁定;而在給.on()提供選擇符參數的情況下,就是事件委托,調用.on()的元素就是事件委托中的受托方(如上面例子中的.comment 和 document)。

P.318
為了明確起見,建議在傳入數據的情況下,最好還是給第二個參數傳入一個null值(一般事件綁定),或者傳入一個選擇符值(事件委托)。