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

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

  上部分已給出主要輔助方法css了,有了它我們就可以實現類的實例的樣式共享。另外,我們的類的實現模式是基于prototype,這樣就實現方法共享。現在我們來看看如何渲染它,首先呈上它大體的結構層代碼:

 
<div id="" class="popups" >
  <div class="caption"></div>
  <form>
    <div class="replaceable"></div>
    <div class="submitable">
      <a class="negative" href="javascript:void(0)">取消</a>
      <a class="positive" href="javascript:void(0)">確認</a>
    </div>
  </form>
  <a class="closebtn" href="javascript:void(0)"></a>
</div>

  這結構層代碼比騰訊那個簡單得多了,而且沒用到table來布局,全憑CSS來處理。雖然元素很少,但如果用W3C那一套操作DOM的API來干活,也要十多行。我們不想一味地createElement然后appendChild的話,就要派innerHTML上場了。一個常識是,當DOM超過十個時,就要考察用字符串拼接實現,這樣代碼看起來也直觀一點。我們再來分析一下這結構層。頂層是一個DIV,不用說,它是彈出層,其他東西都直接構筑在它的上面。考察到一個頁面可能存在多個動態生成的彈出窗口,因此我賦給他們一個獨一無二的標識,也就是ID。ID在我的樣式藍圖中沒有用,要實現共享就要用class,我給它一個popups值。接著是標題欄,看上去空蕩蕩,然后它有一個文本節點,與一張背景圖片做icon,還有一個關閉按鈕(我把它放到最底層了class="closebtn")。這里要用絕對定位。然后是一個表單,表單分兩部分,一是替換區(replaceable),為什么這樣叫?因為它視alert,prompt,confirm等功能而重寫。一個是提交區,有兩個按鈕。你們可能奇怪了,為什么不用語義化更強、制定性更好的button標簽來實現呢?這都怪IE6在拖后腿,只有帶href屬性的a標簽才支持hover偽類。之所以用hover偽類,是因為我不想在它們上面多綁定兩個事件(mouseover與mouseout)。而為什么確認按鈕放在取消按鈕之后呢?因為我們稍后要用到向右浮動。整個提交區是位于form的底部的,這個我們可以用bottom:0來實現。

 
 Dialog.prototype = {
    constructor: Dialog,
    init: function() {
      var container = this.container,width = this.width, height = this.height,
      id = this.id,builder = [],
      document.body.insertBefore(container,null);
      container.id = id;
      container.className = "popups";
      builder.push('
'+this.title+'
');
      builder.push('
'); builder.push('
'); builder.push('取消'); builder.push('確認'); builder.push('
');
      builder.push('');
      container.innerHTML = builder.join('');
   }
}

  這樣就創建完成了。我們再來看表現層。要做得好看,得花一些功夫。自已用IE8開發人員工具看生成后的CSS代碼吧。它已經使用到CCS3的圓角特征(這在IE8中看不到)。有的人想去掉按下按鈕時出現的虛線框,這里給出一個簡捷方法:outline:0。

  接著看如何實現圓角與半透明效果與盒陰影。如果不考慮IE與Opera,只需要多添加三行代碼:

 
this.css(".popups","background:rgba(104,223,251,.8)");
this.css(".popups","-moz-border-radius:5px;-moz-box-shadow:10px 10px 5px #c0c0c0;");
this.css(".popups","-webkit-border-radius:5px;-webkit-box-shadow:10px 10px 5px #c0c0c0;");

  不過要實現兼容IE也不難,就是利用VML生成一個圓角矩形,然后利用二級標記fill與shadow輕易實現上述功能。由于VML元素與HTML元素是位于同一個層的,因此我們插入這些VML時肯定會影響原來的文檔流,因此我的彈出層的大多數對象都是定位元素,這樣誰都影響不了誰。標準瀏覽器就有點麻煩了,本來我費了很大勁用canvas實現圓角矩形,但回頭發現它不住陰影fillShadow等方法。于是改用SVG。我們可以比較一下動態生成后VML與SVG的代碼。

 
//利用canvas實現圓角矩形
        var canvas =  document.createElement("canvas");
        container.insertBefore(canvas,null);
        this.attr(canvas,{width:width,height:height,className:"canvas"});
        this.css("#"+this.id +" canvas" ,"position:absolute;");
        if(canvas.getContext) {
          var ctx = canvas.getContext('2d');
          ctx.fillStyle = "rgba(104,223,251,.5)";
          roundedRect(ctx,0, 0, width, height,5);
          ctx.shadowColor = '#00f';
          ctx.shadowOffsetX = 16;
          ctx.shadowOffsetY = 16;
          ctx.shadowBlur = 8;
          ctx.shadowColor = 'rgba(0, 0, 255, 0.25)';
          function roundedRect(ctx,x,y,width,height,radius){
            ctx.beginPath();
            ctx.moveTo(x,y+radius);
            ctx.lineTo(x,y+height-radius);
            ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
            ctx.lineTo(x+width-radius,y+height);
            ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
            ctx.lineTo(x+width,y+radius);
            ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
            ctx.lineTo(x+radius,y);
            ctx.quadraticCurveTo(x,y,x,y+radius);
            ctx.fill();
          }
        }
<vml:roundrect class="vml" style="position: absolute;width:400px;
     height:300px;top:0px;left:0px;">
<vml:fill class="vml" opacity="0.8" color="#68DFFB" />
<vml:shadow class="vml" on="t" color="#333" opacity="0.2"  offset="10px,10px" />
</vml:roundrect>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="410px" height="310px">
<defs>
   <filter id="drop-shadow">
      <feGaussianBlur in="SourceAlpha" result="blur-out" stdDeviation="1.5" />
      <feOffset in="blur-out" result="the-shadow" dx="0" dy="2" />
     <feBlend in="SourceGraphic" in2="the-shadow" mode="normal" />
    </filter>
  </defs>
  <rect x="10px" y="10px" width="400px" height="300px" rx="5"  fill="#333"
        style="opacity:0.2" filter="url(#drop-shadow)"/>
  <rect width="400px" height="300px" rx="5"  fill="#68DFFB" style="opacity:0.8" />
</svg>
 

  接著下來就是綁定事件了,字符串拼接有一個不好處,要獲取剛剛生成的DOM對象的引用比較麻煩。不過我打算利用事件代理就另當別論了,因為我們手頭上最明確的對象就是那個DIV元素,我們把所有事件都綁定在它上面就是了。這個留在下次說。

0
0
 
 
 

文章列表

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

    IT工程師數位筆記本

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