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();
}
}
});
Related
When hovering over an element and then refreshing the page (without moving the mouse):
Chrome does not fire the mouseenter event on page load
Firefox does fire the mouseenter event on page load
Below is an example snippet. To reproduce the issue, hover over the div and then refresh the page. In Chrome, the div does not contain "mouseenter". In Firefox, it does.
Note that this does not work in the Stacksnippets environment since you need to click "run snippet" first. JSFiddle: https://jsfiddle.net/9fu6cx5d/7/
let div = document.getElementById('my-div');
div.addEventListener('mouseenter', function () {
div.innerHTML = 'mouseenter';
});
#my-div {
width: 150px;
height: 150px;
background-color: #aaaaaa;
}
<div id="my-div">
</div>
Which browser has the correct behaviour? How can I work around the difference in behaviour or at least make them both behave the same?
Chrome version: 59.0.3071.115 (Official Build) (64-bit)
Firefox version: 54.0 (64-bit)
As pointed out in the comments, Chrome's behavior is the correct one according to the specs. Below is an idea on how to work around the difference.
You can make sure you get the value right by checking whether the mouse is inside the bounds of the div on document load. Unfortunately there is no way in JS to check the mouse position without firing events, so you will have to resort to some hack involving CSS hover rules and checking against them on $(document).ready.
To quote this hilarious answer:
Overlay your page with a div that covers the whole document. Inside
that, create (say) 2,000 x 2,000 elements (so that the :hover
pseudo-class will work in IE 6, see), each 1 pixel in size. Create a
CSS :hover rule for those elements that changes a property (let's
say font-family). In your load handler, cycle through each of the 4
million elements, checking currentStyle / getComputedStyle() until
you find the one with the hover font. Extrapolate back from this
element to get the co-ordinates within the document.
N.B. DON'T DO THIS.
While you definitely shouldn't do this, the general idea of using non-effective hover styles for the sake of checking if an element is hovered without needing JS events is a good one if you just need to work around browser quirks. I'm using font-weight in the example below, but you can change it to whatever works for you.
The css
#my-div:hover {font-weight:700;}
The js
// Pseudocode!
var mouseIsInside = false,
div = $('#my-div');
$(document).ready(function(){
if (div.css('font-weight') === 700) {
mouseIsInside = true;
}
doStuffIfMouseInside();
});
div.on('mouseenter', function(){
mouseIsInside = true;
doStuffIfMouseInside();
})
function doStuffIfMouseInside() {
if (mouseIsInside) {
...
}
}
If you add (function(){})(); around your code it seems to work in both browsers.
It seems that firefox might be firing events before the dom is available causing problems with mousein/out events.
See: https://jsfiddle.net/9fu6cx5d/8/
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.
It is fairly easy to find the location of a div, when you know the div name. But is there an easy way to get the div id when all I know is the X/Y cords of the screen?
There will be no overlapping divs within a range of divs named '#Items1' to '#Items50' on a board (another div) called #HarbourRadar. Each div #Items can have more than one stacked image in it.
Anyway any hint to find the div out from a location would be greatly appreciated.
The following code (taken from the answer below on this side) gets the id of the div #HarbourRadar, that is partially right since the div #marker is layered ontop on that one, but does not return the div #marker that is selected - ie one with a higher Z-index.
var pos = $("#marker").position();
alert(document.elementFromPoint(pos.left, pos.top).id);
Yeah, it is possible using the document.elementFromPoint method.
This is how it is documented by Microsoft.
Here is Mozilla documentation.
The function is almost fully compatible, as you can see in this browser comparison.
Here is some sample code from MDN docs:
function changeColor(newColor) {
elem = document.elementFromPoint(2, 2);
elem.style.color = newColor;
}
<p id="para1">Some text here</p>
<button onclick="changeColor('blue');">blue</button>
<button onclick="changeColor('red');">red</button>
have a look at this existing StackOverflow conversation you may find this helps:
Determine which element the mouse pointer is on top of in Javascript
This is using a javascript function document.elementFromPoint and has a great demo that shows a working example.
The jsFiddle URL is: http://jsfiddle.net/MPTTp/
Code from the fiddle:
$(window).click(function(e) {
var x = e.clientX, y = e.clientY,
elementMouseIsOver = document.elementFromPoint(x, y);
alert(elementMouseIsOver);
});
I am teaching myself web programming. I'm also working on C++. I am having a problem with Javascript.
I need to know how to create an "if statement" based on the location of an image.
I am making a simple game that has a cannon that is moving back and forth. I want the user to press a button that will cause the cannon to stop and fire launching another image toward the target.
I have already created the images and a gif of the image that will travel from the cannon in an arc toward the target.
If the user fires when the cannon is in the correct position the image will hit the target.
Can someone tell me how to create an if statement based on position? Or can someone tell me how to make the cannon stop and make the gif appear?
To move the cannon, read up on the onkeyup() event - it will wait for when a key is released, and do something.
What will it do? Probably change the left position of the cannon somehow. I'd recommend setting the CSS style position:absolute on your cannon, then changing the .left property with Javascript.
For example, here's some Javascript to get you started (untested):
var cannon = document.getElementById("cannonPic");
var leftlim = 200;
document.body.onkeyup = function() {
// Remove 'px' from left position style
leftPosition = cannon.style.left.substring(0, cannon.style.left - 2);
// Stop the cannon?
if (leftPosition >= leftLim) {
return;
}
// Move cannon to new position
cannon.style.left = cannon.style.left.substr(0, cannon + 10);
}
And its companion HTML would look like...
...
<img id='cannonPic' src='cannon.jpg' />
...
<script type='text/javascript' src='cannon.js' />
The HTML could be styled like this:
#cannonPic {
left:0;
position:absolute;
}
To answer your "appear/reappear" sub-question, you can use the .display property, accessed via Javascript:
var cannon = document.getElementById("cannonPic");
function appear() {
cannon.style.display = '';
}
function hide() {
cannon.style.display = 'none';
}
A small word of warning, things traveling in arcs will require some math to translate them in two dimensions, depending on how accurate you want it. A fun exercise though if you like math :)
To get the very first image on your page's x and y position on the screen, for instance, try:
var xpos = document.getElementsByTagName('img')[0].x;
var ypos = document.getElementsByTagName('img')[0].y;
Just to add a little background, the way this is typically done:
You have a main loop that will "run" the game.
Each iteration of the loop, you a) update the positions of in-game objects (cannon, projectiles, and targets in your case) and b) render the resulting objects to the screen.
When you detect a "fire" keypress, you simply set the "speed" of your moving cannon to 0, causing it to "stop".
You can retrieve the object's position using Steve's or sajawikio's approach but your game logic determines (and should know) the position of all objects at all times. It is your game logic that says "draw the projectile at position (x,y)". Your game logic should NOT say "I have a projectile, not sure exactly where it is, HMM, so let's query it's position using Javascript". At least not in this case where you have simple, predictable movement.
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!