2009年01月15日

[JavaScript] 如何讓 reset.css 和 HTML 預覽功能並存?

問題描述

現在 CSS 排版技術越來越盛行,很多網頁設計師為更精準地控制頁面呈現效果,都會使用 reset.css 來將 HTML 元素在瀏覽器的預設呈現效果給移除 (例如 YUI 的 reset.css 或 Eric Meyer 的 reset.css ) 。

雖然這個技術很好用,但在需要讓客戶自訂畫面的專案上就會遇到一個問題:如何讓客戶的 HTML 呈現出瀏覽器原本預設的效果?

像 YUI 有提供一個 base.css ,可以稍微幫我們將 HTML 元素回復原本的呈現方式。但我們有時只是需要在畫面上一小部份轉換為原來的效果,這時就勢必得修改 base.css ,在它的各項元素定義前加上某區塊的 class 或 id ;不過這不是一個好選項,因為大多數狀況我們還是沒辦法百分之百讓畫面呈現它原本的樣子。

解決方案

其實用 iframe 就可以幫我們解決這個問題。

步驟很簡單:

  • 建立一個動態 iframe 。
  • 將原本的 html 內容指定給 iframe 的 document 。
  • 把 iframe 高度調整至和 html 內容一般高。

這裡我用 jQuery 來實作囉。

建立一個動態 iframe

假設我們的 html 內容已經放在 div.htmlContent 這個區塊中,我們可以用以下程式來動態建立一個 iframe ,並將它 append 在 div.htmlContent 中。當然也別忘記把原來的內容清掉:

$(function () {
    var $iframe = $('<iframe src="about:blank" width="100%" height="300" frameborder="0"></iframe>');
    var $htmlContent = $('div.htmlContent');
    var html = $htmlContent.html();
    $htmlContent.html('');
    $htmlContent.append($iframe);
}

這裡要注意一點,就是 iframe 的高度一定要設定一個大於 0 的整數值,不然等一下 IE 在自動調整高度時會出問題。 (別問我為什麼...我也是自己試出來的 Orz)

至於 iframe 的來源,我們設定為 about:blank 就好,也就是瀏覽器預設的空白頁。

將原本的 html 內容指定給 iframe 的 document

在建立好動態的 iframe 之後,我們要先等它將內容載完。在載完之後,我們就可以將原來的 html 放到 iframe 裡的 docuement 物件的 body 中。

    $iframe.load(function () {
        var iframeDocument = getIframeDocument($iframe.get(0));
        $(iframeDocument.body).html(html).css({ margin: '0', padding: '0' });
    });

這裡用到了一個自訂函式 getIframeDocument , 它可以幫我們取得 iframe 裡的 document 物件,而且是跨瀏覽器的:

function getIframeDocument(iframeObject) {
    if (iframeObject.contentWindow) {
        return iframeObject.contentWindow.document;
    } else if (iframeObject.contentDocument) {
        return iframeObject.contentDocument.document;
    }
    return null;
}

註:getIframeDocument 暫時不支援 Google Chrome 和 Safari 。

把 iframe 高度調整至和 html 內容一般高

接著我們要調整 iframe 的高度,讓它能完整呈現出 html 的內容。

在 html 載入完畢後,body 的 offsetHeight 就會是我們所需要的內容高度:

    $iframe.load(function () {
        var iframeDocument = $.wacow.getIframeDocument($iframe.get(0));
        $(iframeDocument.body).html(html).css({ margin: '0', padding: '0' });

        setTimeout(function () {
            var bodyHeight = iframeDocument.body.offsetHeight + 20;
            $iframe.height(bodyHeight);
        }, 0);
    });

這裡有個小技巧,就是重新指定 html 內容時, load 事件並不會被觸發,所以我們要利用 setTimeout 來確定 html 已經全部加載完畢 (讓它跳離到另一個執行空間) 。

到這裡就大功告成啦~謝謝收看~



Posted by jaceju at 樂多Roodo! │18:11 │JavaScript
樂多分類:網路/3C 共同主題:Java/JavaScript 工具:編輯本文
Ads by Roodo!