JavaScriptDOM編程藝術 綜合示例global.js源碼

下面是完整的global.js源碼,部分程序稍作瞭一些修改(不需要修改其他源文件),並且註明瞭在使用THML5的時候哪些函數可以不需要。

function addLoadEvent(func) { // 為load事件添加響應函數
    var curonload = window.onload; // 保存當前的load事件響應函數
    if(typeof curonload != 'function') { // 如果當前的load事件響應函數的類型不是function的話,即沒有綁定任何load事件響應函數的話,
        window.onload = func; // 則將func幫定為load事件的響應函數。
    } else { //否則,
        window.onload = function() { // 為load事件綁定新的響應函數,其定義如下:
            curonload(); //當前的load事件響應函數
            func(); // 新添加的load事件響應函數
        }
    }
}

function insertAfter(newElement, targetElement) { // 在目標元素(targetElement)之後插入新元素(newElement)
    var parent = targetElement.parentNode; // 獲得目標元素的父節點
    if(parent.lastchild == targetElement) { // 如果目標元素是父節點的最後一個子節點的話,
        parent.appendChild(targetElement); // 直接調用內置的appendChild()函數,將新元素追加到最後。
    } else { // 否則
        parent.insertBefore(newElement, targetElement.nextSibling); // 調用內置的insertBefore()函數,將新元素插入到目標元素的下一個兄弟節點之前
    }
}

function addClass(element, value) { // 為元素(element)添加新類(value)
    if(!element.className) { // 如果元素的類屬性值為空字符串的話,則
        element.className = value; // 將元素的類屬性設置為value
    } else { // 否則
        newClassName = element.className; // 使用newClassName保存className屬性當前的值
        newClassName += " "; // 因為向元素添加不同的類需要用空格隔開,所以使用字符串加法添加一個空格
        newClassName += value; // 將新類名添加到newClassName中
        element.className = newClassName; // 將元素的類名屬性設置為newClassName
    }
}

function hilightPage() { // 高亮當前頁的導航
    if(!document.getElementsByTagName) return false;
    if(!document.getElementById) return false;
    var headers = document.getElementsByTagName('header'); // 獲得header元素
    if(0 == headers.length) return false;
    var navs = headers[0].getElementsByTagName('nav'); // 獲得nav元素
    if(0 == navs.length) return false;
    var links = navs[0].getElementsByTagName('a'); // 獲得包含a元素的數組
    var linkurl; // 定義變量linkurl用於存儲完整的超鏈接
    for(var i = 0; i < links.length; ++i) { // 遍歷導航欄的所有鏈接
        linkurl = links[i].getAttribute('href'); // 獲得第i個a元素的href值
        if(window.location.href.indexOf(linkurl) != -1) { // 如果當前地址中包含linkurl,則
            links[i].className = 'here'; // 將導航欄中第i個a元素的類屬性設置為here
            var linktext = links[i].lastChild.nodeValue.toLowerCase(); // 獲得a元素的文本子節點(即導航欄上顯示的文本)的小寫形式
            document.body.setAttribute('id', linktext); // 將當前網頁的id屬性設置為linktext
            break; // 不用再處理後面的a元素
        }
    }
}

function moveElement(elementID, final_x, final_y, interval) { // 在瀏覽器內容窗口中移動id為elementID的元素到位置final_x和final_y,刷新間隔為interval
    if(!document.getElementById) return false;
    if(!document.getElementById(elementID)) return false;
    var elem = document.getElementById(elementID); // 獲得需要移動的元素
    if(elem.movement) { // 如果元素elem有屬性movement,則
        clearTimeout(elem.movement); // 取消數字movement代表的由setTimeout()方法產生的延時調用
    }
    // 如果該元素沒有默認初始位置,則設置該元素的初始位置為相對於父元素的左上角
    if(!elem.style.left) {
        elem.style.left = '0px';
    }
    if(!elem.style.top) {
        elem.style.top = '0px';
    }
    // 獲得元素的初始位置
    var xpos = parseInt(elem.style.left);
    var ypos = parseInt(elem.style.top);
    // 如果到達目標位置則返回true
    if(xpos == final_x && ypos == final_y) {
        return true;
    }
    // 移動x和y,每次移動的距離為當前位置到目標位置的十分之一
    if(xpos < final_x) { // 移動x
        var dist = Math.ceil((final_x - xpos) / 10);
        xpos += dist;
    } else {
        var dist = Math.ceil((xpos - final_x) / 10);
        xpos -= dist;
    }
    if(ypos < final_y) { // 移動y
        var dist = Math.ceil((final_y - ypos) / 10);
        xpos += dist;
    } else {
        var dist = Math.ceil((ypos - final_y) / 10);
        ypos -= dist;
    }
    // 需要為left和top屬性加上單位px(像素)
    elem.style.left = xpos + 'px';
    elem.style.top = ypos + 'px';
    // 以interval為間隔延時調用函數moveElement()
    var repeat = "moveElement('"+elementID+"',"+final_x+","+final_y+","+interval+")";
    elem.movement = setTimeout(repeat,interval); // 保存代表該延時調用的數字
}

function prepareSlideshow() { // 滑動顯示動畫的準備函數
    if(!document.getElementsByTagName) return false;
    if(!document.getElementById) return false;
    if(!document.getElementById('intro')) return false;
    var intro = document.getElementById('intro');
    // 創建滑動區域,並設置id為slideshow
    var slideshow = document.createElement('p');
    slideshow.setAttribute('id', 'slideshow');
    // 創建一個圖片元素用於顯示邊框
    var frame = document.createElement('img');
    frame.setAttribute('src', 'images/frame.gif');
    frame.setAttribute('alt', '');
    frame.setAttribute('id', 'frame');
    slideshow.appendChild(frame); // 將frame追加為slideshow的子節點
    // 創建圖片元素並設置屬性
    var preview = document.createElement('img');
    preview.setAttribute('src', 'images/slideshow.gif');
    preview.setAttribute('alt', 'a glimpse of what awaits you');
    preview.setAttribute('id', 'preview');
    slideshow.appendChild(preview); // 將preview追加為slideshow的子節點
    insertAfter(slideshow, intro); // 將slideshow插入到元素intro後面

    var links = document.getElementsByTagName('a'); // 獲得所有的鏈接
    var destination; // 定義變量destination以保存目標url
    for(var i = 0; i < links.length; ++i) { // 遍歷為個鏈接
        links[i].onmouseover = function() { // 為每個鏈接添加mouseover事件的響應函數
            destination = this.getAttribute('href'); // 將destination設置為鼠標當前懸停的鏈接
            // 移動圖片
            if(destination.indexOf('index.html') != -1) {
                moveElement('preview', 0, 0, 5);
            } else if(destination.indexOf('about.html') != -1) {
                moveElement('preview', -150, 0, 5);
            } else if(destination.indexOf('photos.html') != -1) {
                moveElement('preview', -300, 0, 5);
            } else if(destination.indexOf('live.html') != -1) {
                moveElement('preview', -450, 0, 5);
            } else if(destination.indexOf('contact.html') != -1) {
                moveElement('preview', -600, 0, 5);
            }
        }
    }
}

function showSection(id) { // 顯示某部分內容
    var sections = document.getElementsByTagName('section'); // 獲得所有的section元素
    for(var i = 0; i < sections.length; ++i) { // 遍歷所有的section
        if(sections[i].getAttribute('id') != id) { // 如果不是當前的section則
            sections[i].style.display = 'none'; // 不顯示
        } else { // 否則
            sections[i].style.display = 'block'; // 顯示
        }
    }
}

function prepareInternalnav() { // 準備內部導航
    if(!document.getElementsByTagName) return false;
    if(!document.getElementById) return false;
    var articles = document.getElementsByTagName('article'); // 獲得所有的article元素
    if(0 == articles.length) return false; // 如果沒有article元素則返回false
    var navs = articles[0].getElementsByTagName('nav'); // 獲得article內部所有的的nav元素
    if(0 == navs.length) return false; // 如果沒有nav元素則返回false
    var nav = navs[0]; // 取第一個nav元素
    var links = nav.getElementsByTagName('a'); // 獲得navs[0]中所有的a元素
    for(var i = 0; i < links.length; ++i) { // 遍歷每個鏈接
        var sectionId = links[i].getAttribute('href').split('#')[1]; // 將鏈接中的#號去掉,以獲得網頁內部錨的地址(獲取每個section的id)
        if(!document.getElementById(sectionId)) continue; // 如果不存在id為sectionID的section元素,則跳過本次循環
        document.getElementById(sectionId).style.display = 'none'; // 將所有的section都設置為不顯示
        links[i].destination = sectionId; // 為每個鏈接(a元素)添加一個名為destination的新屬性用於儲存目標section的id
        links[i].onclick = function() { // 為頁內導航的click事件添加事件響應函數
            showSection(this.destination); // 顯示鏈接i對應的section
            return false; // 返回false防止頁面跳轉
        }
    }
}

function showPic(whichpic) { // 顯示圖片
    var source = whichpic.getAttribute('href'); // 獲得當前圖片代表的鏈接(該鏈接指向當前圖片放大後的圖片)
    var placeholder = document.getElementById('placeholder');
    placeholder.setAttribute('src', source); // 將placeholder的圖片設置為當前圖片放大後的圖片
    var text = ''; // 創建描述文本並設置為空字符串
    if(whichpic.getAttribute('title')) { // 獲得title屬性
        text = whichpic.getAttribute('title');
    }
    var description = document.getElementById('description'); // 獲得id為description的p元素
    if(3 == description.firstChild.nodeType) { // 如果第一個子節點為文本節點的話,則
        description.firstChild.nodeValue = text; // 將文本節點的值設置為text
    }
}

function preparePlaceholder() { // 準備圖片顯示區域
    if(!document.getElementById) return false;
    if(!document.createElement) return false;
    if(!document.createTextNode) return false;
    if(!document.getElementById('imagegallery')) return false; // 如果沒有id為imagegallery的元素則返回false
    // 創建一個img元素
    var placeholder = document.createElement('img');
    placeholder.setAttribute('id', 'placeholder');
    placeholder.setAttribute('src', 'images/placeholder.gif');
    placeholder.setAttribute('alt', 'my image gallery');
    // 創建一個p元素用於描述圖片
    var description = document.createElement('p');
    description.setAttribute('id', 'description');
    // 為p元素創建文本子節點
    var desctext = document.createTextNode('Choose an image');
    description.appendChild(desctext);
    var gallery = document.getElementById('imagegallery'); // 獲得id為imagegallery的元素
    insertAfter(description, gallery); // 將descrip插入到gallery後面
    insertAfter(placeholder, description); // 將placeholder插入到description後面
}

function prepareGallery() { // 準備gallery
    if(!document.getElementsByTagName) return false;
    if(!document.getElementById) return false;
    if(!document.getElementById('imagegallery')) return false;
    var gallery = document.getElementById('imagegallery'); // 獲得id為imagegallery的元素
    var links = gallery.getElementsByTagName('a'); // 獲得所有的鏈接
    for(var i = 0; i < links.length; ++i) { // 遍歷每個鏈接
        links[i].onclick = function() { // 為每個鏈接的click事件綁定響應函數
            showPic(this); // 在placeholder中顯示圖片
            return false; // 返回false防止頁面跳轉
        }
    }
}

function stripeTables() { // 使表格產生間隔效果
    if(!document.getElementsByTagName) return false;
    var tables = document.getElementsByTagName('table'); // 獲得所有的table元素
    for(var i = 0; i < tables.length; ++i) { // 遍歷每個table
        var rows = tables[i].getElementsByTagName('tr'); // 獲得第i個table的所有行(tr)
        for(var j = 0; j < rows.length; ++j) { // 遍歷每行(tr)
            if(1 == j % 2) { // 如果行數為奇數,則
                addClass(rows[j], 'odd'); // 為該行的類屬性添加odd類
            }
        }
    }
}

function highlightRows() { // 高亮表格當前鼠標懸停的行
    if(!document.getElementsByTagName) return false;
    var rows = document.getElementsByTagName('tr'); // 獲得網頁中的所有tr元素
    for(var i = 0; i < rows.length; ++i) { // 遍歷所有tr元素
        rows[i].oldClassName = rows[i].className; // 為tr元素添加新的屬性以保存當前的className
        rows[i].onmouseover = function() { // 為tr元素的mouseover事件添加響應函數
            addClass(this, 'highlight'); // 為該行添加類highlight
        }
        rows[i].onmouseout = function() { // 為tr元素的mouseout事件添加響應函數
            this.className = this.oldClassName; // 將className屬性設置為高亮之前的值oldClassName
        }
    }
}

function displayAbbreviations() { // 顯示縮寫
    if(!document.getElementsByTagName || !document.createElement || !document.createTextNode) return false;
    var abbreviations = document.getElementsByTagName('abbr'); // 獲得所有的abbr元素
    if(abbreviations.length < 1) return false; // 如果沒有abbr元素則返回false
    var defs = new Array(); // 創建一個[key,definitin]鍵值數組(字典)
    for(var i = 0; i < abbreviations.length; ++i) { // 遍歷所有的abbr元素
        var current_abbr = abbreviations[i]; // 獲得當前abbr元素
        if(current_abbr.childNodes.length < 1) continue; // 如果當前abbr元素沒有子元素(通常指沒有含縮寫文本的文本子節點),則返回false
        var definition = current_abbr.getAttribute('title'); // 將當前abbr元素的title值賦給變量definition
        var key = current_abbr.lastChild.nodeValue; // 獲得縮寫文本(通常abbr元素隻有一個文本子節點)
        defs[key] = definition; // 存儲鍵值對
    }
    var dlist = document.createElement('dl'); // 創建元素dl(description list)
    for(key in defs) { // 遍歷[key,definition]鍵值對數組
        var definition = defs[key]; // 將縮寫key對應的全稱賦給definition
        var dtitle = document.createElement('dt'); // 創建元素dt(description title)
        var dtitle_text = document.createTextNode(key); //創建內容為縮寫文本key的文本節點
        dtitle.appendChild(dtitle_text); // 將文本節點dtitle_text追加為dtitle元素的子節點
        var ddesc = document.createElement('dd'); // 創建元素dd(description description)
        var ddesc_text = document.createTextNode(definition); // 創建內容為全稱definition的文本節點
        ddesc.appendChild(ddesc_text); // 將文本節點ddesc_text追加為ddesc的子節點
        dlist.appendChild(dtitle); // 將描述標題元素dtitle追加為描述列表元素dlist的子節點
        dlist.appendChild(ddesc); // 將描述定義元素ddesc追加為描述列表元素dlist的子節點
    }
    if(dlist.childNodes.length < 1) return false; // 如果描述列表為空,則返回false
    var header = document.createElement('h3'); // 為描述列表創建一個標題元素h3
    var header_text = document.createTextNode('Abbreviations'); // 創建文本節點
    header.appendChild(header_text); // 將文本節點header_text追加為3級標題節點header的子元素
    var articles = document.getElementsByTagName('article'); // 獲得所有的article元素
    if(0 == articles.length) return false; // 如果沒有article元素,則返回false
    var container = articles[0]; // 獲得第一個article元素
    // 將header和dlist追加為articles[0]的子節點
    container.appendChild(header);
    container.appendChild(dlist);
}

function focusLabels() {
    if(!document.getElementsByTagName) return false;
    var labels = document.getElementsByTagName('label'); // 獲得所有標簽
    for(var i = 0; i < labels.length; ++i) {
        labels[i].onclick = function() { // 為點擊標簽事件綁定響應函數
            var id = this.getAttribute('for'); // 獲得標簽的for屬性
            if(!document.getElementById(id)) return false; // 如果標簽沒有綁定任何表單,則返回false,否則
            var element = document.getElementById(id); // 取得該表單對象
            element.focus(); // 是標簽對應的表單獲得焦點
        }
    }
}

function resetFields(whichForm) { // 表單驗證: 獲得和失去焦點的處理函數、設置表單占位符
    if(Modernizr.input.placeholder) return; // 如果input表單支持placeholder屬性,則返回
    for(var i = 0; i < whichForm.elments.length; ++i) { // 遍歷所有表單元素
        var element = whichForm.elments[i]; // 獲得第i個表單元素
        if(element.type == 'submit') continue; // 如果是提交按鈕則跳過
        var check = element.placeholder || element.getAttribute('placeholder'); // 獲得placeholder屬性的值(占位符)
        if(!check) continue; // 如果placeholder屬性值為空(無占位符),則跳過
        element.onfocus = function() { // 為獲得焦點事件添加響應函數
            var text = this.placeholder || this.getAttribute('placeholder'); // 獲得placeholder屬性的值(占位符)
            if(this.value == text) { // 如果當前表單內容為placeholder屬性的值(表明之前用戶未輸入任何內容),則
                this.className = ''; // 將類名設為空
                this.value = ''; // 將表單內容設為空
            }
        }
        element.onblur = function() { // 為失去焦點添加響應函數
            if(this.value == '') { // 如果當前表單內容為空,則
                this.className = 'placeholder'; // 將表單的類名設置為placeholder(占位符)
                this.value = this.placeholder || this.getAttribute('placeholder'); // 將表單內容設置為placeholder屬性的值(占位符)
            }
        }
        element.onblur(); // 為每個表單元素執行一次onblur方法
    }
}

function prepareForms() { // 準備表單
    for(var i = 0; i < document.forms.length; ++i) { // 遍歷每一個表單元素
        var thisform = document.forms[i];
        //resetFields(thisform); // 調用上面的resetFields,HTML5不需要調用此函數
        thisform.onsubmit = function() { // 為onsubmit事件添加響應函數
            //if(!validateForm(this)) return false; // HTML5不需要調用此函數
            var article = document.getElementsByTagName('article')[0]; // 獲得article元素
            if(submitFormWithAjax(this, article)) return false; // 提交成功返回false防止頁面跳轉,
            return true; // 否則跳轉頁面
        }
    }
}

function isFilled(field) { // HTML5不需要此函數
    if(field.value.replace(' ','').length == 0) return false; // 如果去掉所有空格後,內容長度為0則返回false
    var placeholder = field.palceholder || field.getAttribute('placeholder'); // 獲得placeholder屬性值
    return (field.value != placeholder); // 如果表已被修改則返回true,否則返回false
}

function isEmail(field) { // HTML5不需要此函數
    return (field.value.indexOf('@') != -1 && field.value.indexOf('.') != 1); // 如果串中有@和.符號則返回true,否則返回false(簡單但不完全可靠的驗證方式)
}

function validateForm(whichform) { // HTML5不需要此函數
    for(var i = 0; i < whichform.elements.length; ++i) {
        var element = whichform.elements[i];
        if(element.required == 'required') {
            if(!isFilled(element)) { // 如果必填表單未填寫,則提示用戶填寫
                alert('Please fill in the ' + element.name + ' field');
                return false;
            }
        }
        if(element.type == 'email') {
            if(!isEmail(element)) { // 如果表單為email,如果格式是不正確,則提示用戶修改
                alert('The ' + element.name + ' field must be a valid email address');
                return false;
            }
        }
    }
    return true; // 所有表單內容都符合要求,則返回true
}

function getHTTPObject() { // HTML5不需要此函數
    if(typeof XMLHttpRequest == 'undefined') {
        try {
            return new ActiveXObject('Msxml2.XMLHTTP.6.0');
        }
        catch(e) {}

        try {
            return new ActiveXObject('Msxml2.XMLHTTP.3.0');
        }
        catch(e) {}

        try {
            return new ActiveXObject('Msxml2.XMLHTTP');
        }
        catch(e) {}

        return false;
    }
    return new XMLHttpRequest();
}

function displayAjaxLoading(element) { // 顯示加載動畫
    while(element.hasChildNodes()) {
        element.removeChild(element.lastChild);
    }
    var content = document.createElement('img');
    content.setAttribute('src', 'images/loading.gif');
    content.setAttribute('alt', 'Loading...');
    element.appendChild(content);
}

function submitFormWithAjax(whichform, thetarget) { // 使用Ajax提交表單
    //var request = getHTTPObject();
    // IE9以後的IE瀏覽器和其它如chrome、firefox等瀏覽器都已經內置瞭XMLHttpRequest對象,直接new XMLHttpRequest()就可以返回一個XMLHttpRequest對象,而不需要自己寫函數
    //if(!request) { return false; }
    var request = new XMLHttpRequest(); // 獲得xmlhttp對象實例
    displayAjaxLoading(thetarget); 

    // 對表單元素進行編碼
    var dataParts = [];
    var element;
    for(var i = 0; i < whichform.elements.length; ++i) { // 遍歷所有表單
        element = whichform.elements[i]; // 獲得第i個表單
        dataParts[i] = element.name + '=' + encodeURIComponent(element.value); // 提取表單數據
    }
    var data = dataParts.join('&'); // 將表單數據用符號&連接起來

    request.open('POST', whichform.getAttribute('action'), true ); // 以POST方式異步發送數據
    request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); // 設置請求頭
    request.onreadystatechange = function() { // 狀態改變事件的響應函數
        if(request.readyState == 4) { // 如果響應已完成,則
            if(request.status == 200 || request.status == 0) { // 如果請求成功或請求未初始化:
                var matches = request.responseText.match(/
([\s\S]+)<\/article>/); // 使用正則表達式捕獲以
開頭,以
結尾的字符串 if(matches.length > 0) { // 如果捕獲的內容長度大於0,則 thetarget.innerHTML = matches[1]; // 將thetarget的內容設置為捕獲組1的內容 } else { // 否則, thetarget.innerHTML = '
Oops, there was an error. Sorry.

'; // 顯示錯誤信息 } } else { // 否則,顯示當前請求的狀態信息 thetarget.innerHTML = '
' + request.statusText + '

'; } } }; request.send(data); // 發送數據 return true; // 返回true } addLoadEvent(prepareForms); addLoadEvent(focusLabels); addLoadEvent(prepareGallery); addLoadEvent(preparePlaceholder); addLoadEvent(hilightPage); addLoadEvent(prepareSlideshow); addLoadEvent(prepareInternalnav); addLoadEvent(stripeTables); addLoadEvent(highlightRows); addLoadEvent(displayAbbreviations);

發佈留言