var scrollr = scrollr || {}; scrollr.scrollers = []; scrollr.doInit = function() { var elements = scrollr.getElementsByClass(document.body, 'div', 'scrollr'); for (element in elements) { //var new_scroller = new scrollr.Scrollbar(elements[element]); //scrollr.scrollers.push(new_scroller); } } scrollr.Scrollbar = function(element) { this.element = element; this.element.style.overflow = "hidden"; this.element.style.whiteSpace = "nowrap"; //this.element.className = 'scrollr_js'; this.container = document.createElement('div'); this.container.className = 'scrollr_container'; this.element.parentNode.insertBefore(this.container, this.element); this.container.appendChild(this.element); var divs = this.element.getElementsByTagName('div'); for (div in divs) { divs[div].className = 'scrollr_item'; } this.location = new scrollr.Vector(0, 0, 0); this.velocity = new scrollr.Vector(0, 0, 0); this.acceleration = new scrollr.Vector(0, 0, 0); this.last_x = 0; this.createScrollbar(); this.createScroller(); this.timer = new scrollr.Loop(25, (function(context) { return function(e) { context.doScroll(e); } })(this) ); } scrollr.Scrollbar.prototype.createScrollbar = function() { this.scrollbar = document.createElement('div'); this.scrollbar.className = 'scrollr_scrollbar'; this.container.appendChild(this.scrollbar); this.container.style.paddingBottom = (this.scrollbar.offsetHeight + (parseInt(this.container.style.paddingBottom) || 0))+"px"; this.attached_mouse = false; this.mouse_event = (function(context) { return function(e) { context.onMouseMove(e); } })(this); scrollr.addEvent(this.scrollbar, 'mousedown', (function(context) { return function(e) { context.onClick(e); e.preventDefault(); return false; } })(this) ); scrollr.addEvent(this.scrollbar, 'mouseup', (function(context) { return function(e) { context.onRelease(e); } })(this) ); } scrollr.Scrollbar.prototype.createScroller = function() { this.scroller_box = document.createElement('div'); this.scroller_box.className = 'scrollr_scroller_box'; this.scrollbar.appendChild(this.scroller_box); // this.scroller_box.style.width = ( this.scroller_box.offsetWidth * this.getMultiplier() )+"px"; this.scroller = document.createElement('div'); this.scroller.className = 'scrollr_scroller'; this.scroller_box.appendChild(this.scroller); this.scroller.style.width = ( this.scroller.offsetWidth * this.getMultiplier() )+"px"; } scrollr.Scrollbar.prototype.getInnerWidth = function() { return (this.element.scrollWidth); } scrollr.Scrollbar.prototype.getMultiplier = function() { return ( this.element.offsetWidth / this.element.scrollWidth ); } scrollr.Scrollbar.prototype.onClick = function(event) { var e = window.event || event; var offset_left = e.clientX-(this.container.offsetLeft); this.target_x = offset_left; if (offset_left > this.scroller.offsetLeft && offset_left < this.scroller.offsetLeft+this.scroller.offsetWidth) { if (!this.attached_mouse) { this.attached_mouse = true; scrollr.addEvent(window, 'mousemove', this.mouse_event); } } /* if (offset_left < this.location.x) { var move = (offset_left - this.location.x)*this.getMultiplier(); this.applyForce(new scrollr.Vector(move, 0, 0)); } else if (offset_left > this.location.x+this.scroller.offsetWidth) { var move = 4 * (( offset_left - (this.location.x+this.scroller.offsetWidth) )); this.applyForce(new scrollr.Vector(move, 0, 0)); }*/ this.timer.Start(); return false; } scrollr.Scrollbar.prototype.onRelease = function(event) { if (this.attached_mouse) { this.attached_mouse = false; scrollr.removeEvent(window, 'mousemove', this.mouse_event); } } scrollr.Scrollbar.prototype.onMouseMove = function(event) { var e = window.event || event; var offset_left = e.clientX-(this.container.offsetLeft); //this.target_x = offset_left; if (offset_left < this.previous_x) { this.target_x = this.location.x - (this.previous_x-offset_left); } else if (offset_left > this.previous_x) { this.target_x = this.scroller.offsetWidth+this.location.x+(offset_left-this.previous_x); } this.previous_x = offset_left; this.timer.Start(); } scrollr.Scrollbar.prototype.doScroll = function(delta) { if (this.target_x < this.location.x) { var move = (this.target_x - this.location.x)*this.getMultiplier(); this.applyForce(new scrollr.Vector(move, 0, 0)); } else if (this.target_x > this.location.x+this.scroller.offsetWidth) { var move = (( this.target_x - (this.location.x+this.scroller.offsetWidth) ))*this.getMultiplier(); this.applyForce(new scrollr.Vector(move, 0, 0)); } if (this.location.x <= 8) { // this.velocity.multiply(0); this.applyForce(new scrollr.Vector(-this.location.x, 0, 0)); //this.container.style.paddingBottom = (this.scrollbar.offsetHeight + (parseInt(this.container.style.paddingBottom) || 0))+"px"; } else if ((this.location.x + this.scroller.offsetWidth) > this.element.offsetWidth-8) { // this.velocity.multiply(0); this.applyForce(new scrollr.Vector(this.element.offsetWidth-(this.location.x+this.scroller.offsetWidth), 0, 0)); } var friction = this.velocity.copyVector(); friction.multiply(-1); friction.normalize(); friction.multiply(2.5); this.applyForce(friction); this.velocity.add(this.acceleration); this.location.add(this.velocity); this.acceleration.multiply(0); this.scroller.style.marginLeft = this.location.x+'px'; this.element.scrollLeft = this.location.x/this.getMultiplier(); if (this.location.x == this.last_x) { this.timer.Stop(); } this.last_x = this.location.x; }; scrollr.Scrollbar.prototype.applyForce = function(force) { var new_force = force.copyVector(); new_force.divide(15.0); this.acceleration.add(new_force); } scrollr.addEvent = function(target, event_type, callback, bubble) { bubble = (typeof bubble !== 'undefined' ? bubble : false); if (typeof target.attachEvent !== 'undefined') { target.attachEvent('on'+event_type, callback); } else if (typeof target.addEventListener !== 'undefined') { target.addEventListener(event_type, callback, bubble); } } scrollr.removeEvent = function(target, event_type, callback, bubble) { bubble = (typeof bubble !== 'undefined' ? bubble : false); if (typeof target.detachEvent !== 'undefined') { target.detachEvent('on'+event_type, callback); } else if (typeof target.removeEventListener !== 'undefined') { target.removeEventListener(event_type, callback, bubble); } } scrollr.getAbsoluteElementOffset = function(element) { var offset_top = 0; var offset_left = 0; var obj = element; do { offset_top += obj.offsetTop; offset_left += obj.offsetLeft; } while (obj = obj.offsetParent); return { x: offset_left, y: offset_top }; } scrollr.getElementsByClass = function(search_element, element_name, class_name) { var elements = search_element.getElementsByTagName(element_name); var return_elements = []; for (element in elements) { if (elements[element].className == class_name) { return_elements.push(elements[element]); } } return return_elements; } scrollr.Loop = function(loop_time, target_callback) { this.start_time = new Date().getTime(); this.current_time = this.start_time; this.previous_time = this.start_time; this.elapsed_time = 0; this.delta_time = 0; this.loop_time = loop_time; this.is_running = false; this.Tick = function() { this.current_time = new Date().getTime(); this.delta_time = (this.current_time - this.previous_time); this.elapsed_time += this.delta_time; target_callback(this.delta_time); this.previous_time = this.current_time; if (this.is_running) { (function(_this) { setTimeout(function() { _this.Tick(); }, _this.loop_time-_this.delta_time)})(this); } }; this.Start = function() { if (!this.is_running) { this.start_time = new Date().getTime(); this.current_time = this.start_time; this.previous_time = this.start_time; this.elapsed_time = 0; this.delta_time = 0; this.is_running = true; this.Tick(); } }; this.Stop = function() { this.is_running = false; }; }; scrollr.Vector = function(x, y, z) { this.x = x; this.y = y; this.z = z; this.add = function(vector) { this.x += vector.x; this.y += vector.y; this.z += vector.z; }; this.subtract = function(vector) { this.x -= vector.x; this.y -= vector.y; this.z -= vector.z; }; this.multiply = function(multiplier) { this.x = this.x * multiplier; this.y = this.y * multiplier; this.z = this.z * multiplier; }; this.divide = function(divisor) { this.x = this.x / divisor; this.y = this.y / divisor; this.z = this.z / divisor; }; this.getMagnitude = function() { return Math.sqrt(this.x*this.y + this.y*this.y); }; this.copyVector = function() { return new scrollr.Vector(this.x, this.y, this.z); }; this.normalize = function() { var magnitude = this.getMagnitude(); (magnitude != 0 ? this.divide(magnitude) : ''); }; }; scrollr.addEvent(window, 'load', scrollr.doInit);