天天看點

使用Popup視窗建立無限級Web頁菜單(5)

使用Popup視窗建立無限級Web頁菜單(5)

    為了比較直覺的說明代碼的作用,我就從菜單的顯示開始說。要顯示一個菜單顯必須建構一個菜單的執行個體,執行個體建構的完整代碼如下:

使用Popup視窗建立無限級Web頁菜單(5)

<div oncontextmenu="return ShowContextMenu(this);" style="width: 200; height: 200; border: solid 1px blue;">

使用Popup視窗建立無限級Web頁菜單(5)

    <table width="100%" height="100%" border="0">

使用Popup視窗建立無限級Web頁菜單(5)

         <tr>

使用Popup視窗建立無限級Web頁菜單(5)

             <td valign="middle" align="center">

使用Popup視窗建立無限級Web頁菜單(5)

                  right click me

使用Popup視窗建立無限級Web頁菜單(5)

             </td>

使用Popup視窗建立無限級Web頁菜單(5)

         </tr>

使用Popup視窗建立無限級Web頁菜單(5)

    </table>

使用Popup視窗建立無限級Web頁菜單(5)

</div>

使用Popup視窗建立無限級Web頁菜單(5)

<script language="javascript">

使用Popup視窗建立無限級Web頁菜單(5)

function ShowContextMenu(elmt)

使用Popup視窗建立無限級Web頁菜單(5)

{

使用Popup視窗建立無限級Web頁菜單(5)

    if ( !elmt.contextMenu )

使用Popup視窗建立無限級Web頁菜單(5)

    {

使用Popup視窗建立無限級Web頁菜單(5)

         elmt.contextMenu = CreateContextMenu();

使用Popup視窗建立無限級Web頁菜單(5)

    }

使用Popup視窗建立無限級Web頁菜單(5)

    var win = window; 

使用Popup視窗建立無限級Web頁菜單(5)

    elmt.contextMenu.Show(win);

使用Popup視窗建立無限級Web頁菜單(5)

    return false; 

使用Popup視窗建立無限級Web頁菜單(5)

}

使用Popup視窗建立無限級Web頁菜單(5)

CreateMenu

生成的Context Menu效果

    這是完全手工添加菜單條目生成的一個Context Menu,最後會完成一個自動解析菜單資料來生成菜單的方法。

    我們現在來看這個Menu.prototype.Show(win)方法,這是菜單的第一級顯示時的方法,它是由使用者來調用的,因為菜單需要定位于使用者給定位置(ContextMenu的使用者給定位置就是滑鼠點選的位置)。在菜單顯示出第一級後,後續的子菜單的顯示,都是在Menu類内部來處理的,子菜機關置是相對于parent

menu,後續邏輯就都封裝在Menu類内部了。Show()方法代碼如下:

使用Popup視窗建立無限級Web頁菜單(5)

Menu.prototype.Show = function(win)

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

    if ( !win )

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

        return;

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

    var menuObj = this;

使用Popup視窗建立無限級Web頁菜單(5)

    menuObj.m_Opener = win;

使用Popup視窗建立無限級Web頁菜單(5)

    menuObj.__resumeItem();

使用Popup視窗建立無限級Web頁菜單(5)

    var win = menuObj.m_Opener;

使用Popup視窗建立無限級Web頁菜單(5)

    var popup, popwin, popdoc;

使用Popup視窗建立無限級Web頁菜單(5)

    // 判斷菜單的容器popup是否建立

使用Popup視窗建立無限級Web頁菜單(5)

    if ( !menuObj.m_Popup )

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

        popup = win.createPopup();

使用Popup視窗建立無限級Web頁菜單(5)

        popup.document.body.bgColor = 'windowtext';

使用Popup視窗建立無限級Web頁菜單(5)

        popup.document.body.style.backgroundColor = 'window';

使用Popup視窗建立無限級Web頁菜單(5)

        menuObj.m_Popup = popup;

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

    else

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

        popup = menuObj.m_Popup;

使用Popup視窗建立無限級Web頁菜單(5)

        menuObj.__resumeAll();

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

    popdoc = popup.document;

使用Popup視窗建立無限級Web頁菜單(5)

    popwin = popdoc.parentWindow;

使用Popup視窗建立無限級Web頁菜單(5)

    // 判斷是否需要重繪菜單的内容

使用Popup視窗建立無限級Web頁菜單(5)

    if ( menuObj.m_Invalidate || !menuObj.m_Drawn )

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

        popdoc.body.innerHTML = menuObj.Render().outerHTML;

使用Popup視窗建立無限級Web頁菜單(5)

        // popdoc.body.appendChild(menuObj.Render());

使用Popup視窗建立無限級Web頁菜單(5)

        menuObj.m_Invalidate = false;

使用Popup視窗建立無限級Web頁菜單(5)

        menuObj.m_Drawn = true;

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

    // 擷取菜單的主table(菜單是使用table來實作的)

使用Popup視窗建立無限級Web頁菜單(5)

    var menuHtml = popup.document.getElementById('menu');

使用Popup視窗建立無限級Web頁菜單(5)

    // 這個show隻是為了測量菜單的bounds而調用的

使用Popup視窗建立無限級Web頁菜單(5)

    popup.show(0, 0, 1, 1);

使用Popup視窗建立無限級Web頁菜單(5)

    var w = popdoc.body.scrollWidth; 

      // 判斷菜單條目的Text的顯示寬度是否在許可範圍内,

      // 如果超出許可範圍則ellipsis處理并傳回新的MenuItem的width

使用Popup視窗建立無限級Web頁菜單(5)

    w = this.__isEllipsis(this, menuHtml);

使用Popup視窗建立無限級Web頁菜單(5)

    var h = popdoc.body.scrollHeight;

使用Popup視窗建立無限級Web頁菜單(5)

    var x = win.event.clientX + win.screenLeft;

使用Popup視窗建立無限級Web頁菜單(5)

    var y = win.event.clientY + win.screenTop;

使用Popup視窗建立無限級Web頁菜單(5)

    popup.show(x, y, w, h); 

      // 菜單的顯示特效,使用filter實作的

使用Popup視窗建立無限級Web頁菜單(5)

    this.FadeinEffect(Menu.Attributes.ShowMenuEffect);

使用Popup視窗建立無限級Web頁菜單(5)

    menuObj.m_Bounds = 

使用Popup視窗建立無限級Web頁菜單(5)
使用Popup視窗建立無限級Web頁菜單(5)

        top: x, left: y,

使用Popup視窗建立無限級Web頁菜單(5)

        width: menuHtml.offsetWidth,

使用Popup視窗建立無限級Web頁菜單(5)

        height: menuHtml.offsetHeight

使用Popup視窗建立無限級Web頁菜單(5)

    }; 

      // 把菜單操作的事件attach到菜單上,滑鼠和鍵盤操作等

使用Popup視窗建立無限級Web頁菜單(5)

    menuObj.AttachEvents(menuHtml);

使用Popup視窗建立無限級Web頁菜單(5)

};

上面注解應該都比較清楚了,隻是這個popup.show(0, 0, 1,

1);比較有意思哈,當我們向popup裡添加好了菜單的HTML元素後,我們發現在popup沒有顯示過之前,是根本取不到構成Menu

UI的那個Table

element的bounds資訊的。這裡show上一下後,就是為了讓IE算出其bounds資訊,然後再使用實際的bounds資訊show菜單。這算一個小hack吧,也是這個Menu中比較有效率的地方,因為除了這個show(0,

0, 1,1)就在沒有計算菜單bounds的地方了,當然也用不着了。然而為什麼又沒有把bounds計算也做成lazy

load象popup的生成那樣呢?是因為使用者可能在菜單顯示後修改IE的字型大小(比如按住Ctrl再滾動滑鼠滾輪),這樣保證了再次顯示菜單時能修正菜單的實際bounds。而後面把menu的bounds存了起來是為了在顯示子菜單時,友善判斷其預設向右展開空間是否足夠,如果不夠寬則從parent

menu左側展開。 

本文轉自部落格園鳥食軒的部落格,原文連結:http://www.cnblogs.com/birdshome/,如需轉載請自行聯系原部落客。 

繼續閱讀