function Scroll(holder, content, bars, timer, settings){ this.holder = holder; this.content = content; this.timer = Timer.detectTimer(timer); this.mov = new moveable(this.content); this.onscroll = DOMEvent.cloneEvent(this.mov.onmove); this._bars = bars; this.settings = Scroll.defaultSettings; if(settings){ for(var i in settings){ this.settings[i] = settings[i]; } } if(this.settings._INIT){ this.init(); } } Scroll.prototype.init = function(){ this.getHolderProps(); this.getContentProps(); this.check(); } Scroll.prototype.getHolderProps = function(){ this.holder_props = Style.getDimensions(this.holder); } Scroll.prototype.getContentProps = function(){ this.content_props = Style.getDimensions(this.content); } Scroll.prototype.check = function(dX, dY){ var deltaX = dX || (this.content_props.width - this.holder_props.width); var deltaY = dY || (this.content_props.height - this.holder_props.height); if(this.barX){ this.barX.refresh(deltaX); }else{ if(this._bars.X){ this.barX = new Scroll.Scrollbar("X", this, deltaX); } } if(this.barY){ this.barY.refresh(deltaY); }else{ if(this._bars.Y){ this.barY = new Scroll.Scrollbar("Y", this, deltaY); } } this.deltaY = deltaY; this.deltaX = deltaX; } Scroll.prototype.refresh = function(){ this.getHolderProps(); this.getContentProps(); this.check(); } Scroll.prototype.moveContentTo = function(x, y){ if(this.barX){ this.barX.moveContentTo(x); } if(this.barY){ this.barY.moveContentTo(y); } } Scroll.Scrollbar = function(type, parentObject, delta){ this.parent = parentObject; this.type = type.toUpperCase(); this.op_type = Scroll.types[Number(!Scroll.types.indexOf(this.type))]; this.delta = delta; //this.settings = this.parent.settings[this.type]; this.PROPS = Scroll.bars[this.type]; this.HIDDEN = false; this.THUMB_SET = false; this.STATE = 0;//NOT INITIALIZED this.init(); } Scroll.Scrollbar.prototype.init = function(partly){ if(!partly){ var _bar = this.parent._bars[this.type]; for(var i in _bar){ this[i] = _bar[i]; } if(this.delta <= 0){ this.hide(); this.STATE = 1;//PARTLY INITIALIZED return false; } } this.count(); this.initMovs(); this.get_speed(); this.init_buttons(); if(this.parent.settings._ARROWS){ this.init_arrows(); } if(this.type == "Y"){ if(this.parent.settings._MOUSEWHEEL){ this.initWheel(); } if(this.parent.settings._SELECTION){ this.initSelection(); } } this.STATE = 2;//INITIALIZED } Scroll.Scrollbar.prototype.unpack = function(){ } Scroll.Scrollbar.prototype.count = function(){ var prop = this.PROPS.mainDim; var pad = parseInt(Style.getElementStyle(this.track, this.PROPS.secDim)); this.track_len = parseInt(Style.getElementStyle(this.track, prop)); this.thumb_len = parseInt(Style.getElementStyle(this.thumb, prop)); if(!this.thumb_len || this.THUMB_SET){ this.set_thumb(prop) } this.th_delta = this.track_len - this.thumb_len; this.mov_coeff = this.delta / this.th_delta; if(this.th_mov){ this.th_mov.limits[this.type].to = this.th_delta; this.dd_mouse.to = this.thumb_len; } } Scroll.Scrollbar.prototype.initMovs = function(){ this.th_mov = new moveable(this.thumb); this.th_mov.setLimits(this.type, this.th_delta, 0); this.th_mov.allowed[this.op_type] = false; this.th_mov.onmove.register("mov", function(oM){ var args = [0, -oM["move" + this.type] * this.mov_coeff]; if(this.type == "X"){ args = args.invert(); } this.parent.mov.moveBy.apply(this.parent.mov, args); }.bind(this, this.th_mov)); this.th_movement = new Movement(this.th_mov, this.parent.timer); this.dd = new DragDrop(this.th_mov); //this.set_dd_mouse(); } Scroll.Scrollbar.prototype.set_thumb = function(prop){ var c_length = this.parent.content_props[prop]; var h_length = this.parent.holder_props[prop]; var t_len = Math.floor(this.track_len / (c_length / h_length)); this.thumb_len = Math.max(t_len, this.parent.settings.thumb_min_len); this.thumb.style[prop] = this.thumb_len + "px"; this.THUMB_SET = true; } Scroll.Scrollbar.prototype.get_speed = function(){ this.step = this.parent.settings.speed / this.mov_coeff; } Scroll.Scrollbar.prototype.set_dd_mouse = function(){ this.dd_mouse = new Limit(0, this.thumb_len); this.dd.ondragstart.register("catch mouse", function(){ this.dd_mouse.value = this.dd["mouse_" + this.type.toLowerCase()]; this.th_mov[this.PROPS.onmore].register("change mouse more", function(lim){ this.dd_mouse.change(lim.exceeded); }.bind(this, this.th_mov.limits[this.type])); this.th_mov[this.PROPS.onless].register("change mouse less", function(lim){ this.dd_mouse.change(lim.preceeded); }.bind(this, this.th_mov.limits[this.type])); }.bind(this)); this.dd.ondrop.register("drop limits", function(){ this.th_mov[this.PROPS.onmore].remove("change mouse more"); this.th_mov[this.PROPS.onless].remove("change mouse less"); this.th_mov.onmove.remove("accumulate"); }.bind(this)) this.dd_mouse.onmore.register("accumulate", function(){ if(!this.accumulate){ this.accumulate = new Limit(0, Infinity); this.accumulate.onless.register("drop all", function(){ var m = this.accumulate.preceeded; this.accumulate = null; this.th_mov.onmove.remove("accumulate"); if(this.type == "X"){ this.th_mov.moveBy(m, 0); }else{ this.th_mov.moveBy(0, m); } }.bind(this)) this.th_mov.onmove.register("accumulate", function(){ this.accumulate.change(this.th_mov["move" + this.type]); this.th_mov["move" + this.type] = 0; }.bind(this), false, 0); this.accumulate.change(this.dd_mouse.exceeded); } }.bind(this)); this.dd_mouse.onless.register("accumulate", function(){ if(!this.accumulate){ this.accumulate = new Limit(0, Infinity); this.accumulate.onless.register("drop all", function(){ var m = -this.accumulate.preceeded; this.accumulate = null; this.th_mov.onmove.remove("accumulate"); if(this.type == "X"){ this.th_mov.moveBy(m, 0); }else{ this.th_mov.moveBy(0, m); } }.bind(this)) this.th_mov.onmove.register("accumulate", function(){ this.accumulate.change(-this.th_mov["move" + this.type]); this.th_mov["move" + this.type] = 0; }.bind(this), false, 0); this.accumulate.change(-this.dd_mouse.preceeded); } }.bind(this)); } Scroll.Scrollbar.prototype.scroll_plus = function(){ var M = this.th_movement; var args = [0, this.step]; if(this.type == "X"){ args = args.invert(); } M.setSteps.apply(M, args); M.start(); } Scroll.Scrollbar.prototype.scroll_minus = function(){ var M = this.th_movement; var args = [0, -this.step]; if(this.type == "X"){ args = args.invert(); } M.setSteps.apply(M, args); M.start(); } Scroll.Scrollbar.prototype.stop_scroll = function(e){ if(this.th_movement.isMoving){ this.th_movement.stop(); stopPropagation(e || window.event); DetachEvent(document, "mouseup", this._mouseup_func); } } Scroll.Scrollbar.prototype.init_buttons = function(){ this.bPlus.onmousedown = this.scroll_plus.bind(this); this.bMinus.onmousedown = this.scroll_minus.bind(this); this._mouseup_func = this.stop_scroll.bind(this); this.bPlus.onmouseup = this.bMinus.onmouseup = this._mouseup_func; this.bPlus.onmouseout = this.bMinus.onmouseout = function(){ AttachEvent(document, "mouseup", this._mouseup_func); }.bind(this); this.bPlus.onmouseover = this.bMinus.onmouseover = function(){ try{ DetachEvent(document, "mouseup", this._mouseup_func); }catch(e){} } } Scroll.Scrollbar.prototype.init_arrows = function(){ this.start_arrow = Scroll.Scrollbar.start_arrow.bindAvoidingEvent(this, this.type); AttachEvent(_elem(this.parent.holder), "mouseover", this.start_arrow); this.stop_arrow = Scroll.Scrollbar.stop_arrow.bind(this); AttachEvent(_elem(this.parent.holder), "mouseout", this.stop_arrow); } Scroll.Scrollbar.prototype.detach_arrows = function(){ this.stop_arrow(); DetachEvent(_elem(this.parent.holder), "mouseover", this.start_arrow); } Scroll.Scrollbar.prototype.attach_arrows = function(){ AttachEvent(_elem(this.parent.holder), "mouseover", this.start_arrow); } Scroll.Scrollbar.prototype.initWheel = function(){ this._start_wheel = function(){ if(this.WHEEL_WORKS){ return false; } this.WHEEL_WORKS = true; Scroll.setMouseWheel(this); }.bind(this); AttachEvent(_elem(this.parent.holder), "mouseover", this._start_wheel); this._stop_wheel = function(e){ var ev = e || window.event; var target = ev.relatedTarget || ev.toElement; var el = _elem(this.parent.holder); if(target == el || _isChild(target, el)){ return false; } if(!this.WHEEL_WORKS){ return false; } this.WHEEL_WORKS = false; window.onmousewheel = document.onmousewheel = null; if(window.addEventListener && !window.opera){ window.removeEventListener('DOMMouseScroll', this.wheelFunc, false); } }.bind(this); AttachEvent(_elem(this.parent.holder), "mouseout", this._stop_wheel); } Scroll.Scrollbar.prototype.detach_wheel = function(){ this._stop_wheel(); DetachEvent(_elem(this.parent.holder), "mouseover", this._start_wheel); } Scroll.Scrollbar.prototype.attach_wheel = function(){ AttachEvent(_elem(this.parent.holder), "mouseover", this._start_wheel); } Scroll.Scrollbar.prototype.initSelection = function(){ this.previousMouseY = 0; if(Style._browser == "IE"){ this.parent.content.onselectstart = Scroll.Scrollbar.start_selection.bind(this); }else{ this.parent.content.onmousedown = Scroll.Scrollbar.start_selection.bind(this); } } Scroll.Scrollbar.start_arrow = function(type){ if(this.ARROWS_WORK){ return false; } this.ARROWS_WORK = true; this._key_down_function = Scroll.Scrollbar.arrows[this.type].bind(this); this._key_up_function = this.stop_scroll.bind(this); AttachEvent(document, "keydown", this._key_down_function); AttachEvent(document, "keyup", this._key_up_function); } Scroll.Scrollbar.stop_arrow = function(){ if(!this.ARROWS_WORK){ return false; } this.ARROWS_WORK = false; DetachEvent(document, "keydown", this._key_down_function); DetachEvent(document, "keyup", this._key_up_function); } Scroll.Scrollbar.arrows = { X: function(e){ if(this.dd.IS_DRAGGING){ return false; } switch(e.keyCode){ case 39: //down this.scroll_plus(); break; case 37: //up this.scroll_minus(); break; } }, Y: function(e){ if(this.dd.IS_DRAGGING){ return false; } switch(e.keyCode){ case 40: //down this.scroll_plus(); break; case 38: //up this.scroll_minus(); break; } } } Scroll.Scrollbar.start_selection = function(e){ var ev = e || window.event; this.previousMouseY = ev.clientY; document.onmousemove = function(e){ var ev = e || window.event; var delta = this.previousMouseY - ev.clientY; this.previousMouseY = ev.clientY; this.th_mov.moveBy(0, -delta); }.bind(this); document.onmouseup = function(){ document.onmousemove = null; } } Scroll.Scrollbar.stop_selection = function(){ } Scroll.wheelFunc = function(e){ if(this.dd.IS_DRAGGING){ return false; } var ev = window.event || e; var delta = ev.wheelDelta ? ev.wheelDelta / 120 : -ev.detail / 3; this.th_mov.moveBy(0 ,-delta * 3); if(ev.preventDefault){ ev.preventDefault(); } ev.returnValue = false; } Scroll.setMouseWheel = function(obj){ switch(Style._browser){ case "Gecko": obj.wheelFunc = Scroll.wheelFunc.bind(obj); window.addEventListener('DOMMouseScroll', obj.wheelFunc, false); break; case "Opera": window.onmousewheel = Scroll.wheelFunc.bind(obj); break; case "IE": document.onmousewheel = Scroll.wheelFunc.bind(obj); break; } } Scroll.Scrollbar.prototype.moveContentTo = function(value){ var val = value / this.mov_coeff; if(this.type == "X"){ this.th_mov.moveTo(val, 0); }else{ this.th_mov.moveTo(0, val); } } Scroll.Scrollbar.prototype.refresh = function(delta){ if(delta == this.delta){ return false; } this.delta = delta; if(delta < 0){ this.hide(); }else if(this.delta > 0){ if(this.STATE == 1){ this.init(true);//continue initialization } this.contentPosition = -this.parent.mov[this.PROPS.mainPos]; this.moveContentTo(0); this.show(); this.count(); this.get_speed(); this.moveContentTo(this.contentPosition); } } Scroll.Scrollbar.prototype.hide = function(visibility){ if(this.HIDDEN){ return false; } var vis = visibility || false; var prop = Scroll._display_props.bool(vis); this.bar.style[prop] = Scroll.__hides.bool(vis); this.HIDDEN = true; if(this.STATE < 2){ return false; } this.moveContentTo(0); if(this.type == "Y"){ if(this.parent.settings._MOUSEWHEEL){ this.detach_wheel(); } } if(this.parent.settings._ARROWS){ this.detach_arrows(); } } Scroll.Scrollbar.prototype.show = function(visibility){ if(!this.HIDDEN){ return false; } var vis = visibility || false; var prop = Scroll._display_props.bool(vis); this.bar.style[prop] = Scroll.__shows.bool(vis); if(this.type == "Y"){ if(this.parent.settings._MOUSEWHEEL){ this.attach_wheel(); } } if(this.parent.settings._ARROWS){ this.attach_arrows(); } this.HIDDEN = false; } Scroll.Scrollbar.prototype.toString = __toString; Scroll.Scrollbar.prototype.__name = "Scrollbar"; Scroll.prototype.toString = __toString; Scroll.prototype.__name = "Scroll"; Scroll.bars = { X: { mainDim: "width", secDim: "height", mainPos: "left", secPos: "right", plusPos: "right", minusPos: "left", pad: "paddingRight", onmore: "onrightlimitreach", onless: "onleftlimitreach" }, Y: { mainDim: "height", secDim: "width", mainPos: "top", secPos: "bottom", plusPos: "bottom", minusPos: "top", barPos: "right", pad: "paddingRight", onmore: "onbottomlimitreach", onless: "ontoplimitreach" } } Scroll.types = ["X", "Y"]; Scroll._display_props = ["display", "visibility"]; Scroll.__shows = ["block", "visible"]; Scroll.__hides = ["none", "hidden"]; Scroll.defaultSettings = { _INIT: true, _MOUSEWHEEL: true, _ARROWS: true, _SELECTION: false, speed: 5, thumb_min_len: 10, toString: function(){ var str = "object Settins\t\n\t"; for(var i in this){ if(i != "toString"){ str += i + " => " + this[i] + "\t\n\t"; } } return str; } }