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.
Related
Images can explain better than words sometimes.
So I've a very weird problem with my self-written jquery tooltip (I actually want to avoid to use some lib, since my use-case is actually pretty simple and I don't need some bloated lib here).
When I move my mouse from right to left or from top to down everything is fine. When I move my mouse from left to right or bottom to top my tooltip gets stuttering - see the gif.
My tooltips are referenced by data attributes
HOVER ME
<div id="myTooltip">Tooltip Content Foo Bar</div>
To avoid problems positioning my element I'll move it later wit jQuery to the body.
Well, now I've now idea whats going on with my tooltip. Any ideas why it is stuttering?
BTW: This is happening in all modern browsers for me.
$(function () {
$('[data-tooltip]').each(function () {
$($(this).data('tooltip')).appendTo('body');
// this mouseenter listener could be safely removed, probably
// (don't forget to move the display:block part to mousemove tho)
$(this).on('mouseenter', function (e) {
$($(this).data('tooltip')).css({
display: 'block',
left: e.pageX,
top: e.pageY
});
});
$(this).on('mousemove', function (e) {
$($(this).data('tooltip')).css({
left: e.pageX,
top: e.pageY
});
});
$(this).on('mouseleave', function () {
$($(this).data('tooltip')).hide();
});
});
});
I think I found a solution for you. Might not really what you wanted but I think it will work for what you want to use it for.
Here is the JSfiddle: http://jsfiddle.net/nj1hxq47/3/
Ok so the key is to make sure the mouse never goes over the element you are dragging. So making sure you have at least 1 xp between the element you are dragging and the element you are hovering over will make sure it does not trigger the onleavemouse event.
var yPos = e.pageY + 5;
I am sure there is a better way to do this... but I hope this helps.
EDIT: The main problem is the mouse is going over the element you are moving to the mouse's position and thus triggering the onmouseleave event resulting in the element being hidden and shown in milliseconds of each other. Because the mouse leave event triggers before the move.
I have some problems with mouse events in a rich html application.
I have a big fat 'semi-transparent' div covering the half of the screen (damn designers). Let's call him A.
Behind this A div, there is a big container called B.
Inside B, there are 4 divs that should respond to mouseover and mouseout events. We can call them C1, C2, C3 and C4.
Unfortunately, the big fat A div blocks all my Javascript/jQuery events.
This could be solvable with some workarounds, but here's the thing:
This bug appears inside a homemade Javascript engine. I know B but I'm not supposed to know the C elements (or their ids) standing inside B.
So I can't use neither coordinates trick nor if/else workarounds.
The application should run on a TV (inside a weird version of opera). So no 'pointer-events' CSS trick.
Please don't tell me to redesign my app :)
I tried to handle (with and without jQuery) the event from A and trigger it to B. It works but then B doesn't forward it to its C children, and once more, I don't know them by advance.
Here is what you do. Most browsers support css pointer events.
On those browsers use:
#big-blocking-div {
pointer-events: none;
}
For browsers that don't support this css feature do this
#big-blocking-div {
display : none;
}
OR
inside tag: style="pointer-events: none;"
Since you have div1 which contains some HTML content that should listen to clicks and div2 that is overlapping it, you need to find the coordinates of the click and then click on the correct position based on that, via:
$(yourdiv).click(function(e) {
// element that has been clicked.
var elm = $(this);
// getting the respective
let x = e.pageX;
// coordinates of location.
let y = e.pageY;
let elementsToClick = document.elementsFromPoint(x, y);
for (let element of elementsToClick) {
//Implement the function below
if ((this !== element) && shouldBeClicked(element)) {
element.click();
}
}
});
I am trying to get this resizing object to work properly.
When MouseDown (holding), object resizes to 80px.
When release, I want the object to resize back to normal.
Problem:
As the object resizes from 100px to 80px on MouseDown, it may happen that the mouse is no more in the object itself, so releasing the mouse won't trigger the "resize back to normal" animation again.
That's why I tried to do a workaround with this:
if (global.mouseup) and ($('#myimage').width('80px'))
Complete code at:
http://jsfiddle.net/G8Ste/568/
Thanks for any help !
Bind a mouseup handler to the document that resizes the img back to normal:
$('#myimage').mousedown(function() {
var img = $(this);
img.stop().animate({
width: ['80px', 'swing'],
height: ['80px', 'swing'],
}, 50, 'swing');
$(document).one("mouseup", function(){
img.css({width:"",height:""});
});
});
Working demo: http://jsfiddle.net/G8Ste/569/
A couple of notes about your code.
You don't have a global variable defined, so you are getting an error there.
Instead of and, you must mean &&.
Edit: You can, of course, use the animation as you have in your original code. Demo here: http://jsfiddle.net/G8Ste/574/. The limitation of that is that you have to duplicate code, specifying the default width and height in the CSS and in the JavaScript. You can resolve that any number of ways, such as using the technique I describe in this answer, or using jQuery-UI's .switchClass() and related methods. Example using jQuery-UI:
$('#myimage').mousedown(function() {
var img = $(this);
img.stop().addClass("small", 50);
$(document).one("mouseup", function(){
img.stop().switchClass("small", "large", 150, function() {
img.removeClass("large", 1000);
});
});
});
Demo: http://jsfiddle.net/G8Ste/576/
Sorry if this might seem trivial for me to ask but..
I have some images and I need them to enlarge when I hover my mouse over them. But.. I want for the enlarged image to stick next to the pointer as I move it across the image. I don't know what to call it. I'm pretty sure it's only done with javascript, just css won't work here.
Something like this http://www.dynamicdrive.com/style/csslibrary/item/css-popup-image-viewer/ , but you know, it has to move with the pointer in motion.
What's the most effective way to do this?
The previous answers may be exactly what you're looking for, and you may already have this solved. But I note that you didn't mention jquery anywhere in your post and all of those answers dealt with that. So for a pure JS solution...
I'll assume from the way the question was phrased that you already know how to pop the image up? This can be done by coding an absolutely positioned hidden img tag in the html or generated on the fly with JS. The former may be easier if you are a JS novice. In my examples I'll assume you did something similar to the following:
<img src="" id="bigImg" style="position:absolute; display:none; visibility:hidden;">
Then you need an onMouseOver function for your thumbnail. This function must do three things:
1) Load the actual image file into the hidden image
//I'll leave it up to you to get the right image in there.
document.getElementById('bigImg').src = xxxxxxxx;
2) Position the hidden image
//See below for what to put in place of the xxxx's here.
document.getElementById('bigImg').style.top = xxxxxxxx;
document.getElementById('bigImg').style.left = xxxxxxxx;
3) Make the hidden image appear
document.getElementById('bigImg').style.display = 'block';
document.getElementById('bigImg').style.visibility = 'visible';
Then you'll need to capture the onMouseMove event and update the now un-hidden image's position accordingly using the same code you would have used in (2) above to position the image. This would be something like the following:
//Get the mouse position on IE and standards compliant browsers.
if (!e) var e = window.event;
if (e.pageX || e.pageY) {
var curCursorX = e.pageX;
var curCursorY = e.pageY;
} else {
var curCursorX = e.clientX + document.body.scrollLeft;
var curCursorY = e.clientY + document.body.scrollTop;
}
document.getElementById('bigImg').style.top = curCursorY + 1;
document.getElementById('bigImg').style.left = curCursorX + 1;
And that should just about do it. Just add an onMouseOut event to hide the bigImg image again. You can change the "+1" in the last two lines to whatever you like to place the image correctly in relation to the cursor.
Note that all of the code above was for demonstration purposes only; I haven't tested any of it, but it should get you on the right track. You may want to expand upon this idea further by preLoading the larger images. You could also forgoe capturing mousemove events by using setTimeout to update the position every 20 ms or so, though I think that approach is more complicated and less desirable. I only mention it because some developers (including me when I started) have an aversion to JS event handling.
I did something similar to this with a custom ColdFusion tag I wrote that would generate a floating div users could click and drag around the screen. Same principle. If you need me to I can dig that out to answer any additional questions in more depth.
Good luck!
Liece's solution is close, but won't achieve the desired effect of the large image following the cursor.
Here's a solution in jQuery:
$(document).ready(function() {
$("img.small").hover (function () {
$("img.large").show();
}, function () {
$("img.large").hide();
});
$("img.small").mousemove(function(e) {
$("img.large").css("top",e.pageY + 5);
$("img.large").css("left",e.pageX + 5);
});
});
The HTML is:
<img class="small" src="fu.jpg">
<img class="large" src="bar.jpg">
CSS:
img { position: absolute; }
Try this links [jquery with auto positioning]
1.Simple
http://jquery.bassistance.de/tooltip/demo/
2.Good with forum
http://flowplayer.org/tools/tooltip/index.html
if I understood you correctly you want to position your big image relatively to the cursor. One solution in jquery (i'm not 100% sure of the code here but the logic is there):
$('.thumb').hover(function(e){
var relativeX = e.pageX - 100;
var relativeY = e.pageY - 100;
$(.image).css("top", relativeY);
$(.image).css("left", relativeX);
$(.image).show();
}, function(){
$(.image).hide();
})
Jquery is the easiest route. position absolute is key.
^ In addition to the above, here is a working JS Fiddle. Visit: jsfiddle.net/hdwZ8/1/
It has been roughly edited so it isnt using just overall IMG css tags, easy for anyone to use with this now.
I am using this script instead of a Lightbox in my Wordpress client site, a quick zoomed in image with mouse over is much nicer IMO. It is very easy to make efficient galleries especially with AdvancedCustomFields plug-in & in the WP PHP repeater loops!
I am developing a modal dialog as a part of a web application. There is one thing that's been of a puzzle to me. Please watch a movie clip that I just uploded at http://inter.freetzi.com/example/. I feel strongly that I have to accompany my question with a video because this is the case when it's better to see once, than to hear 100 times.
(It could be vertical scrolling, or both vertical and horizontal at the same time. But I am using horizontal scrolling in my example, so watch for it.)
Here's about my question:
Width of the transparent mask affects the width of the page itself. But in Opera, for exemple, every time the window gets resized, the page gets width that is at most close to 'true'. While in IE, once the transparent mask has affected the width, afterwards the page remembers it and stays with it. What is the problem and how to settle it? How to make IE behave the way Opera does?
In my project, I do the following:
//curViewpointW and curViewpointH are current width and height of the viewpoint (current is meant to be the moment of the resize event)
oMask.style.width = curViewpointW + 'px';
oMask.style.height = curViewpointH + 'px';
var pageWH = getPageWH(); //getPageWH() is a function that gets current width and height of the page (with scrolling if there is any)
var curPageW = pageWH[0];
var curPageH = pageWH[1];
if (curPageW > curViewpointW) {
oMask.style.width = curPageW + 'px';
}
if (curPageH > curViewpointH) {
oMask.style.height = curPageH + 'px';
}
But IE ignores that somehow...
P.S. It's jQuery in my example, so many of you may have used its dialog before.
Have you looked into setting an onresize event handler that will adjust your mask dimensions when the window is resized? If you are using Prototype, you can set up such a handler unobtrusively like this:
Event.observe(document.onresize ? document : window, "resize", function() {//dostuff});
courtesy of the Roberto Cosenza blog