Home  >  Article  >  Web Front-end  >  js simulate scroll bar (horizontal and vertical)_javascript skills

js simulate scroll bar (horizontal and vertical)_javascript skills

WBOY
WBOYOriginal
2016-05-16 17:41:351175browse

JS:

Copy code The code is as follows:

(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;
    /***************************Private functions*************************/
    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';
    };
    /***************************Tool functions*************************/
    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"]。The main difference is that IE uses a collection instead of a method, which is consistent with other access methods at the time such as document.images and document.forms.

IE 4 was also the first to introduce the function of using document.all.tags() to obtain a list of elements by tag name. For all intents and purposes, this is the original version of document.getElementsByTagName() and works exactly the same. If you want to get all div elements, you can use document.all.tags("div"). Even in IE 9, this method still exists as an alias for document.getElementsByTagName().

IE 4 also introduced us to perhaps the most popular private DOM extension ever: innerHTML. It seems that the people at Microsoft realized how painful it is to create a DOM programmatically, so they provided this convenient method to us together with outerHTML. Both methods have proven to be very useful and have been standardized in HTML5 [1]. The APIs that came with them for handling plain text - innerText and outerText - also proved influential enough, as DOM Level 3 has introduced textContent[2] which behaves similarly to innerText.

Along the same lines, IE 4 introduced insertAdjacentHTML(), yet another way to insert HTML into a document. Although this took longer, it was eventually codified into HTML5[3] and is now widely supported by browsers.

Events

At the beginning, JavaScript had no event mechanism. Both Netscape and Microsoft have tried and come up with different models. Netscape brought us event capture, the idea is that an event is sent to the window first, then the document, and then one by one until it finally reaches the expected target. Versions prior to Netscape Browser 6 only supported event capture.

Microsoft took the opposite approach and designed event bubbling. They believe that an event should start from the actual target first, and then trigger on upper nodes up to the document. Browsers prior to IE 9 only support event bubbling. Although the official DOM event specification has evolved to include both event capturing and event bubbling, most web developers only use event bubbling, leaving event capturing only in some solutions and small JavaScript libraries. used in techniques.

In addition to creating event bubbling, Microsoft also created a series of additional events that were eventually standardized:

contextmenu – triggered when an element is clicked using the secondary mouse button. First appeared in IE 5 and later codified into HTML5[4]. Now supported by all major browsers.
beforeunload – Fires before the unload event, allowing you to block the exit of the page. Originally introduced in IE 4, it is now also part of HTML5[4].
mousewheel – Fires when the mouse wheel (or similar device) is used. The first browser to support this event was IE 6. Like others, it is currently part of HTML5[4]. The only major desktop browser that does not support this event is Firefox (but it does support a DOMMouseScroll event that can be used instead).
mouseenter – a non-bubble version of mouseover, introduced by Microsoft in IE 5 to overcome the troubles caused by mouseover. This event has been formalized by the DOM Level 3 event specification [5]. Also supported by Firefox and Opera, but not (yet?) supported by Safari and Chrome.
mouseleave – The non-bubble version of mouseout corresponding to mouseenter. Introduced in IE 5 and currently standardized by the DOM Level 3 event specification [6]. Browser support is the same as mouseenter.
focusin – A bubbling version of the focus event, used to help better manage focus behavior on the page. Originally introduced in IE 6, it is now part of the DOM Level 3 event specification[7]. It is currently not well supported, although Firefox has opened a bug regarding its implementation.
focusout – A bubbling version of the blur event, used to help better manage focus behavior on the page. Originally introduced in IE 6, it is now part of the DOM Level 3 event specification[8]. Like focusin, not as well supported but Firefox comes close.
XML and Ajax
Although XML is as widely used on the web today as many people expected, the leader in supporting XML is still IE. It was the first browser to support client-side XML parsing and XSLT transformation via JavaScript. Unfortunately, it represents XML documents and XSLT processors through ActiveX objects. But the folks at Mozilla apparently recognized the merit, because they later created similar functionality with DOMParser, XMLSerializer, and XSLTProcessor. The first two of them have become part of HTML5 [9]. Although the standard-based JavaScript XML processing method is quite different from the version provided by IE, it is undoubtedly deeply influenced by IE.

Client-side XML processing is all part of IE's implementation of XMLHttpRequest, which was first introduced by IE 5 in the form of ActiveX objects. The idea is to get an XML document from the server in a web page and allow JavaScript to process this XML as a DOM.The version of IE requires you to use new ActiveXObject("MSXML2.XMLHttp"), which also makes it dependent on the version string and requires developers to work hard to test and use the latest version. Once again, Firefox stepped in and cleaned up the mess by creating a then-private XMLHttpRequest object with the exact same name as the IE version of the interface. Since then, other browsers have copied Firefox's implementation, and eventually IE 7 also added a version that did not require the use of ActiveX. Of course, the driving force behind the Ajax revolution that got everyone excited about JavaScript was XMLHttpRequest.