Scripting Document 笔记(2)

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);
}
相关文章
相关标签/搜索