I reviewed @Naeem_Shaikh's answer, which is basically an improvement on the standard angular directive.
However, there is another problem with the standard angular draggable directive, which I was able to fix.
The standard directive imposes drag and drop on the entire dialog. On the one hand, this is what we want. We want to drag the whole dialogue. But this has an unfortunate side effect when clicks in different edit fields in the dialog box do not work: the default behavior is prevented! Somehow the buttons were encoded in the bootstrap to overcome this, but not the edit text fields. I assume that the authors did not consider my use case. But dialogs are more than just buttons!
This is difficult because you need to drag the entire dialog, but you only need to drag and drop, initiated by clicks in the heading "hot spot". In other words, the hot spot for initiating a drag is a subset of the area you want to drag.
Naeem's solution allowed me to make it work, so that only clicks in the header trigger a drag. Without its correction, the coordinate transformation was confused.
function clickedWithinHeader(event) { var target = event.currentTarget; var hotspot = null; var hotspots = target.getElementsByClassName("modal-header"); if (hotspots.length > 0) { hotspot = hotspots.item(0); } if (hotspot !== null) { var eY = event.clientY; var tOT = target.offsetTop; var y = eY - tOT; var hH = hotspot.offsetHeight; // since the header occupies the full width across the top // no need to check X. Note that this assumes the header // is on the top, which should be a safe assumption var within = (y <= hH); return within; } else { return true; } } // Draggable directive from: http://docs.angularjs.org/guide/compiler // Modified so that only clicks in the dialog header trigger drag behavior. // Otherwise clicking on dialog widgets did not give them focus. angular.module('drag', []).directive('draggable', function($document) { "use strict"; return function(scope, element) { var startX = 0, startY = 0, x = 0, y = 0; element= angular.element(document.getElementsByClassName("modal-dialog")); element.css({ position : 'fixed', cursor : 'move', }); element.on('mousedown', function(event) { // // OK, where did they touch? Only want to do this // // when they clicked on the header. if (!clickedWithinHeader(event)) { return; } // Prevent default dragging of selected content event.preventDefault(); ...
Note that clickedWithinHeader () logic only works with Naeem enhancement. This may be the best way to do this, but it works. Only clicks in the header trigger the drag and drop and clicks elsewhere do what they need to do.
However, this was not the whole answer, since the standard directive also superimposed the move cursor on the entire dialog, which is very confusing, even if, or especially if you cannot drag it to where it appeared.
Removing this element from element.css in the directive:
element.css({ position : 'fixed', });
and bind the move cursor only to the modal header using CSS
.modal-header { cursor: move; }
provides a complete solution.