I have a drag-able mootools modal window.
The content of the window is a iFrame.
I drag the window from inside the iFrame. (it drags but shakes a lot during dragging)
Live link here.
Question:
- why this strange drag behaviour?
- the iFrame leaves its border, empty, on the origin place. How to avoid this?
Thankfull for ideas/tips on were to search for problem.
My code:
window.addEvent('domready',function() {
document.getElementById('iframe2_footer').addEventListener('mousedown', mouseDown, false);
window.addEventListener('mouseup', mouseUp, false);
});
function mouseUp()
{
window.removeEventListener('mousemove', divMove, true);
}
function mouseDown(e){
var div = parent.document.getElementById("price_info");
offY= e.clientY-parseInt(div.offsetTop);
offX= e.clientX-parseInt(div.offsetLeft);
window.addEventListener('mousemove', divMove, true);
}
function divMove(e){
var div = parent.document.getElementById("price_info");
div.style.position = 'absolute';
div.setPosition({ x: e.clientX-offX });
div.setPosition({ y: e.clientY-offY });
}
EDIT:
Just did some log to the e.clientX
and e.clientY
(Thank you @Nils for the idea) and got this:
...
450 -168
340 -218
460 -173
347 -221
468 -176
355 -224
478 -179
364 -226
483 -182
374 -229
...
Quite big steps. Any idea why?
As someone has already mentioned, I also do not see how this could be solved, at least without additional draggable block element outside of iframe. Maybe you're too focused on this specific problem so you have overlooked the possibilities of simple-modal plugin that you use. This plugin has implemented draggable effect, why not use it. If you open simple-modal.js file, in line 72 is html template for the plugin that looks like:
"<div class=\"simple-modal-header\"> \
<h1>{_TITLE_}</h1> \
</div> \
<div class=\"simple-modal-body\"> \
<div class=\"contents\">{_CONTENTS_}</div> \
</div> \
<div class=\"simple-modal-footer\"></div>"
Simply adjust the template to your preferences, so if you want to have a draggable footer, unlike the default header, try this:
"<div class=\"simple-modal-body\"> \
<div class=\"contents\">{_CONTENTS_}</div> \
</div> \
<div class=\"simple-modal-footer\"></div> \
<div class=\"simple-modal-header\"><h1>{_TITLE_}</h1></div>"
Apply some CSS and that's it, modal and draggable iframe without unnecessary complications.
EDIT:
Why this strange drag behaviour?
Simple test which shows where the problem is, put this code inside drag_test.php and iframe.php:
// script
window.addEventListener("mousemove", function(e) {
document.getElementById('mousepos').innerHTML = e.clientX+' - '+e.clientY;
});
// body
<p id="mousepos"></p>
Move the mouse around, and you'll see that one window does not knows for mouse position when the mouse is inside another window. This is because in DOM hierarchy is window object the top-level object.
The iFrame leaves its border, empty, on the origin place. How to avoid this?
Border that you see is left over from simple-modal div. When you set position: absolute;
to iframe it detaches the frame from container, so container remains on the original place.
Not sure why you are reinventing the wheel. You use MooTools. Use Drag + Drag.Move from MooTools-more:
http://jsfiddle.net/dimitar/bEdX8/
new Drag.Move(document.getElement('div.container'), {
handle: document.getElement('.dragme'),
modifiers: {
x: 'margin-left',
y: 'margin-top'
}
});
seems to work w/o any glitches.
also, your code is very laggy.
var div = parent.document.getElementById("price_info");
div.style.position = 'absolute';
div.setPosition({ x: e.clientX-offX });
div.setPosition({ y: e.clientY-offY });
this runs on every move? so first thing wrong: price info won't change. cache it.
position won't change. set it and forget it.
setPosition
is called twice when you can call it once:
div.setPosition({
y: e.clientY - offY,
x: e.clientX - offX
});
although you have the element - set div.style.left = nnn
; directly to avoid function calls at all.
AND offY
and offX
are global variables (bad) and every reference is 2 scope chains up... seriously, no wonder it is laggy. when you do low level stuff that needs to be performant, javascript needs be micro-optimised and you need to really apply yourself.
also, your code wont work in IE and you don't use the mootools api at all. element -> document.id('someid')
, events: element.addEvents({ event1: fn, event2: fn));
etc etc.
mootools does not just return an element. it also extends it in IELT9 and sets up element uid, storage etc.
if your objective is to be able to move the position of the iframe on a page with an unknown js framework and you need to bind this from within the iframe, then it's understandable what you are trying to do. same principles for perf need to apply, though.
You could try another strategy if you absolutely need to use an iframe. In the iframe :
window.addEvent('mousedown',function(e) {
var start={x:e.clientX,y:e.clientY};
window.addEvent('mousemove',function(e) {
window.parent.postMessage({dX:start.x-e.clientX, dY:start.y-e.clientY});
});
});
window.addEvent('mouseup',function(e) {
window.removeEvents('mousemove');
});
On the main window :
window.onMessage=function(event) {
// do something with event data
}
It should only work in some browsers, the most recent of course. Let me know if you succeed.