implementing a slider with proportional-width thumb using jquery-ui draggable
1. a 2nd slider controls the thumb width 2. slider displays start and end dates, in a demo of using slider as a date picker 3. all implemented on top of jquery-ui "draggable" 4. biggest hack is the option "containment". The natural thing for "containment" is to use the "parent" or named selector option, but these only slide up to 1 pixel shy of the max width of the track. So I use another containment option, an array of 4 numbers, but the setting of those numbers is kludgy
by hrabinowitz
HTML
<h3>implementing a slider with proportional-width thumb using jquery-ui draggable</h3>
<h3>within another DOM element:</h3>
<table>
<tr>
<td>
a rather long label
</td>
<td>
<div id="track" class="track">
<div id="thumb" class="draggable ui-widget-content">
<p>ui.position.left=<span id="offsetX"></span></p>
<div id="startDisplay">
xx
</div>
<div id="endDisplay">
yy
</div>
<div id="startTimeDisplay">
xx:00
</div>
<div id="endTimeDisplay">
yy:00
</div>
</div>
</div>
</td>
</tr>
</table>
<br><br><br><br><br><br>
<h4>
Choose a range within the dataRange. Thumb is proportional to the ratio
</h4>
<select name="rangeMillis" id="rangeMillis">
<option value="86400000">1 day</option>
<option value="604800000">1 week</option>
<option value="2592000000">30 days</option>
<option value="15768000000">half year</option>
<option value="31536000000">1 year</option>
</select>
<h4>
Use the 2nd slider to adjust the % width of the first slider thumb
</h4>
<div id="metaSlider">
<div id="meta-handle" class="ui-slider-handle">
</div>
</div>
CSS
.draggable {
position: absolute;
width: 100px;
height: 90px;
/*padding: 0.5em; */
float: left;
/*margin: 0 10px 10px 0;*/
margin: 0 0 0 0;
padding: 0;
background: yellow;
border: .5px solid orange;
cursor: ew-resize;
}
#startDisplay {
margin-top: 50px;
}
#endDisplay {
/*margin-top: 50px;*/
float: right;
}
#startTimeDisplay {
margin-top: 12px;
width: 250px;
text-align: left;
}
#endTimeDisplay {
float: right;
text-align: right;
width: 250px;
}
.track {
position: relative;
width: 500px;
height: 90px;
border: 0px solid #ccc;
padding: 0px;
background: lightGray;
margin: 0 0 0 0;
}
#metaSlider {
width: 600px;
}
JavaScript
// my code ===============
"use strict";
/**
* timeRangeSlider is a slider whose thumb is proportional
* to a given timeRange within a dataRange, and whose slide
* events pick a start and end time.
* When initializing, pass in options that include
* dataRange (object with start, end)
* $track (a jquery selection of the track div)
* $thumb (a jquery selection of the thumb div)
*/
var timeRangeSlider = function(options) {
var dataRange = options.dataRange;
var dataDiff = dataRange.end - dataRange.start;
//var trackWidth = $('.track').width();
var trackWidth = options.$track.width();
//var $thumb = $('#thumb');
var $thumb = options.$thumb;
var getThumbWidth = function() {
return $thumb.width();
}
console.log("dataDiff=", dataDiff, "trackWidth=", trackWidth, "thumbWidth=" + getThumbWidth());
function getStartDate(left) {
var startEpoch = dataRange.start + left/trackWidth*dataDiff;
return startEpoch;
}
function getEndDate(left) {
var endEpoch = getStartDate(left) + getThumbWidth()/trackWidth * dataDiff;
return endEpoch;
}
function onDrag(e, ui) {
if (ui instanceof HTMLElement) {
var left = +$(ui).position().left;
} else {
var left = +ui.position.left;
}
$('#offsetX').text(left);
var startEpoch = getStartDate(/*ui*/left);
var endEpoch = getEndDate(/*ui*/left);
$startDisplay.text(startEpoch);
$endDisplay.text(endEpoch);
var startDate = new Date(startEpoch);
var endDate = new Date(endEpoch);
$startTimeDisplay.text(startDate.toUTCString());
$endTimeDisplay.text(endDate.toUTCString());
//console.log("endEpoch-startEpoch=", endEpoch - startEpoch);
//console.log("e=", e, "ui=", ui);
}
var $metaHandle = $('#meta-handle');
var $startDisplay = $('#startDisplay');
var $endDisplay = $('#endDisplay');
var $startTimeDisplay = $('#startTimeDisplay');
var $endTimeDisplay = $('#endTimeDisplay');
//var containment = [8, 0, 508, 90];
var trackOffset = $('.track').position().left;
var...