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>Or to within another DOM element:</h3>
<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>

<br><br><br><br><br><br>
<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 #ccc;
	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: 600px; 
	height: 90px; 
	border: 0px solid #ccc; 
	padding: 0px; 
	background: lightGray;
	margin: 0 0 0 0;
}

#metaSlider {
	width: 600px;
}

JavaScript

// my code ===============

var dataRange = {
	start: /*1494348611,*/ 1494288000000,
	end: /*1525884611*/ 1525824000000
};
//debugger
var dataDiff = dataRange.end - dataRange.start;
var trackWidth = $('.track').width();
var $thumb = $('#thumb');
var getThumbWidth = function() {
  return $('#thumb').width();
}
console.log("dataDiff=", dataDiff, "trackWidth=", trackWidth, "thumbWidth=" + getThumbWidth());

function getStartDate(/*ui*/left) {
	//var startEpoch = dataRange.start + ui.position.left/trackWidth*dataDiff;
	var startEpoch = dataRange.start + left/trackWidth*dataDiff;
	return startEpoch;
}

function getEndDate(/*ui*/left) {
	//var endEpoch = getStartDate(ui) + getThumbWidth()/trackWidth * dataDiff;
	var endEpoch = getStartDate(left) + getThumbWidth()/trackWidth * dataDiff;
	return endEpoch;
}

function onDrag(e, ui) {
		//$('#offsetX').text(ui.position.left);
		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 $thumb = $('#thumb');

$('#thumb').draggable({ 
	//containment: ".track", 
	//containment: 'parent',
	containment: containment,
	scroll: false,
	axis: "x",
	drag: onDrag,
	start: onDrag
});

// trigger seems to not work?
// $thumb.trigger('drag', {position: {left: 100, top: 100}});

var fakeDragEvent = $.Event("drag");
$thumb.css('left', 500);
//$thumb.draggable('option',...