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...