// Allow attaching to jQuery selectors $.fn.draggable = function() { makeDraggable(this); }; /** * This function makes an element movable around the page. * It supports mouse and touch input and allows whichever element * is specified to be moved to any arbitrary position. * * @param element */ makeDraggable = function(element) { var container = $(window); var diffX, diffY; function getCursorCoords(e) { var cursor = { x: e.clientX, y: e.clientY }; // Handle touchMove cases if (cursor.x === undefined) { cursor.x = e.originalEvent.touches[0].pageX; } if (cursor.y === undefined) { cursor.y = e.originalEvent.touches[0].pageY; } return cursor; } function startMoving(e) { // Prevent dragging dialog by clicking on slider // (could be extended for buttons, not sure it's necessary if (e.target.type && e.target.type === 'range') { return; } var elementTop = parseFloat(element.offset().top), elementLeft = parseFloat(element.offset().left); var cursor = getCursorCoords(e); diffX = cursor.x - elementLeft; diffY = cursor.y - elementTop; container.css('cursor', 'move'); element.css('cursor', 'move'); element.css({ cursor: 'move', left: elementLeft + 'px', top: elementTop + 'px', bottom: 'auto', // Setting these to empty doesn't seem to work in Firefox or Safari right: 'auto' }); $(document).on('mousemove', moveHandler); $(document).on('mouseup', stopMoving); $(document).on('touchmove', moveHandler); $(document).on('touchend', stopMoving); } function stopMoving() { container.css('cursor', 'default'); element.css('cursor', 'default'); $(document).off('mousemove', moveHandler); $(document).off('touchmove', moveHandler); } function moveHandler(e) { // Prevent dialog box dragging whole page in iOS e.preventDefault(); var elementWidth = parseFloat(element.outerWidth()), elementHeight = parseFloat(element.outerHeight()), containerWidth = parseFloat(container.width()), containerHeight = parseFloat(container.height()); var cursor = getCursorCoords(e); var elementLeft = cursor.x - diffX; var elementTop = cursor.y - diffY; elementLeft = Math.max(elementLeft, 0); elementTop = Math.max(elementTop, 0); if (elementLeft + elementWidth > containerWidth) { elementLeft = containerWidth - elementWidth; } if (elementTop + elementHeight > containerHeight) { elementTop = containerHeight - elementHeight; } element.css({ left: elementLeft + 'px', top: elementTop + 'px', bottom: 'auto', // Setting these to empty doesn't seem to work in Firefox or Safari right: 'auto' }); } element.on('mousedown', startMoving); element.on('touchstart', startMoving); };