您好,欢迎访问一九零五行业门户网

js模拟滚动条(横向竖向)_javascript技巧

js:
复制代码 代码如下:
(function(win){
    var doc = win.document,db = doc.body;
    var mousewheel = 'onmousewheel' in document ? 'mousewheel' : 'dommousescroll';
    var skyscroll = function(opts){ return new skyscroll.prototype.init(opts);};
    skyscroll.prototype = {
        constructor:skyscroll,
        //初始化
        init:function(opts){
            var set = _extend({
                target:'contentbox',
                dir:'top',
                width:500,
                height:300,
                callback:function(){}
            },opts||{});
            var _this = this,mousemovehandle,mousedownhandle;
            this.target = _$(set.target);
            this.parent = this.target.parentnode;
            this.width = set.width;
            this.height = set.height;
            this.dir = set.dir;
            this.callback = set.callback;
            this.addwarpper(set.dir);
            switch(set.dir){
                case 'top':
                    this.addvscroll();
                    break;
                case 'left':
                    this.addlscroll();
                    break;
                default :
                    this.addvscroll();
                    this.addlscroll();
            };
            _addevent(doc,'mousedown',function(e){
                var e = e || window.event,target = e.target || e.srcelement,pos= _getmousepos(e);
                if(target == _this.vscroll || target == _this.lscroll){
                    pos.ttop = parseint(_this.target.style.top);
                    pos.tleft = parseint(_this.target.style.left);
                    pos.stop = parseint(target.style.top);
                    pos.sleft = parseint(target.style.left);
                    mousemovehandle = _mousemovehandle.call(_this,pos,target);
                    _addevent(doc,'mousemove',mousemovehandle);
                    _addevent(doc,'mouseup',function(){_removeevent(doc,'mousemove',mousemovehandle)});
                };
                if(target == _this.vscrollouter || target == _this.lscrollouter){
                    _mounsedownhandle.call(_this,pos,target);
                };
            });
        },  
        //对外提供重新计算滚动条高度或宽度以及滚动范围的方法,用于动态改变内容时,作出的相对应的调整
        recalculated:function(){
            var h = this.target.offsetheight,w = this.target.offsetwidth,t = parseint(this.target.style.top),l = parseint(this.target.style.left),h,w;
            this.ratio = {l:this.width / w,v:this.height / h};
            this.range = {l:w-this.width, t: h - this.height};
            if(this.vscroll){
                h = math.round(math.pow(this.height,2) / h);
                this.vscroll.style.height = h+'px';
                this.vscroll.style.top = math.round(this.height * (-t/h)) + 'px';
                this.range.st = this.height - h;
                this.wrapper.style.height = this.height + 'px';
            };
            if(this.lscroll){
                w = math.round(math.pow(this.width,2) / w)
                this.lscroll.style.width = w + 'px';
                this.lscroll.style.left = math.round(this.width * (-l/w)) + 'px';
                this.range.sl = this.width - w;
                this.wrapper.style.width = this.width + 'px';
            };
        },
        //对外提供设置滚动条的位置的方法
        set:function(pos){
            if(!_isobject(pos)) throw new error('参数类型错误,参数必须是object!');
            if(pos.top && !isnan(parseint(pos.top)) && this.vscroll){
                var top = math.min(pos.top,this.range.t);
                this.target.style.top = -top + 'px';
                this.vscroll.style.top = math.round(this.height * (top / this.target.offsetheight)) + 'px';
            };
            if(pos.left && !isnan(parseint(pos.left)) && this.lscroll){
                var left = math.min(pos.left,this.range.l);
                this.target.style.left = -left + 'px';
                this.lscroll.style.left = math.round(this.width * (left / this.target.offsetwidth)) + 'px';
            };
        },
        addwarpper:function(dir){
            if(this.wrapper) return;
            var _this = this,w = this.target.offsetwidth,h = this.target.offsetheight,mousewheelhandle;
            this.wrapper = _createel('
',this.parent);
            this.wrapper.appendchild(this.target);
            this.target.style.csstext = 'position:absolute;top:0;left:0';
            switch(dir){
                case 'top':
                    this.wrapper.style.height = this.height + 'px';
                    this.wrapper.style.width = w + 'px';
                    break;
                case 'left':
                    this.wrapper.style.height = h + 'px';
                    this.wrapper.style.width = this.width + 'px';
                    break;
                default :
                    this.wrapper.style.width = this.width + 'px';
                    this.wrapper.style.height = this.height + 'px';
            };
            _addevent(this.wrapper,'mouseenter',function(e){
                var pos = {};
                pos.ttop = parseint(_this.target.style.top);
                pos.tleft = parseint(_this.target.style.left);
                if(_this.vscroll) pos.stop = parseint(_this.vscroll.style.top);
                if(_this.lscroll) pos.sleft = parseint(_this.lscroll.style.left);
                mousewheelhandle = _mousewheelhandle.call(_this,pos);
                _addevent(_this.wrapper,'mousewheel',mousewheelhandle);
                _addevent(_this.wrapper,'mouseleave',function(){_removeevent(_this.wrapper,'mousewheel',mousewheelhandle)});
            });
        },
        //对外提供添加竖向滚动条的方法
        addvscroll:function(){
            if(this.vscroll) return;
            !this.wrapper && this.addwarpper('top');
            this.vscrollouter = _createel('
',this.wrapper)
            this.vscroll = _createel('
',this.wrapper);
            this.recalculated();
        },
        //对外提供添加横向滚动条的方法
        addlscroll:function(){
            if(this.lscroll) return;
            !this.wrapper && this.addwarpper('left');
            this.lscrollouter = _createel('
',this.wrapper)
            this.lscroll = _createel('
',this.wrapper);
            this.recalculated();
        },
        //删除竖向滚动条
        delvscroll:function(){
            _deletescroll.call(this,1,this.vscroll,this.vscrollouter,this.lscroll,this.lscrollouter);
        },
        //删除横向滚动条   
        dellscroll:function(){
            _deletescroll.call(this,0,this.lscroll,this.lscrollouter,this.vscroll,this.vscrollouter);
        }
    };
    skyscroll.prototype.init.prototype = skyscroll.prototype;
    window.skyscroll = skyscroll;
    /*************************私有函数*************************/
    function _mousemovehandle(pos,target){
        var _this = this;
        return target == this.vscroll ? function(e){
            e = e || window.event;
            var newpos = _getmousepos(e);
            _this.target.style.top = math.min(0,math.max(pos.ttop + (pos.y - newpos.y)/_this.ratio.v,-_this.range.t)) + 'px';
            target.style.top = math.max(0,math.min(pos.stop - pos.y + newpos.y,_this.range.st))+ 'px';
            _this.callback.call(_this);
            _cancelselect()
        }:function(e){
            e = e || window.event;
            var newpos = _getmousepos(e);
            _this.target.style.left = math.min(0,math.max(pos.tleft + (pos.x - newpos.x)/_this.ratio.l,-_this.range.l)) + 'px';
            target.style.left = math.max(0,math.min(pos.sleft - pos.x + newpos.x,_this.range.sl)) + 'px';
            _this.callback.call(_this);
            _cancelselect();
        }
    };
function _mousewheelhandle(pos){
        var _this = this;
        return this.vscroll ? function(e){
            e = e || window.event;
            _stopevent(e);
            var data = e.wheeldelta ? e.wheeldelta /120 : -e.detail/3;
            var top = parseint(_this.target.style.top);
            var stop = parseint(_this.vscroll.style.top);
            var dist = data * 5;
            _this.target.style.top = math.min(0,math.max(top + dist / _this.ratio.v, -_this.range.t)) + 'px';
            _this.vscroll.style.top = math.max(0,math.min(stop-dist,_this.range.st)) + 'px';
            _this.callback.call(_this);
        }:function(e){
            e = e || window.event;
            _stopevent(e);
            var data = e.wheeldelta ? e.wheeldelta /120 : -e.detail/3;
            var left = parseint(_this.target.style.left);
            var sleft = parseint(_this.lscroll.style.left);
            var dist = data * 5;
            _this.target.style.left = math.min(0,math.max(left + dist / _this.ratio.l, -_this.range.l)) + 'px';
            _this.lscroll.style.left = math.max(0,math.min(sleft-dist,_this.range.sl)) + 'px';
            _this.callback.call(_this);
        }
    };
    function _mounsedownhandle(pos,target){
        var _this = this;
        var elpos = _getelementposition(target);
        if(target == this.vscrollouter){
            console.log(pos.y - elpos.y);
            _this.set({
                top:pos.y - elpos.y
            });
        }else{
            _this.set({
                left:pos.x - elpos.x
            });
        };
    };
    function _deletescroll(n,s1,s11,s2,s22){
        var o = n ? 'height' : 'width' ,s = n ? 'top' : 'left';
        if(!s1) return;
        this.wrapper.removechild(s1);
        this.wrapper.removechild(s11);
        n ?  (this.vscroll = null) : (this.lscroll = null);
        if(!s2){
            this.wrapper.parentnode.appendchild(this.target);
            this.wrapper.parentnode.removechild(this.wrapper);
            this.target.style.csstext = '';
            this.wrapper = null;
        }else{
            this.wrapper.style[o.tolowercase()] = this.target['offset'+o] + 'px';
            this.recalculated();
        };
        this.target.style[s] = '0px';
        //this.target.style[o.tolowercase()]= 'auto';
    };
    /*************************工具函数*************************/
    function _$(id){
        return typeof id === 'string' ? doc.getelementbyid(id) : id;
    };
    function _extend(target,source){
        for(var key in source) target[key] = source[key];
        return target;
    };
    function _createel(html,parent){
        var div = doc.createelement('div');
        div.innerhtml = html;
        el = div.firstchild;
        parent && parent.appendchild(el);
        return el;
    };
    function _getmousepos(e){
        if(e.pagex || e.pagey) return {x:e.pagex,y:e.pagey};
        return {
            x:e.clientx + document.documentelement.scrollleft - document.body.clientleft,
            y:e.clienty + document.documentelement.scrolltop - document.body.clienttop
        };
    };
    function _isobject(o){
        return o === object(o);
    };
    function _getelbyclass(node,oclass,parent){
        var re = [],els,parent = parent || doc;
        els = parent.getelementsbytagname(node);
        for(var i=0,len=els.length;i            if((' ' + els[i].classname+' ').indexof(' '+oclass+' ') > -1) re.push(els[i]);
        };
        return re;
    };
    function _stopevent(e){
        e.stoppropagation ? e.stoppropagation() : (e.cancelbubble = true);
        e.preventdefault ? e.preventdefault() :(e.returnvalue = false);
    };
    function _addevent(el,type,fn){
        if(typeof el.addeventlistener != 'undefined'){
            if(type == 'mouseenter'){
                el.addeventlistener('mouseover',_findelement(fn),false);
            }else if(type === 'mouseleave'){
                el.addeventlistener('mouseout',_findelement(fn),false);
            }else{
                el.addeventlistener(type,fn,false);
            }
        }else if(typeof el.attachevent != 'undefined'){
            el.attachevent('on'+type,fn);
        }else{
            el['on'+type] = fn;
        }
    };
    function _removeevent(el,type,fn){
        if(typeof el.removeeventlistener != 'undefined'){
            el.removeeventlistener(type,fn,false);
        }else if(typeof el.detachevent != 'undefined'){
            el.detachevent('on'+type,fn);
        }else{
            el['on'+type] = null;
        }
    };
    function _findelement(fn){
        return function(e){
            var parent = e.relatedtarget;
            while(parent && parent != this) parent = parent.parentnode;
            if(parent != this) fn.call(this,e);
        }
    };
    function _cancelselect(){
        if (window.getselection) {
            if (window.getselection().empty) {  // chrome
                window.getselection().empty();
            } else if (window.getselection().removeallranges) {  // firefox
                window.getselection().removeallranges();
            }
        }else if (document.selection) {  // ie?
          document.selection.empty();
        }
    };
    function _getelementposition(el){
        var x = 0,y=0;
        if(el.getboundingclientrect){
            var pos = el.getboundingclientrect();
            var d_root = document.documentelement,db = document.body;
            x = pos.left + math.max(d_root.scrollleft,db.scrollleft) - d_root.clientleft;
            y = pos.top + math.max(d_root.scrolltop,db.scrolltop) - d_root.clienttop;
        }else{
            while(el != db){
                x += el.offsetleft;
                y += el.offsettop;
                el = el.offsetparent;
            };
        };
        return {
            x:x,
            y:y
        };
    };
})(window);
html:
复制代码 代码如下:
111111111111111111111111111111译者按 ie 曾是 web 创新的先驱,但最近几年因为对 web 标准的支持落后于其他浏览器以及低版本 ie 的各种 bug 而被人诟病。雅虎的 nicholas c. zakas 带我们回顾了 ie 在 web 发展过程中扮演的辉煌角色,让我们能以一个更客观的眼光来看待 ie。看完这篇文章,也许大家都会对 ie 浏览器有一定的改观,这也是我翻译这篇文章的目的。
译文
在 internet explorer 成为大家都恨之入骨的浏览器的很久以前,它曾是整个互联网的创新驱动力。有时候我们很难记得那些在 ie 6 成为全世界 web 开发者的灾难之前 ie 所作的贡献。不管你信不信,正因为有了 ie 4—6,才会有我们现在所知的 web 开发。ie 的一些独特的功能过去就曾是事实标准,后来成为了官方标准最终进入了 html5 规范。人们也许很难相信,对于我们现在认为理所应当的功能中有很大一部分都应该要想到 ie,但快速地回顾一下历史可以让我们知道的确如此。
dom
如 果 ie 是一个人人都痛恨的浏览器,那么「文档对象模型」(dom)就是人人都痛恨的 api 了。你可以说 dom 过于繁琐、不适合 javascript 甚至是有些荒谬,而且这些也都没错。然而,dom 还是给了开发者通过 javascript 来访问网页的每个部分的途径。曾经你一度只能通过 javascript 访问页面中某些特定的元素。ie 3 和 netscape 3 只允许程序访问表单元素、图片以及链接。netscape 4 改进了这一点,把程序可访问的范围通过 document.layers 扩展到了它特有的 layer 元素。ie 4 作了进一步改进,把这个范围通过 document.all 扩展到了页面的所有元素。
从很多方面来说,document.all 算是 document.getelementbyid() 的最初版本。你还是要使用元素的 id 来通过 document.all 访问它,例如 document.all.mydiv 或是 document.all[mydiv]。最主要的区别就是 ie 使用了一个集合而非方法,而这和其他当时的访问方法比如 document.images 及 document.forms 是相吻合的。
ie 4 也第一个引入了用 document.all.tags() 来通过标签名字获取一个元素列表的功能。无论从哪点来看,这都是 document.getelementsbytagname() 的最初版本,而且工作方式完全相同。如果你想获取所有的 div 元素,你可以使用 document.all.tags(div)。甚至在 ie 9 中,这个方法仍然作为 document.getelementsbytagname() 的一个别名存在。
ie 4 同时也为我们引入了可能是有史以来最流行的私有 dom 扩展:innerhtml。看起来微软的那帮人是认识到了通过编程手段来建立一个 dom 有多么痛苦,所以把这个便捷方法,连同 outerhtml 一起提供给我们。事实证明这两个方法都非常有用,已经在 html5 中被标准化了[1]。随它们一同而来的用来处理纯文本的 api——innertext 以及 outertext——同样被证明足够有影响力,因为 dom level 3 已经引入了与 innertext 行为相似的 textcontent[2]。
按照同样的思路,ie 4 引入了 insertadjacenthtml(),这是又一种将 html 插入文档中的方法。虽然这花了更长的时间,但最终也被编入了 html5[3],而且目前已被各浏览器广泛支持。
事件
在开始时,javascript 并没有事件机制。网景和微软都作出了尝试,并且分别得出了不同的模型。网景给我们带来了事件捕获,其思想是一个事件先发送到窗口,然后是文档,然后一个个直到最终到达预期的目标。网景浏览器 6 以前的版本都仅支持事件捕获。
微 软采取了一个相反的方法,设计出了事件冒泡。他们认为一个事件应该先从实际的目标出发,然后在上层节点触发直到文档。ie 9 以前的浏览器仅支持事件冒泡。虽然随着官方的 dom 事件规范发展,同时包含了事件捕获和事件冒泡,但大多数 web 开发者都只使用事件冒泡,而把事件捕获仅仅留在 javascript 类库中的一些解决方案和小技巧中使用。
除了创造了事件冒泡以外,微软还创造了一系列后来也最终被标准化的额外事件:
contextmenu – 当使用鼠标副按键点击一个元素时触发。在 ie 5 中首次出现,后来被编入了 html5[4]。现在已被所有主流浏览器所支持。
beforeunload – 在 unload 事件前触发,允许你阻断页面的退出。最初由 ie 4 引入,现在也为 html5 的一部分[4]。
mousewheel – 在鼠标滚轮(或类似设备)被使用时触发。首个支持此事件的浏览器是 ie 6。就像其他一样,目前也是 html5 的一部分[4]。唯一不支持此事件的主流桌面浏览器是 firefox(但其支持一个可用来替代的 dommousescroll 事件)。
mouseenter – mouseover 的非冒泡版本,被微软在 ie 5 中引入,用来克服 mouseover 使用时带来的困扰。这个事件已被 dom level 3 事件规范正规化[5]。同样被 firefox 及 opera 支持,但 safari 和 chrome 都(暂时?)不支持。
mouseleave – 与 mouseenter 对应的 mouseout 的非冒泡版本。在 ie 5 中被引入,目前被 dom level 3 事件规范标准化[6]。浏览器支持和 mouseenter 一样。
focusin – focus 事件的冒泡版本,用来帮助更好地管理页面上的聚焦行为。最初在 ie 6 中被引入,现在已成为 dom level 3 事件规范的一部分[7]。目前没有被很好地支持,尽管 firefox 关于其实现的开过一个 bug。
focusout – blur 事件的冒泡版本,用来帮助更好地管理页面上的聚焦行为。最初在 ie 6 中被引入,现在已成为 dom level 3 事件规范的一部分[8]。和 focusin 一样,没有良好支持但 firefox 接近了。
xml 与 ajax
尽 管 xml 已经像很多人所料的那样在现今的 web 上被大量使用,但是对 xml 进行支持的领路人仍然是 ie。它是第一个支持在客户端通过 javascript 进行 xml 解析以及 xslt 变换的浏览器。不幸的是,它是通过 activex 对象来表示 xml 文档以及 xslt 处理器的。但 mozilla 的人显然认识到了其中的可取之处,因为他们后来用 domparser、xmlserializer 和 xsltprocessor 创造了类似的功能。其中前两个已经成为了 html5 的一部分[9]。虽然基于标准的 javascript xml 处理方式和 ie 提供的版本差异较大,但它无疑是深受 ie 影响的。
客户端的 xml 处理都都是 ie 对 xmlhttprequest 的实现的一部分,最开始由 ie 5 以 activex 对象的形式引入。其中的想法是希望可以在一个网页中从服务器获取一个 xml 文档并且允许用 javascript 把这个 xml 当做 dom 来进行处理。ie 的版本需要你使用 new activexobject(msxml2.xmlhttp),这也使得它依赖于版本字符串,而且让开发者要费尽功夫去测试、使用最新版本。再一次,firefox 站出来,通过创建一个当时还是私有的、与 ie 版本接口完全同名的 xmlhttprequest 对象来清理这一片混乱。此后其他浏览器复制了 firefox 的实现,最终使得 ie 7 也增加了一个不需要使用 activex 的版本。当然,使得每个人为 javascript 感到振奋的 ajax 革命背后的驱动力正是 xmlhttprequest。
效果图:
对外提供的方法就是上面那几个按钮上说明的。
其它类似信息

推荐信息