📄 jsslider.js
字号:
/**
* JavaScript slider implementation.
*/
function JSSlider()
{
this._id = undefined;
this._horizontalLayout = undefined; // boolean
this._startPercent = undefined; // 0 to 100
this._endPercent = undefined; // 0 to 100 or undefined
this._rangeSlider = undefined; // boolean
this._numTicks = undefined; // non-negative integer
this._widgetWidth = undefined; // pixels
this._widgetHeight = undefined; // pixels
this._customImage = undefined; // will be stretched to fill ticks area
this._changeListener = undefined; // the name of the static function called when marker positions change
this._trackHidden = false; // if hidden, the ticks and image will consume the full space
var _imagelocation = "js/sliderimages"; // set image location
this._MaxVal = 100;
this._spacerImage = _imagelocation + "/spacer.gif";
this._ticksThickness = 4; // pixels
this._ticksMargin = 3; // pixels
this._tickColor = "#B7B6B3"; // style color
this._widgetMargin = 3; // pixels
this._ticksBeforeTrack = true; // boolean // TODO test this for custom images
this._horizontalMarkerImage = _imagelocation + "/slider-marker-h-point.gif";
this._horizontalMarkerWidth = 11; // pixels
this._horizontalMarkerHeight = 12; // pixels
this._verticalMarkerImage = _imagelocation + "/slider-marker-v-point.gif";
this._verticalMarkerWidth = 12; // pixels
this._verticalMarkerHeight = 11; // pixels
this._trackImageDimension = 6; // pixels (widths and heights, horiz. and vert.)
this._horizontalTrackStartImage = _imagelocation + "/slider-track-h-start.gif";
this._horizontalTrackMidImage = _imagelocation + "/slider-track-h-mid.gif";
this._horizontalTrackEndImage = _imagelocation + "/slider-track-h-end.gif";
this._horizontalTrackRangeImage = _imagelocation + "/slider-track-h-range.gif";
this._verticalTrackStartImage = _imagelocation + "/slider-track-v-start.gif";
this._verticalTrackMidImage = _imagelocation + "/slider-track-v-mid.gif";
this._verticalTrackEndImage = _imagelocation + "/slider-track-v-end.gif";
this._verticalTrackRangeImage = _imagelocation + "/Slider/slider-track-v-range.gif";
// event variable storage
this._dragInProgress = false;
this._dragX = undefined;
this._dragY = undefined;
this._dragLeft = undefined;
this._dragTop = undefined;
this._dragElement = undefined;
this._oldOnmousemove = undefined;
this._oldOnmouseup = undefined;
}
/**
* Renders a slider.
* @param id the unique ID used to identify this widget
* @param horizontalLayout true if a horizontal slider, false if a vertical slider
* @param numTicks a non-negative integer representing the number of tick marks that should be displayed
* @param widgetLength the number of pixels the widget consumes (slightly larger than the actual slider track size to account for marker margins)
* @param startPercent a defined number between 0 and 100
* @param endPercent either a defined number between startPercent and 100 or undefined if this isn't a range slider
* @param customImage optional URL to an image that will serve as a background for the tick marks (tick marks are not required for this to render)
* @param changeListener the name of the static function called when marker positions change (first parameter is a 0 to 100 value for the start marker, second parameter is undefined or 0 to 100 value for the end marker)
* @param trackHidden if hidden, the ticks and image will consume the full space (defaults to false)
*/
JSSlider.getInstance = function(id, horizontalLayout, numTicks, widgetLength, startPercent, endPercent, customImage, changeListener, trackHidden)
{
var newPeer = new JSSlider();
newPeer._id = id;
newPeer._horizontalLayout = horizontalLayout;
newPeer._numTicks = numTicks;
newPeer._startPercent = startPercent;
newPeer._endPercent = endPercent;
newPeer._rangeSlider = (endPercent != null);
newPeer._customImage = customImage;
newPeer._changeListener = changeListener;
newPeer._trackHidden = trackHidden;
if (newPeer._rangeSlider && (endPercent < startPercent) )
{
newPeer._endPercent = startPercent;
}
newPeer._initializeWidgetDimensions(widgetLength);
window[id] = newPeer; // register the object on the window for internal event access
return newPeer;
}
JSSlider.prototype.render = function()
{
var sb = new DhtmlStringBuffer();
this._appendTickMarks(sb);
if (!this._trackHidden)
{
this._appendTrackOutline(sb);
}
this._appendMarker(sb, this._startPercent, this._id + JSSlider._ID_START_MARKER);
if (this._endPercent)
{
this._appendMarker(sb, this._endPercent, this._id + JSSlider._ID_END_MARKER);
}
var rootElement = document.createElement("div");
rootElement.id = this._id + JSSlider._ID_WIDGET;
rootElement.style.position = "relative";
rootElement.style.width = this._widgetWidth + "px";
rootElement.style.height = this._widgetHeight + "px";
rootElement.innerHTML = sb.toString();
return rootElement;
}
JSSlider.prototype.destroy = function()
{
window[this._id] = undefined; // unregister the object from the window (was used for internal event access)
var element = document.getElementById(this._id + JSSlider._ID_WIDGET);
if (element != null)
{
element.style.display = "none";
var parent = element.parentNode;
if (parent != null)
{
parent.removeChild(element);
}
}
}
/**
* Changes the marker position(s).
* @param newStartPercent a defined number between 0 and 100
* @param newEndPercent either a defined number between startPercent and 100 or undefined if this isn't a range slider
* @param broadcastChange true if the change should be broacasted to the listener or not
*/
JSSlider.prototype.setMarkerPercent = function(newStartPercent, newEndPercent, broadcastChange)
{
var startPercent = newStartPercent;
var endPercent = newEndPercent;
if (this._rangeSlider && (endPercent != null) && (endPercent < startPercent) )
{
startPercent = newEndPercent;
endPercent = newStartPercent;
}
// move the start marker
this._startPercent = startPercent;
var top = this._getMarkerTop(this._startPercent);
var left = this._getMarkerLeft(this._startPercent);
var startMarker =
document.getElementById(this._id + JSSlider._ID_START_MARKER);
startMarker.style.top = top + "px";
startMarker.style.left = left + "px";
if (this._rangeSlider && (endPercent != null) )
{
// move the end marker
this._endPercent = endPercent;
top = this._getMarkerTop(this._endPercent);
left = this._getMarkerLeft(this._endPercent);
var endMarker =
document.getElementById(this._id + JSSlider._ID_END_MARKER);
endMarker.style.top = top + "px";
endMarker.style.left = left + "px";
}
if (this._rangeSlider)
{
// update the range bar
this._repositionRangeBar();
}
if (broadcastChange)
{
this._broadcastPositionChange();
}
}
JSSlider.prototype.markerKeyDown = function(element, event)
{
var trapEvent = false;
var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
var markerPercentSmaller, markerPercentLarger;
var pixelPercentage = 1; // the number of percentage points a pixel occupies
var startMarkerInFocus = true;
if (this._rangeSlider)
{
if (element.id.indexOf(JSSlider._ID_START_MARKER) == -1)
{
startMarkerInFocus = false;
}
}
if (this._horizontalLayout)
{
if (document.documentElement.dir == "rtl")
{
markerPercentSmaller = JSSlider._KEY_CODE_ARROW_RIGHT;
markerPercentLarger = JSSlider._KEY_CODE_ARROW_LEFT;
}
else
{
markerPercentSmaller = JSSlider._KEY_CODE_ARROW_LEFT;
markerPercentLarger = JSSlider._KEY_CODE_ARROW_RIGHT;
}
}
else
{
markerPercentSmaller = JSSlider._KEY_CODE_ARROW_DOWN;
markerPercentLarger = JSSlider._KEY_CODE_ARROW_UP;
}
switch (keyCode)
{
case markerPercentSmaller:
{
var currentStart = this._startPercent;
var currentEnd = this._endPercent;
var desiredStart = currentStart;
var desiredEnd = currentEnd;
if (startMarkerInFocus || !this._rangeSlider)
{
desiredStart = Math.max(0, desiredStart - pixelPercentage);
}
else
{
if (desiredEnd - pixelPercentage < desiredStart)
{
desiredStart = Math.max(0, desiredStart - pixelPercentage);
document.getElementById(
this._id + JSSlider._ID_START_MARKER).focus(); // swap focus
}
else
{
desiredEnd = Math.max(0, desiredEnd - pixelPercentage);
}
}
this.setMarkerPercent(desiredStart, desiredEnd, true);
trapEvent = true;
break;
}
case markerPercentLarger:
{
var currentStart = this._startPercent;
var currentEnd = this._endPercent;
var desiredStart = currentStart;
var desiredEnd = currentEnd;
if (startMarkerInFocus || !this._rangeSlider)
{
if (this._rangeSlider && (desiredStart + pixelPercentage > desiredEnd) )
{
desiredEnd = Math.min(100, desiredEnd + pixelPercentage);
document.getElementById(
this._id + JSSlider._ID_END_MARKER).focus(); // swap focus
}
else
{
desiredStart = Math.min(100, desiredStart + pixelPercentage);
}
}
else
{
desiredEnd = Math.min(100, desiredEnd + pixelPercentage);
}
this.setMarkerPercent(desiredStart, desiredEnd, true);
trapEvent = true;
break;
}
}
if (trapEvent)
{
if (event.cancelable)
{
event.stopPropagation();
event.preventDefault();
}
return false;
}
return true;
}
JSSlider.prototype.markerDragged = function(element, event)
{
this._dragInProgress = true;
this._dragX = event.clientX;
this._dragY = event.clientY;
this._dragLeft = parseInt(element.style.left);
this._dragTop = parseInt(element.style.top);
this._dragElement = element;
element.focus(); // so further keyboard navigation is allowed
if (document.all)
{
element.setCapture();
}
else
{
JSSlider.prototype.currentInstance = this;
window.sliderEventId = this._id;
window.captureEvents(Event.MOUSEMOVE | Event.MOUSEUP);
this._oldOnmousemove = document["onmousemove"];
document["onmousemove"] = this.markerMoved;
this._oldOnmouseup = document["onmouseup"];
document["onmouseup"] = this.markerReleased;
if (event.cancelable)
{
// or else the browser thinks you are dragging links or images around
event.stopPropagation();
event.preventDefault();
}
}
return false;
}
JSSlider.prototype.markerMoved = function(event)
{
var peer = this;
if (!document.all)
{
peer = JSSlider.prototype.currentInstance;
}
var element = peer._dragElement;
if (peer._dragInProgress)
{
if (peer._horizontalLayout)
{
element.style.left = peer._ensureMarkerLeftInRange(
peer._dragLeft + event.clientX - peer._dragX) + "px";
}
else
{
element.style.top = peer._ensureMarkerTopInRange(
peer._dragTop + event.clientY - peer._dragY) + "px";
}
if (event.cancelable)
{
// or else the browser thinks you are dragging links or images around
event.stopPropagation();
event.preventDefault();
}
peer._recalculatePercentages();
peer._broadcastPositionChange();
return false;
}
}
JSSlider.prototype.markerReleased = function(event)
{
var peer = this;
if (!document.all)
{
peer = JSSlider.prototype.currentInstance;
}
if (document.all)
{
peer._dragElement.releaseCapture();
}
else
{
window.releaseEvents(Event.MOUSEMOVE | Event.MOUSEUP);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -