一步步教你实现弹出窗口(第1部分)

蓝色理想看到一个漂亮的弹出层,不过看不惯其代码,决定自己重写一个。漂亮是有代价,它用了许多图片,而且那是半透明图片,这在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<l;i++){
          if(keys[i] == k){
            results.push(values[i])
          }
        }
        return results;
      },
      exists:function(k,v){
        var vs = this.get(k);
        for(var i=0,l=vs.length;i<l;i++){
          if(vs[i] == v){
            return true;
          }
        }
        return false;
      },
      set : function(k,v){
        keys.push(k);
        values.push(v);
        size++;
      },
      length :function(){
        return size;
      }
    }
  }

我们把它整合到Dialog类中,这样就可以防止冗余重复的CSS代码生成了!

至此,Dialog类的辅助方法就准备得差不多了,下一部分将正式进行开发。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值