//
// Page Scroller
//
var page_scroller;
function make_page_scroller(min_val,max_val,curr_val,scrollbar_width,callback) {
document.write(make_page_scroller.template(scrollbar_width));
// Define scrollbar attributes.
Slider.SliderMin = 1;
Slider.SliderMax = max_val;
Slider.SliderBorderWidth = 2
// Define scrollbar
var fudge = Slider.isIE ? 6 : 2;
scrollbar_width += fudge;
// Define scrollbar slider.
var slider_e = get_ref('page_scroller');
var slider_width = slider_e.offsetWidth ? slider_e.offsetWidth : 20;
// Reset size of slider for small numbers
if (Math.floor(scrollbar_width / (slider_width + 2*Slider.SliderBorderWidth)) >= (Slider.SliderMax - Slider.SliderMin + 1)) {
slider_width = Math.floor(scrollbar_width / Slider.SliderMax);
}
slider_e.style.width = slider_width + "px";
// Determine number of units per pixel of scrolling.
var scale_width = (scrollbar_width - (slider_width + 2*Slider.SliderBorderWidth));
Slider.SliderScale = (max_val-Slider.SliderMin)/scale_width;
Slider.ScrollStep = 1/Slider.SliderScale;
// Define callback routine.
var scroller_action = function(n,done) {
if (callback) { callback(n,done); }
if (done) { // flag set when scrolling stops
// Set url page parameter to scroller value.
href=location.href.replace(/\&p=\d*/,'') + "&p="+Math.round(n)
// Add total number of rows to url to prevent server from recomputing.
if (window.NFound && NFound > 0) href += "&n="+NFound;
// Display next page.
location.href = href;
}
}
// Setup scrollbar.
var max_pos = scrollbar_width - (slider_width + 2*Slider.SliderBorderWidth);
if (max_pos < 0) max_pos = 0; // happens if slider width equals scrollbar (borders)
page_scroller = new Slider('page_scroller',max_pos,slider_e,scroller_action);
// Move to initial position.
page_scroller.set_val(curr_val);
page_scroller.move(page_scroller.slider_pos(curr_val));
}
make_page_scroller.template = function(scrollbar_width) {
return ''
+ '\n'
+ '
\n'
+ '\n'
+ '';
}
/*
* AcmePScroller v.8
* Control DHTML slider elements.
* Copyright (c) 2003,2006 Mackley F. Pexton. All rights reserved.
* This work based on AcmeSlider v1.3
* Send correspondence and feedback to: mack_pexton[at]acmebase[dot]com.
*/
// Set Slider configuration variables to the CSS style settings of the slider.
Slider.SliderBorderWidth = 2; // slider's border width
Slider.SliderScale = 1; // value per pixel of slider bar
// Set Slider Scroller configuration variables.
Slider.ScrollRate = 100; // Rate of scroll (milliseconds between iterations)
Slider.ScrollDelay = 500; // Initial delay before scrolling (milliseconds)
Slider.ScrollStep = 1; // Step of scroll
Slider.SliderMin = 0; // Minimum value of slider
// Slider working variables.
Slider.current_slider = null; // current activated slider control
Slider.callback_timer; // for IE
Slider.isIE = navigator.userAgent.match(/MSIE/) ? true : false;
// Slider object constructor.
function Slider(e,max,fld,callback) {
// Parameters:
// e -- slider element (element that slides on the scale)
// max -- maximum value of the slider (default is 100)
// fld -- optional form field used to track slider position
// callback -- optional function called with slider value when slider is moved
if (typeof e == 'string') e = document.getElementById(e);
if (fld == null) fld = new Object;
if (max == null) max = 100;
this.e = e; // slider object
this.fld = fld; // field or object to record slider position
this.max = max; // maximum value of slider (pixels)
this.callback = callback; // function called when slider is moved
this.on = false; // flag if slider is active or not
this.xdiff = 0; // offset difference between slider and container
// Copy global settings to object
this.SliderBorderWidth = Slider.SliderBorderWidth;
this.SliderScale = Slider.SliderScale;
// Copy slider scroller global settings to object
this.ScrollRate = Slider.ScrollRate;
this.ScrollDelay = Slider.ScrollDelay;
this.ScrollStep = Slider.ScrollStep;
this.SliderMin = Slider.SliderMin;
this.SliderMax = Slider.SliderMax;
this.saved_pos = 0;
this.saved_val = this.SliderMin;
document.body.parentNode.onmouseup = Slider.turn_off; // safety
}
// Class method for event handler
Slider.turn_off = function(evt) {
if (Slider.current_slider) Slider.current_slider.turn_off(evt);
Slider.current_slider = null;
}
Slider.prototype.next_pos = function(evt) {
var pos = (evt.pageX ? evt.pageX : evt.clientX) - this.xdiff;
if (pos < 0) pos = 0;
if (pos > this.max) pos = this.max;
return pos;
}
Slider.prototype.set_pos_val = function(pos) {
var val = this.slider_val(pos);
this.set_val(val);
}
Slider.prototype.set_val = function(val) {
if (this.fld.value) this.fld.value = val;
else if (this.fld) {
// Note: setTimeout is necessary when IE displays the slider in a frame.
if (Slider.isIE) { var e = this.fld; setTimeout(function(){e.innerText=val},1); }
else { this.fld.innerHTML = val; }
}
this.saved_val = val;
}
Slider.prototype.slider_val = function(pos) {
return Math.round(pos*this.SliderScale + this.SliderMin); // integer value
}
Slider.prototype.slider_pos = function(val) {
var pos = Math.round((val - this.SliderMin)/this.SliderScale); // integer value
if (pos < 0) pos = 0;
if (pos > this.max) pos = this.max;
return pos;
}
Slider.prototype.track = function(evt) {
// Track current position of slider
if (! this.on) return;
var pos = this.next_pos(evt);
this.set_pos_val(pos);
this.move(pos);
this._collapse_text_selection();
}
Slider.prototype.move = function(pos,done) {
if (isNaN(pos)) return;
// Move slider to position.
// Note: pos already assumed to be checked to be within its range.
this.e.style.left = pos + 'px';
// Call callback function notifying that the slider has moved.
if (this.callback) {
if (Slider.isIE) {
// HACK: IE has a timing problem when callback function assigns a
// new url to location.href (an initial intended purpose of this).
var obj = this;
var val = this.saved_val;
setTimeout(function(){obj.callback(val,done)},1);
}
else {
this.callback(this.saved_val,done);
}
}
// Hack, save pos so callback can be called in scroll_stop().
this.saved_pos = pos;
}
Slider.prototype.turn_on = function(evt) {
// Start tracking slider
var pos = parseInt(this.e.style.left,10);
if (isNaN(pos)) pos = 0;
this.xdiff = (evt.pageX ? evt.pageX : evt.clientX) - pos;
this._activate(evt);
}
Slider.prototype.move_and_turn_on = function(evt) {
evt = evt ? evt : window.event ? window.event : null;
var target = evt.target ? evt.target : evt.srcElement ? evt.srcElement : null;
// Note: this method is to be fired when mouse is clicked on the
// slider-bar-top or slider-bar-bottom elements which are enclosed
// by the slider-container element. It moves the slider to the position
// clicked and then follows the cursor. If the target is the slider-container
// element, it is because Netscape (v6-v7.1) fires the event when the
// mouse is clicked outside of the element, which is wrong. (!!)
// The problem apparently comes from Netscape keeping a flag if the mouse
// is down and clears it only if the original element that fires a
// mousedown fires the mouseup. Because the slider moves into place
// on a mousedown event, it is the slider that receives the mouseup
// and not the original element receiving the mousedown, so Netscape
// thinks the mouse is still down until the next click.
if (target.className == 'slider-container') return; // Netscape errant trigger workaraound
// Move the slider to the place on the slider bar where the mouse was clicked.
this.xdiff = target.offsetLeft + 10; // 10 is half of slider's width
this._activate(evt);
}
Slider.prototype.turn_off = function(evt) {
evt = evt ? evt : window.event ? window.event : null;
this.on = false;
if (evt) {
evt.cancelBubble = true;
if(evt.stopPropagation) evt.stopPropagation();
var pos = this.next_pos(evt);
this.move(pos,true);
this._collapse_text_selection();
this.set_pos_val(pos);
}
if (this == Slider.current_slider) Slider.current_slider = null;
}
Slider.prototype._collapse_text_selection = function() {
// Un-select text that might have been selected as the mouse moved.
if (window.getSelection) {
var sel = window.getSelection();
if (sel.removeAllRanges) sel.removeAllRanges(); // Moz
else if (sel.getRangeAt) sel.getRangeAt(0).collapse(true); // DOM
}
else if (document.selection && document.selection.empty) {
document.selection.empty(); // IE
}
}
Slider.prototype._activate = function(evt) {
// Start following mouse pointer with slider.
Slider.scroll_stop(); // safety
this.on = true;
Slider.current_slider = this; // register
this.track(evt);
evt.cancelBubble = true;
if(evt.stopPropagation) evt.stopPropagation();
}
/*
* Slider Scroll Methods
*/
// Slider scroller working variables.
Slider.scroll_timer; // setTimeOut() timer
Slider.scroll_sliders = []; // working array - list of sliders being scrolled
Slider.scroll_rate; // working variable - milliseconds between scroll
Slider.scroll_dir; // working variable - direction of scroll (-1 left, 1 right)
Slider.prototype.scroll = function(dir) {
// Scroll slider left or right
Slider.scroll_stop(); // safety
document.onmouseup = Slider.scroll_stop; // safety
// Save arguments for next scroll in global context
Slider.scroll_sliders = [ this ]; // one element array
Slider.scroll_dir = dir;
Slider.scroll_rate = this.ScrollRate;
Slider.scroll_move();
// Schedule next scroll
Slider.scroll_timer = setTimeout(Slider.scroll_next,this.ScrollDelay);
}
Slider.prototype.scroll_stop = function(evt) {
evt = evt ? evt : window.event ? window.event : null;
// Stop scrolling
clearTimeout(Slider.scroll_timer);
if (evt) {
evt.cancelBubble = true;
if(evt.stopPropagation) evt.stopPropagation();
}
this.move(this.saved_pos,true);
}
// Class method
Slider.scroll_next = function() {
Slider.scroll_move();
Slider.scroll_timer = setTimeout(Slider.scroll_next,Slider.scroll_rate);
}
// Class utility method to move all sliders a step.
Slider.scroll_move = function() {
// Recover scroller arguments from saved class variables
var slider;
for (var i = 0; i < Slider.scroll_sliders.length; i++) {
slider = Slider.scroll_sliders[i];
var val = slider.saved_val + (Slider.scroll_dir * 1);
if (val < slider.SliderMin) val = slider.SliderMin;
if (val > slider.SliderMax) val = slider.SliderMax;
slider.set_val(val);
slider.move(slider.slider_pos(val));
}
}
// Class method
Slider.scroll_all = function(dir) {
// Scroll a list of sliders left or right
Slider.scroll_stop(); // safety
document.onmouseup = Slider.scroll_stop; // safety
// Save arguments for next scroll in global context
Slider.scroll_sliders = [ ]; // initialize array
Slider.scroll_dir = dir; // scroll direction
Slider.scroll_rate = Slider.ScrollRate; // use global setting
for (var i = 1; i < arguments.length; i++) {
Slider.scroll_sliders[i-1] = arguments[i];
}
Slider.scroll_move();
// Schedule next scroll
Slider.scroll_timer = setTimeout(Slider.scroll_next,Slider.ScrollDelay);
}
// Class method
Slider.scroll_stop = function(evt) {
// Stop scrolling
clearTimeout(Slider.scroll_timer);
}