4. 屬性(Attribues)php
HTML元素由tag name和稱爲屬性的name/value對集合組成.node
4.1 HTML屬性做爲Element屬性數組
表示HTML文檔屬性的HTMLElement對象定義了read/write屬性, 它們映射了元素的HTML屬性.HTMLElement定義了通用的HTTP屬性(如: id, title lang和dir, 時間處理器onclick)屬性.特定的Element子類型爲其元素定義了特定的屬性.瀏覽器
var p_w_picpath = document.getElementById("myp_w_picpath"); var imgurl = p_w_picpath.src; p_w_picpath.id === "myp_w_picpath" var f = document.forms[0]; f.action = "http://www.example.com/submit.php"; f.method = "POST";
須要注意的是HTML屬性是大小寫不敏感的, 但Javacript的屬性是大小寫敏感的. 若是要轉換一個屬性爲Javascript的屬性, 需將其小寫.app
4.2 獲取和設置非HTML屬性async
HTMLElement及子類型定義了對應HTML元素的標準屬性的屬性, Element類型也定義了用來查找和設置非標準HTML屬性以及XML文檔屬性的方法: getAttribute()和setAttribute(). 如:ide
var p_w_picpath = document.p_w_picpaths[0]; var width = parseInt(p_w_picpath.getAttribute("WIDTH")); p_w_picpath.setAttribute("class", "thumbnail");
上述代碼描述了這些方法和基於屬性的API的顯著區別: 函數
全部屬性值做爲字符串, getAttribute()不會返回數值, boolean和對象.oop
這些方法使用標準屬性名字, 即便那些屬性名字是Javascript保留的關鍵字.url
Element也定義了兩個相關的方法: hasAttribute()和removeAttribute(), 它們用來檢查給定屬性是否存在和刪除屬性.
4.3 做爲Attr節點的屬性
還有一種使用Element的屬性的方法, Node類型定義了attributes屬性, 對於非Element對象的任何節點, 該屬性爲null. 對於Element對象, attributes是隻讀類數組對象, 表示元素的全部屬性. 像Nodelist同樣, attributes也是實時的, 它是能夠用數字索引訪問和屬性名索引. 如:
document.body.attributes[0] document.body.attributes.bgcolor document.body.attributes["ONLOAD"]
當索引attributes對象得到的值是Attr對象, Attr對象是一種特殊的Node, 但不會像Node同樣使用, Attr的name和value屬性返回該屬性的名字和值.
5. 元素內容
5.1 做爲HTML的元素內容
讀取Element的innerHTML屬性做爲字符串標記返回那個元素的內容, 在元素上設置該屬性了Web瀏覽器的解析器, 用新字符串內容的解析展示形式替換元素當前內容. HTML5標準化了innerHTML,HTML5說innerHTML在Document節點和Element節點上工做正常, 但目前未廣泛支持. HTML5還標準化了outerHTML, 當查詢outerHTML時, 返回的HTML或XML標記的字符串包含了被查詢元素的開頭和結尾標籤, 當設置元素的outerHTML時, 元素自己被新的內容替換. 只有Element節點定義了outerHTML屬性, Document則沒有.
5.2 做爲純文本的元素內容
有時須要查找純文本形式的元素內容, 或者在文檔中插入純文本, 標準的方法是用Node的textContent屬性來實現. 如:
var para = document.getElementsByTagName("p")[0]; var text = para.textContent; para.textContent = "Hello World!";
textContent在除了IE的全部瀏覽器中都支持, 在IE中, 用Element的innerText屬性來代替. textContent和innerText屬性很是類似, 能夠互相替換使用, 但需注意空元素和未定義屬性之間的區別:
/** * With one argument, return the textContent or innerText of the element. * With two arguments, set the textContent or innerText of element to value. */ function textContent(element, value) { var content = element.textContent; // Check if textContent is defined if (value === undefined) { // No value passed, so return current text if (content !== undefined) return content; else return element.innerText; } else { // A value was passed, so set text if (content !== undefined) element.textContent = value; else element.innerText = value; } }
5.3 做爲Text節點的元素內容
另外一種處理元素內容的方法是做爲子節點的列表, 每一個子節點可能有它本身的一組子節點, 當考慮元素的內容時, 一般是它的Text節點. 下面的例子給出了查找元素的後代節點中的全部Text節點.
// Return the plain-text content of element e, recursing into child elements. // This method works like the textContent property function textContent(e) { var child, type, s = ""; // s holds the text of all children for(child = e.firstChild; child != null; child = child.nextSibling) { type = child.nodeType; if (type === 3 || type === 4) // Text and CDATASection nodes s += child.nodeValue; else if (type === 1) // Recurse for Element nodes s += textContent(child); } return s; }
nodeValue屬性能夠讀/寫, 設置它能夠改變Text或CDATASection節點所顯示的內容.Text和CDATASection都是CharacterData的子類型, CharacterData定義了data屬性, 它和nodeValue的文本相同. 一下函數經過設置data屬性將Text節點的內容轉化成大寫形式:
// Recursively convert all Text node descendants of n to uppercase. function upcase(n) { if (n.nodeType == 3 || n.nodeTyep == 4) // If n is Text or CDATA n.data = n.data.toUpperCase(); // ...convert content to uppercase. else // Otherwise, recurse on child nodes for(var i = 0; i < n.childNodes.length; i++) upcase(n.childNodes[i]); }
5.4 建立, 插入和刪除節點
Document類型定義了建立Element和Text對象的方法, Node類型定義了在節點樹中插入, 刪除和替換的方法. 以下是節點建立,插入的例子:
// Asynchronously load and execute a script from a specified URL function loadasync(url) { var head = document.getElementsByTagName("head")[0]; // Find document <head> var s = document.createElement("script"); // Create a <script> element s.src = url; // Set its src attribute head.appendChild(s); // Insert the <script> into head }
5.4.1 建立節點
如上能夠經過Document對象的createElement()方法建立Element節點, 該方法接收須要建立元素的tag名字做爲參數. Text節點的建立使用createTextNode()方法, 如:
var newnode = document.createTextNode("text node content");
Document也定義了其餘工廠方法, 如: createComment(), createDocumentFragment()等.
另外一種建立文檔節點的方法是克隆一個存在的節點, 每一個節點有一個cloneNode()方法,其返回存在節點的拷貝副本, 若是傳入參數true, 則嵌套地複製全部子孫, 傳入false返回一個淺拷貝.
5.4.2 插入節點
一旦建立了一個新節點, 就可使用Node的方法appendChild()或者insertBefore()方法將它插入文檔中, appendChild()是在須要插入的Element節點上調用, 它插入指定的節點使其成爲那個節點的最後一個子節點.
insertBefore()相似appendChild(), 可是insertBefore()有兩個參數, 第一個參數是要插入的節點, 第二個參數是已存在的節點, 新插入節點位於節點前面. 這個方法在新插入節點的父節點上調用, 第二個參數必須是父節點的孩子節點. 若是第二個參數是null, 跟appendChild()表現同樣. 以下是appendChild()和insertBefore()的使用例子:
// Insert the child node into parent so that it becomes child node n function insertAt(parent, child, n) { if (n < 0 || n > parent.childNodes.length) throw new Error("invalid index"); else if (n == parent.childNodes.length) parent.appendChild(child); else parent.insertBefore(child, parent.childNodes[n]); }
若是使用appendChild()和insertBefore()插入一個已經存在的節點, 那個節點將自動從當前位置移除, 並插入到新的位置, 可是沒有必要顯式的移除節點. 下面的例子並無建立新的節點, 可是使用appendChild()改變現有節點的順序.
// Sort the rows in first <tbody> of the specified table according to // the value of nth cell within each row. Use the comparator function // if one is specified. Otherwise, compare the values alphabetically. function sortrows(table, n, comparator) { var tbody = table.tBodies[0]; // First <tbody>; may be implicitly created var rows = tbody.getElementsByTagName("tr"); // All rows in the tbody rows = Array.prototype.slice.call(rows,0); // Snapshot in a true array // Now sort the rows based on the text in the nth <td> element rows.sort(function(row1,row2) { var cell1 = row1.getElementsByTagName("td")[n]; // Get nth cell var cell2 = row2.getElementsByTagName("td")[n]; // of both rows var val1 = cell1.textContent || cell1.innerText; // Get text content var val2 = cell2.textContent || cell2.innerText; // of the two cells if (comparator) return comparator(val1, val2); // Compare them! if (val1 < val2) return -1; else if (val1 > val2) return 1; else return 0; }); // Now append the rows into the tbody in their sorted order. // This automatically moves them from their current location, so there // is no need to remove them first. If the <tbody> contains any // nodes other than <tr> elements, those nodes will float to the top. for(var i = 0; i < rows.length; i++) tbody.appendChild(rows[i]); } // Find the <th> elements of the table (assuming there is only one row of them) // and make them clickable so that clicking on a column header sorts // by that column. function makeSortable(table) { var headers = table.getElementsByTagName("th"); for(var i = 0; i < headers.length; i++) { (function(n) { // Nested funtion to create a local scope headers[i].onclick = function() { sortrows(table, n); }; }(i)); // Assign value of i to the local variable n } }
5.4.3 刪除和替換節點
removeChild()方法從文檔樹中刪除一個節點, 但將要刪除的節點不會調用removeChild(), 而是要刪除的節點的父節點調用removeChild()方法, 在刪除節點的父節點調用該方法, 而要刪除的節點做爲參數傳遞給removeChild()方法. 如:
n.parentNode.removeChild(n);
replaceChild()方法首先刪除一個孩子節點而後用心的節點替換它, 這個方法也是被父節點調用, 新節點做爲第一個參數, 被替換的節點做爲第二個參數. replaceChild()的使用參考以下例子:
// Replace the node n with a new <b> element and make n a child of that element. function embolden(n) { // If we're passed a string instead of a node, treat it as an element id if (typeof n == "string") n = document.getElementById(n); var parent = n.parentNode; // Get the parent of n var b = document.createElement("b"); // Create a <b> element parent.replaceChild(b, n); // Replace n with the <b> element b.appendChild(n); // Make n a child of the <b> element }
5.4.4 使用DocumentFragments
DocumentFragments是一特殊的Node,它做爲其餘節點的一個臨時容器, 經過以下建立一個DocumentFragments:
var frag = document.createDocumentFragment();
像Document節點, DocumentFragments是獨立的, 不做爲其餘文檔的一部分, 它的父節點老是爲null. 然而, 跟Element同樣, DocumentFragments能夠有任何數量的孩子, 並且能夠appendChild(), insertBefore()等來操做. DocumentFragments的特殊之處在於它使得一組節點被當作一個節點看待, 若是給appendChild(), insertBefore()或replaceChild()傳遞一個DocumentFragments,實際上是將該文檔片斷的全部子節點插入到文檔中, 而非片斷自己. 下面是一個使用DocumentFragments來反轉孩子節點的順序的例子:
// Reverse the order of the children of Node n function reverse(n) { // Create an empty DocumentFragment as a temporary container var f = document.createDocumentFragment(); // Now loop backward through the children, moving each one to the fragment. // The last child of n becomes the first child of f, and vice-versa. // Note that appending a child to f automatically removes it from n. while(n.lastChild) f.appendChild(n.lastChild); // Finally, move the children of f all at once back to n, all at once. n.appendChild(f); }