黃忠成

風雪之閣- i live,so i writing
文章數 - 133, 回應數 - 126, 引用數 - 0


關於我:



黃忠成

  • 資深.NET 技術顧問
  • Run! PC 雜誌專欄作者
  • 程序員雜誌文章作者
  • PC Magazine 雜誌專欄作者
  • MSDN 專欄作者
  • MSDN 特約專屬講師
  • Microsoft .NET專屬講師
  • 台灣微軟特約技術顧問
  • 台灣微軟最有價值專家


  • 批評,指教,鼓勵, 請 寫信給我
    轉載文章請使用連結模式,
    請勿整篇Copy! 謝謝!


    我所提供的教育訓練:

    Windows Forms
    ASP.NET 2.0
    如有課程需要,請與我聯絡!

  • 我的著作:

  • 文章標籤

    全部標籤

    每月文章

    文章分類

    [IE8] Internet Explorer 8 中的JavaScript

     

    Internet Explorer 8 中的JavaScript
     
     
    /黃忠成
     
     
    本文主題涵蓋
     
    1.           開發者工具-JavaScript Debugger
    2.           開發者工具-JavaScript Profiler
    3.           JavaScript Language Changes of IE 8
    4.           JavaScript偵測IE 版本
    5.           CSS偵測IE版本
    6.           Query Selector API
    7.           postMessage API
     
     
    開發者工具及JavaScript Debugger
     
     
         Internet Explorer 8中,最具亮點的幾個特色就是開發者工具、三大新功能(Web SliceAcceleratorSearch Provider)兩個,其中三大新功能的部份,
    Microsoft網站及許多Blog都已著墨許多,因此本文就不談這個,未來在此系列文章內,預計將由實際案例應用來介紹她們。
     
       對於許多程式設計師及網頁設計師而言,開發者工具的誕生是令人興奮的,其對JavaScript的除錯支援,對CSS的解析能力,皆是大家夢寐以求的。
    要測試IE 8中對JavaScript除錯能力很簡單,只要開啟任一使用JavaScript的網頁,按下F12啟動開發者工具,即可在指令碼頁籤中於想要停下的JavaScript
    程式碼行設定中斷點(F9是設定中斷點的快速鍵),然後按下【開始偵錯】開始進行除錯。
     
    1
     
     
     
       開始時,由於某些JavaScript需要特定的動作觸發才會執行,而有些則是已經執行過了,所以大多數情況,在你按下【開始偵錯】按紐後不會有任何反應,
    這時你可以回到IE 8的瀏覽頁面,按下【F5】來重新載入網頁,此時如果中斷點所在的位置是載入網頁時會執行到的行,那麼開發者工具就會跳出來。
    MSDN首頁來說,我們所設定的中斷點處__doPostBack函式會在切換語言時觸發,因此這裡我們只要切換一下語言,開發者工具就會在__doPostBack
    函式處停下。
     
    2
     
     當停下後,你可以用F10來【逐程序執行】,也就是Step Over模式,在這個模式下不會追入函式內部,也就是說當呼叫函式時,直接執行並往下一行走,
    按下F11則是【逐步執行】,也就是Step Into式,這種模式會追入函式內部,也就是說當呼叫函式時,直接跳入該函式的程式碼逐步執行。 
        在右方區塊中,你可以觀察主控台頁籤,這裡通常會出現一些訊息,例如【程式碼錯誤】、或由程式以console.logconsole.info等函式所輸出的資訊。
    中斷點頁籤則可以觀察到目前所設定的所有中斷點資訊。
     
    3
     
    區域變數頁籤可觀察到目前此函式所使用的區域變數及值。
     
    4
     
      
      這些變數的值會在F10F11時即時更新,所以如果你想觀察的變數是區域變數的話,就直接於此頁籤中觀察即可,不需設定監看式。特別注意的是,
    開發者工具允許你在除錯時期改變特定變數的值。
      例如在此例中,我們原本選擇的是【簡體中文】語系,但在中斷點停下時,可以透過區域變數頁籤將變eventTarget的值改變(簡體中文是ctl10結尾,
    此例改為ctl11結尾),那麼實際執行時,切換的語系也會因為eventTarget的變數值改變而跟著改變,這是開發者工具除錯JavaScript時相當犀利的優點,
    可以運用此技巧來測試後端網頁的安全防堵是否完善
     
    監看式頁籤中允許我們手動鍵入變數名稱,與區域變數頁籤內一樣,這些變數值會在F10F11時即時更新。
    5
     
    當監看的變數為物件型態時,可展開查看內部結構。
     
    6
     
    監看式通常用來觀察全域變數值,有些情況下我們也會在監看式中監看區域變數值,這常發生在不想在區域變數、監看式間切來切去的時候。
    呼叫堆疊頁籤則是開發者工具另一讓人讚賞的功能,於此頁籤會列示到達目前中斷點前的呼叫歷程,以本例而言如圖7
     
    7
     
     
    點擊第二個項目就會跳到該程式碼處,這是呼叫__doPostBack函式的程式碼。
     
    8
     
    眼尖的話會發現,【停止偵錯】右方的按紐內容有所改變,是的!開發者工具不僅可以除錯網頁中的
    inline JavaScript,同時連帶的也可除錯以<script src..>引入的JavaScript程式檔。
     
    9
     
    附帶一提,如果要略過此中斷點往後執行,按下F5即可,假如後面還有其它中斷點被執行到、或是此中斷點再次被執行到時,開發者工具會再次停下。
    開發者工具所提供的JavaScript支援很棒,但其它功能也不錯,之後的文章會再針對其CSSHTML解部份介紹。
     
    JavaScript Profiler
     
     開發者工具還提供了JavaScript Profiler的能力,也就是由特定點開始到特定點結束期間,所有JavaScript函式的執行時間,與偵錯能力相同,
    不僅可偵測網頁中的inline JavaScript,連帶著引入的JavaScript程式檔都一併偵測,程式1是用來測試此功能的範例網頁。
     
    程式1
    TestProfiler.htm
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <script language="javascript" type="text/javascript">
            function DoFirst() {
                for (val = 0; val < 10000; val++) {
                    document.getElementById("test");
                }
            }
            function DoSecond() {
                for (val = 0; val < 30000; val++) {
                    document.getElementById("test");
                }
            }
        </script>
    </head>
    <body>
        <input id="test" type="button" value="Run" onclick="DoFirst();DoSecond();alert('ok');" />
    </body>
    </html>
     
    開啟此網頁後,以F12啟動開發者工具,切到【分析者工具】頁籤,按下【開始設定資料】按紐,告知開發者工具由現在這個點開始偵測。
     
    圖10
     
     
      在按下【開始設定資料】按紐後,該按紐會變成【結束設定資料】,稍後進行完觸發JavaScript動作後,即可再按下此按紐來結束偵測,此時會列出所有的偵測所得資訊,
    現在請按下網頁上的【Run按紐,待跳出訊息框後再按下【結束設定資料】按紐。
    11
    12
     
     
     
     
    JavaScript Language Changes of IE 8
     
       Internet Explorer 8中,添加了許多新的JavaScript函式,這些會在本文後面進行介紹,在這之前,我們先看看Internet Explorer 8中,一個關於getElementById函式的變動,
    這個函式在IE 7前對於傳入的id參數值是不分大小寫的,在IE 8時,各位要注意到此函式開始區分大小寫了,以程式2的例子來說。
     
    程式2
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>   
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
       
            <div id="T1">TEST</div>
            <input type="button" id="btn1" value="test" onclick="document.getElementById('t1').innerHTML='<br>TEST HTML</b><div><p>Test1</p></div>';" />
        </div>
        </form>
    </body>
    </html>
    IE 7時,此網頁可正常執行無誤,那是因為getElementById不分大小寫的緣故,所以不管用t1或是T1都可以正確執行。但在IE 8時,就得注意了,t1 != T1
    分辨大小寫的特性會讓此網頁產生錯誤。
     
     
    透過JavaScript判定IE版本
     
       這很簡單,程式3是一個例子。
     
    程式3
    DetectIEVersion_Short.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="DetectIEVersion_Short.aspx.cs" Inherits="DetectIEVersion_Short" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
        <script language="javascript">
            var isIE8 = navigator.userAgent.indexOf("MSIE 8");
            if (isIE8 > 0)
                alert("in IE8");
            else
                alert("not in IE8");
        </script>   
        </div>
        </form>
    </body>
    </html>
     
     
     
    不過這是偷懶版,官方希望我們使用程式4的較長、較精確的寫法。
     
    程式4
    DetectIEVersion.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="DetectIEVersion.aspx.cs" Inherits="DetectIEVersion" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
        <script language="javascript">
            function getInternetExplorerVersion()
            {
                var rv = -1; // Return value assumes failure.
                if (navigator.appName == 'Microsoft Internet Explorer') {
                    var ua = navigator.userAgent;
                    var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
                    if (re.exec(ua) != null)
                        rv = parseFloat(RegExp.$1);
                }
                return rv;
            }
            function checkVersion() {
                var msg = "You're not using Windows Internet Explorer.";
                var ver = getInternetExplorerVersion();
                if (ver > -1) {
                    if (ver >= 8.0)
                        msg = "You're using a recent copy of Windows Internet Explorer."
                    else
                        msg = "You should upgrade your copy of Windows Internet Explorer.";
                }
                alert(msg);
            }
            checkVersion();
        </script>
        </div>
        </form>
    </body>
    </html>
     
     
    透過CSS判定IE 版本
     
     除了透過JavaScript判別IE版本外,網頁設計師也常用CSS來判定IE版本並選取對應的CSS,這可以透過程式5的方式完成。
     
    程式5
    Default_IE8_IE7.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default_IE8_IE7.aspx.cs" Inherits="Default_IE8_IE7" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head2" runat="server">
        <title></title>
         <!--[if gte IE 8]>
        <style type="text/css">       
            div
            {
                border: medium dashed #00FF00;
                border: 2px solid #0033CC;
            }
            .container
            {
               min-width:400px;
            }
        </style>
        <![endif]-->
        <!--[if lt IE 8]>
        <style type="text/css">       
            div
            {
                border: medium dashed #00FF00;
                border: 2px solid #009966; /*firefox*/
                *border: 2px solid #0033CC; /*ie7*/
                _border: 2px solid #FF3366; /*ie6或更舊的版本*/
            }
            .container
            {
               min-width:400px;
            }
        </style>
        <![endif]-->
       
    </head>
    <body>
        <form id="form2" runat="server">
        <div>
       
            <div id="t1">TEST</div>
            <input type="button" id="Button1" value="test" onclick="document.getElementById('t1').innerHTML='<br>TEST HTML</b><div><p>Test1</p></div>';" />
        </div>
        </form>
    </body>
    </html>
     
      此例運用了IEifdef判斷式完成,請注意,以往在style前加【*】號的方式不適用於IE 8,也就是說網路上常見的程式6寫法僅適用於判定IE 7
    當使用者使用IE 8時,會出現不同結果。
     
    程式6
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <style type="text/css">
            div
            {
                border: medium dashed #00FF00;
                border: 2px solid #009966; /*firefox*/
                *border: 2px solid #0033CC; /*ie7*/
                _border: 2px solid #FF3366; /*ie6或更舊的版本*/
            }
            .container
            {
               min-width:400px;
            }
        </style>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
       
            <div id="t1">TEST</div>
            <input type="button" id="btn1" value="test" onclick="document.getElementById('t1').innerHTML='<br>TEST HTML</b><div><p>Test1</p></div>';" />
        </div>
        </form>
    </body>
    </html>
     
    Query Selector API
     
     相信大家都有體驗過JQuery的強大選取HTML元素能力,W3C在之前就有製訂了一個關於選取HTML元素的規格,名為【Query Selector API】,
    IE 8中正式的支援此規格,程式7是運用這些API的範例。 
     
    程式7
    UsingQuerySelector.aspx
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml">
    <!--
     http://www.w3.org/TR/css3-selectors/
    -->
    <head>
        <title></title>
        <script language="javascript" type="text/javascript">
            function GetElement() {
                //選取id為div1的Element,只回傳第一個找到的HTML元素
                var div = document.querySelector("#div1");
                div.innerHTML = "Selected";
            }
     
            function GetSingleElement() {
                //選取id為div1或是id為s1的Element,只回傳第一個找到的HTML元素,
                //也就是說找到div1的話就回傳div1,如沒找到,就繼續找id為s1,
                //如找到就回傳s1,否則就回傳null.
                var div = document.querySelector("#div1, #s1");
                div.innerHTML = "Selected";
            }
     
            function GetInnerElement() {
                //選取id為s1內的子div Element,僅回傳第一個找到的子div Element.
                var div = document.querySelector("#s1 div");
                div.innerHTML = "Selected";
            }
     
            function GetElements() {
                //選取id為div1及id為s1的Elements,回傳所有找到的HTML元素,
                //此回傳值為一陣列。
                var divs = document.querySelectorAll("#div1,#s1");
                for (val = 0; val < divs.length; val++)
                    divs[val].innerHTML = "Selected";
            }
     
     
            function GetAllElement() {
                //選取所有span Elements,回傳所有找到的HTML元素,
                //此回傳值為一陣列。
                var spans = document.querySelectorAll("span");
                for (val = 0; val < spans.length; val++)
                    spans[val].innerHTML = "Selected";
            }
     
            function GetAllElementWithClass() {
                //選取所有套用.c1及.c2 style(class)的的Elements,回傳所有找到的HTML元素,
                //此回傳值為一陣列。
                var spans = document.querySelectorAll(".c1, .c2");
                for (val = 0; val < spans.length; val++)
                    spans[val].innerHTML = "Selected";
            }
        </script>
    </head>
    <body>
       <input type="button" value="Select Div" onclick="GetElement()" />
       <input type="button" value="Select First Match Div" onclick="GetSingleElement()" />
       <input type="button" value="Select Match Divs" onclick="GetElements()" />
       <input type="button" value="Select InnerDiv" onclick="GetInnerElement()" />
       <input type="button" value="Select Spans" onclick="GetAllElement()" />
       <input type="button" value="Select Styles" onclick="GetAllElementWithClass()" />
      
       <div id="div1"></div>
      
       <div id="s1">
         S1 Content
         <div>TEST</div>
       </div>
      
       <span></span>
       <span></span>
       <span></span>
      
       <p class="c1"></p>
       <p class="c1"></p>
       <p class="c1"></p>
      
       <p class="c2"></p>
       <p class="c2"></p>
       <p class="c2"></p>
      
    </body>
    </html>
    更多的Query Selector語法可參考http://www.w3.org/TR/css3-selectors/
     
     
    post Message API
     
     以往,如果我們在網頁中內嵌許多IFrame時,常會遇到不知如何讓這些IFrame互通訊息的情況,IE 8提供了一個postMessage函式,外面的頁面可以呼叫此
    函式將訊息送入IFrameIFrame內則可以藉由掛載事件至onmessage來接收訊息,程式8是一個這樣的例子。
     
    程式8
    InnerFrame.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="InnerFrame.aspx.cs" Inherits="InnerFrame" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
          <script language="javascript" type="text/javascript">
              window.attachEvent('onmessage', function(e) {
                  if (e.origin.indexOf('http://localhost') >= 0) {
                      if (e.data == 'Hello World') {
                          document.getElementById("t1").innerHTML = "Got Message";
                      }
                  }
              });
          </script>
          <div id="t1"></div>
        </div>
        </form>
    </body>
    </html>
    OuterFrame.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="OuterFrame.aspx.cs" Inherits="OuterFrame" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
        <script language="javascript" type="text/javascript">
            function sendMessageToFrame(msg) {
                var w = document.getElementById("Frame1").contentWindow;
                w.postMessage(msg,"http://localhost");
            }
        </script>   
        <a href="#" onclick="sendMessageToFrame('Hello World');">Test Link</a>
        </div>
        <iframe src="InnerFrame.aspx" id="Frame1"></iframe>
        </form>
    </body>
    </html>
    postMessage的第二個參數是描述呼叫的Domain(網域),技術上IE 8並不硬性規定postMessage僅能送訊息到同一Domain,不過就安全性而言,
    我們依然要遵守此原則,於onmessage事件中判斷訊息來源,避免不必要的安全漏洞產生。
    13為執行OuterFrame.aspx的情況。
     
    13
    按下Test Link連結時,sendMessageToFrame函式會以postMessage送出訊息到frm1這個IFrame,此時frm1內的InnerFrame.aspx中的onmessage會被觸發,
    而後將此訊息顯示在t1這個div中,圖14是此流程示意圖。
    圖14
     
     本文範例下載

     


    posted on 2009/4/9 22:01 | 2 人收藏 1 人推薦 我要推薦 | 閱讀數 : 7367 | 文章分類 [ IE ] 訂閱

    Feedback

    # re: [IE8] Internet Explorer 8 中的JavaScript 回覆

    請教一下,
    external.AddFavorite(url, title) 在 IE8 無法執行,
    是否 IE8 Javascript 有新的標準?
    2009/7/28 下午 04:03 | hank

    # re: [IE8] Internet Explorer 8 中的JavaScript 回覆

    看來IE 8已不再支援這種做法了....

    2009/8/14 下午 03:58 | code6421

    回應

    標題
    姓名
    電子郵件 (將不會被顯示)
    個人網頁
    內容 
      登入後使用進階評論  
    Please add 7 and 7 and type the answer here:

    Powered by: