一步步教你實現彈出窗口(第1部分)

作者: 司徒正美  來源: 博客園  發布時間: 2009-11-08 15:19  閱讀: 2296 次  推薦: 0   原文鏈接   [收藏]  

  在藍色理想看到一個漂亮的彈出層,不過看不慣其代碼,決定自己重寫一個。漂亮是有代價,它用了許多圖片,而且那是半透明圖片,這在IE6中就遇到麻煩,需要動用IE的DXImageTransform.Microsoft.AlphaImageLoader來實現fixbug!對于我而言,圖片根本是沒有必要,因為我掌握非常先進的動態生成圖片(位圖)的技術,這樣就可以大大減少請求數與圖片對服務器的壓力。但是,該死的IE6不支持這種技術,因此我還是需要一些圖片。至于半透明與圓角與陰影,我是利用vml與canvas與CSS3高級特征來實現。好了,開場白就此打住,我們開始吧。

  通常而言,彈出窗口都是居中對齊的,因此我們需要獲取瀏覽器可視區的大小。這里有一個函數,可以幫我們迅速取得結果。

 
 var getBrowserWindowSize = function(){
      var de = document.documentElement;
      return {
        'width':(
        window.innerWidth
          || (de && de.clientWidth )
          || document.body.clientWidth),
        'height':(
        window.innerHeight
          || (de && de.clientHeight )
          || document.body.clientHeight)
      }
    }

  要創建一個彈出窗口,我們需要一些參數,具體可以參考這里。但作為起步,我們不需要面面俱到,現在只要title,width與height這三個就算了。以下是其主體框架:

 
  var Dialog = function(){
    var options = arguments[0] || {};
    this.title = options.title || "新窗口",
    this.width = options.width || 400,
    this.height = options.height || 300,
    this.contain = document.createElement("div"),
    this.id = "id" + (( new Date() * Math.random()) >> 0);
    this.init();
  }
  Dialog.prototype = {
    constructor: Dialog,
    init: function() {
      //*****************
    }
  }

  UI控件就難免涉及動態設置樣式的問題,通常人們都是這樣做:el.style.cssText = "******************"

  換言之,就是使用內聯樣式。但這樣做有兩個缺點:1,不能使用偽類;2,相同樣式容易重復定義。我的一個腳本雖然也用到cssText,但生成的是內部樣式,完美地避免了這兩個問題。我早期的UI控件都是利用它來設置樣式。不過,如你們所見,它的體積比較龐大,而且一下子設置所有樣式,需要對UI有夠全面的了解,在迭代開發中,恐怕沒有人敢保證他現在寫的樣式就是最后確定用的樣式。因此,我又開發另一套動態設置樣式規則的方法。IE有一個很好用的方法,createStyleSheet,能生成一個樣式表對象。不過有個缺陷,就是一個頁面只能使用31次,再多就只能求助于document.createElement("style")。IE的樣式表對象有兩個重要的方法,分別為addRule與removeRule 。我是不推薦用removeRule方法,同理,任何移除節點的方法能不用就不要用。因為IE7中,引入新的DOM元素的回收機制:在離開頁面時回收DOM樹上的所有元素。換言之,如果所有元素(無論動態創建的還是原來的),只要關閉引頁面時,它們都在DOM樹上,就不會泄漏,否則肯定泄漏。你不要以為當時移除節點后,IE7會即時回收它,對不起,它很懶,因此內存會一直飆升,直到關閉時才得以喘息。回歸正傳,標準瀏覽器肯定沒有這些方法,對應方法都是非常不好用,因此我們讓它們擁有這種IE風格的方法即可。

if(typeof document.createStyleSheet === 'undefined') {
    document.createStyleSheet = (function() {
      function createStyleSheet() {
        var element = document.createElement('style');
        element.type = 'text/css';
        document.getElementsByTagName('head')[0].appendChild(element);
        var sheet = document.styleSheets[document.styleSheets.length - 1];
        if(typeof sheet.addRule === 'undefined')
          sheet.addRule = function(selectorText, cssText, index) {
            if(typeof index === 'undefined')
              index = this.cssRules.length;
            this.insertRule(selectorText + ' {' + cssText + '}', index);
          };
        return sheet;
      }
      return createStyleSheet;
    })();
  }
  然后我們用createStyleSheet創建一個樣式表對象,并把作為Dialog的靜態屬性,
目的讓所有Dialog對象都共享這個對象,因為在IE中,這方法在一個頁面只能使用31次,
能省就省啊!
      if(!!Dialog.sheet){
        Dialog.sheet.addRule(selector,declaration);
      }else{
        Dialog.sheet = document.createStyleSheet();
        Dialog.sheet.addRule(selector,declaration);
      }

  這有點像單例模式,但上面的寫法只能保證創建一個樣式表對象,不能防止兩個完全一樣的樣式規則對象的創建。有關樣式規則對象等概念,請參考我另一篇博文《再談動態添加樣式規則》

  在IE8開發人員工具下,我們可以看到一些樣式規則完全一樣。我的設想是選擇器部分可以重復,但其內容不能重復。因此我們需要設置一個容器來保存與管理這些樣式規則。

  初步開發了這樣一個小東西,類似java的集合,但去掉無關的功能:

 
  var memory = function(){
    var keys = [],values = [],size = 0;
    return {
      get : function(k){
        var results = [];
        for(var i=0,l=keys.length;i

我們把它整合到Dialog類中,這樣就可以防止冗余重復的CSS代碼生成了!

  至此,Dialog類的輔助方法就準備得差不多了,下一部分將正式進行開發。

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()