zoukankan      html  css  js  c++  java
  • 一个 YUI模块,Gallery

    学习一个框架到一定阶段后,如果希望对它有更深入的理解,应该尝试写给它写独立的模块或者插件。

    趁周末写了一个YUI模块:

    1.支持自定义数量的预加载

    2.支持history

    3.支持键盘导航

    参照了人人网的相册,还有百度的图片搜索结果页面。

    人人网的相册功能,体验还是不错的。载入大图的时候速度很快,猜测肯定是预加载了的,现在的网站大规模的使用了ajax功能,url不会刷新,但是内容会变,带来的后果就是,可能失去历史信息,人人的相册对这个也是做了处理的,图片切换url地址会变,那么历史前进后退功能也就没有问题了。而且也是支持鼠标导航的。试下左右方向键。

    类似的效果还有百度的图片搜索结果,有一个很贴心的功能就是点击向下翻页的时候,上一页的最后一个会列在新一页的第一个,这样感觉很好,这个一并copy了

    1.图片预加载

    最简单能想到的就是 

    var img = new Image();

    img.src = imgurl;

    对IE浏览器来说,很好,但是火狐却不能达到预加载的目的。【我自己没有验证,参考了这里 ,因为火狐中的图片有独立的缓存 new Image().src  has a separate cache for images】

    一个兼容的预加载的实现就是

        preloadImage:function(src){
          Y.log('preload:'+src);
          if(Y.UA.ie){
            new Image().src = src;
          }else{
            var d = document,
            b = document.body;
            o = d.createElement('object');
            o.data  = src;
            o.width = o.height = 0;
            b.appendChild(o);
          }
        }
    

    2.历史记录功能

    YUI3 是提供了这样的功能的:当切换一张图片,改变url的hash值,即历史记录添加一个value

     history.addValue("pic",currentIndex || null);
    

    切换图片后,重新刷新页面,或者将本页面的url发送给别人,再次进入这个页面,图片的也是如期望所显示的

            var pic = Number(history.get("pic"));
            if(thumbs.item(pic)){
              gallery.gotoIndex(pic);
            }
    

    3.键盘导航

    键盘导航还是比较简单的,给document添加一个keydown 事件,判断如果按下的是左方向键,那么久显示上一张图片,如果按下的是向右方向键,那么显示下一张图片。按理说,应该也是可以将事件绑定到document.body 上的,发现在出FF以外的浏览器上是OK的,而FF不太灵敏,最终将keydow 事件绑定到了document上。

            var eventType = (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress';
            var handleKeypress = function(e){
              //console.log('keynav',e.keyCode);
              if(e.keyCode === 37 || e.keyCode === 38){
                gallery.prevImage();
              }else if(e.keyCode === 39 || e.keyCode === 40){
                gallery.nextImage();
              }
            }
    

      

    第一个YUI模块还是不够满意,放了好多代码在实例化后,来支持历史记录和键盘导航功能,有空会将这些逻辑放到模块本身中去。上代码了:

    YUI.add('k2-gallery', function(Y) {
    
      var Lang = Y.Lang,
          EVENT_FORWARD = "forward",
          EVENT_BACKWARD = "backward",
          EVENT_CHANGE = "change";
    
    
      var DefaultConfig = {
        preloadNumber:10,
        autostart:true,
        playPause:'#play-pause',
        imgContainer:'#img-con',
        imgEl:'#img-el',
        prev:'#prev',
        next:'#next',
        autoPlay:false,
        direction:'forward',
        loading:'#k2-gallery-loading',
        bigImage:{"selector":'li>a','data-src':'href','data-alt':'title'},
        smallImage:{"selector":'li>a>img','data-src':'src','data-alt':'alt'},
        //一批小图个数
        batchSize:5
    
      };
      function KGallery(imgList,config) {
        Y.log("imgList id:"+imgList);
        //图片源
        this.imageList = Lang.isObject(imgList) ? imgList : Y.one(imgList);
        if(!this.imageList) return;
    
        this.config = DefaultConfig;
    
        if(Lang.isObject(config))
          this.config = Y.merge(this.config,config);
    
        // Y.log(this.config);
    
        // 图片容器
        this.imgContainer = Y.one(this.config.imgContainer);
        // 图片元素
        this.imgEl = Y.one(this.config.imgEl);
        // next && next trigger
        this.nextEl = Y.one(this.config.next);
        this.prevEl = Y.one(this.config.prev);
    
        this.bindEvent();
    
        KGallery.superclass.constructor.call(this);
    
      }
    
      KGallery.NAME = 'k2-gallery';
      /*
       * The attributes this extension provides
       */
      KGallery.ATTRS = {
      };
    
      Y.extend(KGallery,Y.Base,{
        init:function(){
          var self = this;
          Y.log(this.config);
          this.allImages = [];
          this.getAllImages();
    
          //Y.log(this.allImages.toString());
          if(this.allImages.length > 0)
            this.currentImage = this.allImages[0];
    
          Y.log("currentImage:"+this.currentImage.toString());
          this.preloadImages();
          this.currentIndex = 0;
          this.showCurrentImage();
    
          return this;
        },
        bindEvent:function(){
          if(this.nextEl)
            this.nextEl.on("click",this.nextImage,this);
          if(this.prevEl)
          this.prevEl.on("click",this.prevImage,this);
    
        },
        getAllImages:function(){
          var self = this;
          var bigImages,smallImages;
          bigImages = this.imageList.all(this.config.bigImage.selector);
    
          bigImages.each(function(v,index){
            if(!self.allImages[index])
              self.allImages[index] = {};
            var obj = self.allImages[index];
    
            obj.bigSrc = v.getAttribute(self.config.bigImage['data-src']);
            obj.bigAlt = v.getAttribute(self.config.bigImage['data-alt']);
    
          });
          if(this.config.smallImage.selector){
            smallImages = this.imageList.all(this.config.smallImage.selector);
            smallImages.each(function(v,index){
              if(!self.allImages[index])
                self.allImages[index] = {};
              var obj = self.allImages[index];
    
              obj.smallSrc = v.getAttribute(self.config.smallImage['data-src']);
              obj.smallAlt = v.getAttribute(self.config.smallImage['data-alt']);
            });
          };
    
          //console.log(self.allImages.toString());
    
        },
        preloadImages:function(){
          var currentImage = this.currentImage,
              index = this.currentIndex,
              images = this.allImages.slice(index,index+this.config.preloadNumber),
              len = images.length,
              preloadedFlag = false,
              self = this;
          // Y.log("preload images:"+images.toString());
          Y.each(images,function(v){
            if(!v.preloaded){
              preloadedFlag = true;
              //Y.log("DOES NOT LOADED:"+v.toString());
              self.preloadImage(v.bigSrc);
            }
          });
    
          preloadedFlag && this.updatePreloadStatus(index,len);
        },
        updatePreloadStatus:function(index,len){
          var item;
          while(len > 0){
            item = this.allImages[index+len-1];
            if(item){
              item.preloaded = true;
              //Y.log("item:"+item.toString());
            }
            --len;
          }
        },
        preloadImage:function(src){
          Y.log('preload:'+src);
          if(Y.UA.ie){
            new Image().src = src;
          }else{
            var d = document,
            b = document.body;
            o = d.createElement('object');
            o.data  = src;
            o.width = o.height = 0;
            b.appendChild(o);
          }
        },
        autoplay:function(){
          var playFn ;
          if(this.config.direction === 'backward')
            playFn = this.next;
          else
            playFn = this.prev;
    
          if(this.config.autoPlay)
            this.autoPlayTimer = setTimeout(arguments.callee,this.config.duration);
          else
            playFn();
        },
        gotoIndex:function(index){
          var allImage = this.allImages;
          if(index<0){
            index = allImage.length -1;
          }else if(index>allImage.length-1){
            index = 0;
          }
          this.currentIndex = index;
          this.currentImage = allImage[index];
          //console.log("current image",this.currentImage);
          this.showCurrentImage();
          this.fire(EVENT_CHANGE,{currentImage:this.currentImage,index:this.currentIndex});
        },
        nextImage:function(){
          // var allImg = this.allImages;
          // var index = Y.Array.indexOf(allImg,this.currentImage);
          this.gotoIndex(this.currentIndex+1);
        },
        prevImage:function(){
          // var allImg = this.allImages;
          // var index = Y.Array.indexOf(allImg,this.currentImage);
          this.gotoIndex(this.currentIndex-1);
        },
        next:function(){
          Y.log("show next image... ");
          this.setNextImage();
          this.showCurrentImage();
    
          this.fire(EVENT_FORWARD,{currentImage:this.currentImage});
          this.fire(EVENT_CHANGE,{currentImage:this.currentImage,index:this.currentI});
    
          if(this.config.autoPlay){
            this.setAutoplayDirection("forward");
            if(!this.autoPlayTimer)
              this.autoPlay();
          }
          this.preloadImages();
        },
        prev:function(){
          this.setPrevImage();
          this.showCurrentImage();
          if(this.config.autoPlay){
            this.setAutoplayDirection("backward");
            if(!this.autoPlayTimer)
              this.autoPlay();
          }
          this.preloadImages();
        },
        setAutoPlay:function(b){
          this.config.autoPlay = !!b;
        },
        setAutoplayDirection:function(d){
          this.config.direction = b;
        },
        showCurrentImage:function(){
          var imgContainer = this.imgContainer,
              imgEl = this.imgEl,
              imgData = this.currentImage;
          if(imgData){
            imgEl.setAttribute("src",imgData.bigSrc);
            imgEl.setAttribute("alt",imgData.bigAlt);
          }
          this.preloadImages();
    
          /*
          var animOut = new Y.Anim({
            node:node,
            to:{
    
            }
          });
           */
    
    
        },
        /*
         * @param:index
         * @param:offset*/
        getNextBatch:function(index,offset){
          if(offset>this.allImages.length){
            return this.allImages;
          }else{
            var arr = this.allImages.slice(index,offset);
            if(arr.length < offset)
              arr.push(this.allImages.slice(0,offset - arr.length));
            return arr;
          }
        },
        _hideEffect:function(){
    
        },
        _showEffect:function(){}
      });
    
    
      Y.KGallery = KGallery;
    
    
    },'1-1-0',{requires:['node-base','oop','base-base']});
    

      

  • 相关阅读:
    贪心-poj-3040-Allowance
    [置顶] .net技术类面试、笔试题汇总3
    数据对接—kettle使用之二
    做好先期工作,才能有效沟通
    cc++复习基础要点08--c++单例模式
    android 限制adb的访问目录
    我奋斗18年,和你或者咖啡没有任何关系
    (3)选择元素——(15)总结(Summary)
    (3)选择元素——(16)延伸阅读(Further reading)
    网络协议复习
  • 原文地址:https://www.cnblogs.com/wewe/p/2255509.html
Copyright © 2011-2022 走看看