Determine current mouse position in IFRAME? - javascript

I have an IFRAME inside an IFRAME and my getMousePosition method is not able to retrieve the current mouse position inside the iframe. It works in the first Iframe, but when I call the getMousePosition from a function in the parent document it returns fallback values 600 & 350. FYI: I am not able to control the content of the IFrame as it is generated, but it is not an cross domain access. Both IFRAMES and the parent document are hosted on the same server. I am only programming for Internet Explorer 8. So browser compatibility is not an issue.
function getMousePosition(){
if(!inframe)
$(document).mousemove(function(e){
mouseX = e.pageX
mouseY = e.pageY
});
else
{
mouseX = 600;
mouseY = 350;
}
//This is where I get the Iframe Document (I then parse through the document, picking up the specific links and storing them in the array verifiedlinks)
var src = window.frames[iframeindex].document.getElementsByTagName("a");
// This is where I call my function which uses the values returned by getMousePosition (verifiedlinks is an array of links inside the iframe):
verifiedlinks[i].onmouseover = function()
{
showPeopleDetails(this.getAttribute('username'));
}
// This should display User Details at the current Mousecoordinates
function showPeopleDetails(UserId){
var vpd = document.getElementById("PeopleDetails");
if ( vpd != null ) {
getMousePosition();
vpd.style.left=mouseX+10; //mouseX and mouseY are defined globally
vpd.style.top=mouseY+10;
vpd.style.display="block";
}
}
I have read this question: SOLVED QUESTION but the answer didn't solve my problem.
I found this question but none of the answers seem to be working for me.
My new edited code:
function showPeopleDetails(UserId, x, y){
var vpd = document.getElementById("PeopleDetails");
try
{
if ( vpd != null ) {
//getMousePosition();
//alert("MouseX: " +mouseX+" MouseY: "+mouseY);
//vpd.style.left=mouseX+10;
//vpd.style.top=mouseY+10;
vpd.style.left = x +10 - window.frames[2].document.body.scrollLeft;
vpd.style.top = y +10 - window.frames[2].document.body.scrollTop;
}
}

If you call getMousePosition from a parent window then document will point to the parent window document. You should call this method in the context of iframe. Also where is inframe defined and do you update its value on any event?
You can use jquery to attach the mouseover events to link. Using this you will get event object which provides the mouse x/y coordinates of the link relative to the document. I hope it will help you.
$(verifiedlinks[i]).mouseover(function(e){
showPeopleDetails($(this).attr('username'), e.pageX, e.pageY);
}
function showPeopleDetailsNow(UserId, x, y){
var vpd = document.getElementById("PeopleDetails");
if ( vpd != null ) {
getMousePosition();
//vpd.style.left=mouseX+10; //mouseX and mouseY are defined globally
//vpd.style.top=mouseY+10;
vpd.style.left= x +10 + $(document).scrollTop(); //mouseX and mouseY are defined globally
vpd.style.top= y +10;
vpd.style.display="block";
}
}

Related

Drag a profile image inside a div but it does not work in mobile

I have taken a codepen reference https://codepen.io/dsalvagni/pen/BLapab to drag a profile image. But it doesn't work in mobile. Getting this error in mobile "[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See ". I tried adding third parameter passive:false. But did not work. Can anyone please help me out. Thanks in advance!
Adding code snippet below that I tried to change so that it works in mobile.
$(window).on("mousemove touchmove", function (e) {
e.preventDefault();
if ($dragging) {
var refresh = false;
clientX = e.clientX;
clientY = e.clientY;
if (e.touches) {
clientX = e.touches[0].clientX;
clientY = e.touches[0].clientY;
}
var dy = clientY - y;
var dx = clientX - x;
dx = Math.min(dx, 0);
dy = Math.min(dy, 0);
/**
* Limit the area to drag horizontally
*/
if (self.model.width + dx >= self.model.cropWidth) {
self.model.x = dx;
refresh = true;
}
if (self.model.height + dy >= self.model.cropHeight) {
self.model.y = dy;
refresh = true;
}
if (refresh) {
render();
}
}
},{ passive: false });
Now I understood your question; to drag profile image. You meant as to pan it around.
So jQuery can't add support to passive listeners. The work around is to use native addEventListener. To support multiple events, I just add array with event names, then use forEach() to run both events.
['mousemove', 'touchmove'].forEach(evt =>
window.addEventListener(evt, function(e) {}, {
passive: false
})
This will remove the error, but then, still one more to change in the code as your reference is in dragStart() function. JQuery modified the original events, and store it in e.originalEvent. if you just use e.touches, there is no such object in e, you have to look inside e.originalEvent
Here is the full example with amendment to your reference code, because SO can't add more than 3000 characters

window.onmousemove and document.onmousemove doesn't capture iframe events [duplicate]

I have an iframe that takes up the entire window (100% wide, 100% high), and I need the main window to be able to detect when the mouse has been moved.
Already tried an onMouseMove attribute on the iframe and it obviously didn't work. Also tried wrapping the iframe in a div like so:
<div onmousemove="alert('justfortesting');"><iframe src="foo.bar"></iframe></div>
.. and it didn't work. Any suggestions?
If your target isn't Opera 9 or lower and IE 9 or lower you can use css attribute pointer-events: none.
I found it the best way just to ignore iframe. I add class with this attribute to iframe in onMouseDown event and remove in onMouseUp event.
Works perfect for me.
Iframes capture mouse events, but you can transfer the events to the parent scope if the cross-domain policy is satisfied. Here's how:
// This example assumes execution from the parent of the the iframe
function bubbleIframeMouseMove(iframe){
// Save any previous onmousemove handler
var existingOnMouseMove = iframe.contentWindow.onmousemove;
// Attach a new onmousemove listener
iframe.contentWindow.onmousemove = function(e){
// Fire any existing onmousemove listener
if(existingOnMouseMove) existingOnMouseMove(e);
// Create a new event for the this window
var evt = document.createEvent("MouseEvents");
// We'll need this to offset the mouse move appropriately
var boundingClientRect = iframe.getBoundingClientRect();
// Initialize the event, copying exiting event values
// for the most part
evt.initMouseEvent(
"mousemove",
true, // bubbles
false, // not cancelable
window,
e.detail,
e.screenX,
e.screenY,
e.clientX + boundingClientRect.left,
e.clientY + boundingClientRect.top,
e.ctrlKey,
e.altKey,
e.shiftKey,
e.metaKey,
e.button,
null // no related element
);
// Dispatch the mousemove event on the iframe element
iframe.dispatchEvent(evt);
};
}
// Get the iframe element we want to track mouse movements on
var myIframe = document.getElementById("myIframe");
// Run it through the function to setup bubbling
bubbleIframeMouseMove(myIframe);
You can now listen for mousemove on the iframe element or any of its parent elements -- the event will bubble up as you would expect.
This is compatible with modern browsers. If you need it to work with IE8 and below, you'll need to use the IE-specific replacements of createEvent, initMouseEvent, and dispatchEvent.
Another way to solve this that work well for me is to disable mouse move events on the iframe(s) with something like on the mouse down:
$('iframe').css('pointer-events', 'none');
and then, re-enable mouse move events on the iframe(s) on the mouse up:
$('iframe').css('pointer-events', 'auto');
I tried some of the other approaches above and they work, but this seems to be the simplest approach.
Credit to: https://www.gyrocode.com/articles/how-to-detect-mousemove-event-over-iframe-element/
MouseEvent.initMouseEvent() is now deprecated, so #Ozan's answer is a bit dated. As an alternative to what's provided in his answer, I'm now doing it like this:
var bubbleIframeMouseMove = function( iframe ){
iframe.contentWindow.addEventListener('mousemove', function( event ) {
var boundingClientRect = iframe.getBoundingClientRect();
var evt = new CustomEvent( 'mousemove', {bubbles: true, cancelable: false})
evt.clientX = event.clientX + boundingClientRect.left;
evt.clientY = event.clientY + boundingClientRect.top;
iframe.dispatchEvent( evt );
});
};
Where I'm setting clientX & clientY you'll want to pass any info from the content window's event to the event we'll be dispatching (i.e., if you need to pass something like screenX/screenY, do it there).
The page inside your iframe is a complete document. It will consume all events and have no immediate connection to it's parent document.
You will need to catch the mouse events from javascript inside the child document and then pass this somehow to the parent.
I have been faced with a similar issue, where I had div's that I wanted to drag around over an iFrame. Problem was that if the mouse pointer moved outside the div, onto the iFrame, the mousemove events were lost and the div stopped dragging. If this is the sort of thing you want to do (as opposed to just detecting the user waving the mouse over the iFrame), I found a suggestion in another question thread which seems to work well when I tried it.
In the page that contains the and the things you want to drag, also include a like this:
<div class="dragSurface" id="dragSurface">
<!-- to capture mouse-moves over the iframe-->
</div>
Set it's initial style to be something like this:
.dragSurface
{
background-image: url('../Images/AlmostTransparent.png');
position: absolute;
z-index: 98;
width: 100%;
visibility: hidden;
}
The z-index of '98' is because I set the div's I want to drag around to be z-index:99, and the iFrame at z-index:0.
When you detect the mousedown in the to-be-dragged object (not the dragSurface div), call the following function as part of your event handler:
function activateDragSurface ( surfaceId )
{
var surface = document.getElementById( surfaceId );
if ( surface == null ) return;
if ( typeof window.innerWidth != 'undefined' )
{ viewportheight = window.innerHeight; }
else
{ viewportheight = document.documentElement.clientHeight; }
if ( ( viewportheight > document.body.parentNode.scrollHeight ) && ( viewportheight > document.body.parentNode.clientHeight ) )
{ surface_height = viewportheight; }
else
{
if ( document.body.parentNode.clientHeight > document.body.parentNode.scrollHeight )
{ surface_height = document.body.parentNode.clientHeight; }
else
{ surface_height = document.body.parentNode.scrollHeight; }
}
var surface = document.getElementById( surfaceId );
surface.style.height = surface_height + 'px';
surface.style.visibility = "visible";
}
Note: I cribbed most of that from somebody else's code I found on the internet! The majority of the logic is just there to set the size of the dragSurface to fill the frame.
So, for example, my onmousedown handler looks like this:
function dragBegin(elt)
{
if ( document.body.onmousemove == null )
{
dragOffX = ( event.pageX - elt.offsetLeft );
dragOffY = ( event.pageY - elt.offsetTop );
document.body.onmousemove = function () { dragTrack( elt ) };
activateDragSurface( "dragSurface" ); // capture mousemoves over the iframe.
}
}
When dragging stops, your onmouseup handler should include a call to this code:
function deactivateDragSurface( surfaceId )
{
var surface = document.getElementById( surfaceId );
if ( surface != null ) surface.style.visibility = "hidden";
}
Finally, you create the background image (AlmostTransparent.png in my example above), and make it anything except completely transparent. I made an 8x8 image with alpha=2.
I have only tested this in Chrome so far. I need to get it working in IE as well, and will try and update this answer with what I discover there!
I found a relatively simple solution to this for a similar issue I was having where I wanted to resize the iframe and a long with a div sitting next to it. Once the mouse went over the iframe jquery would stop detecting the mouse.
To fix this I had a div sitting with the iframe both filling the same area with the same styles except for the z-index of the div (set to 0) and the iframe (set to 1). This allowed for the iframe to be used normally when not resizing.
<div id="frameOverlay"></div>
<iframe></iframe>
When resizing, the div z-index gets set to 2 and then back to 0 afterwards. This meant the iframe was still visible but the overlay was blocking it, allowing for the mouse to be detected.
On your "parent" frame, select your "child" iframe and detect the event you are interested, in your case mousemove
This an example of code to be used in your "parent" frame
document.getElementById('yourIFrameHere').contentDocument.addEventListener('mousemove', function (event) {
console.log(, event.pageX, event.pageY, event.target.id);
}.bind(this));
<script>
// dispatch events to the iframe from its container
$("body").on('click mouseup mousedown touchend touchstart touchmove mousewheel', function(e) {
var doc = $("#targetFrame")[0].contentWindow.document,
ev = doc.createEvent('Event');
ev.initEvent(e.originalEvent.type, true, false);
for (var key in e.originalEvent) {
// we dont wanna clone target and we are not able to access "private members" of the cloned event.
if (key[0] == key[0].toLowerCase() && $.inArray(key, ['__proto__', 'srcElement', 'target', 'toElement']) == -1) {
ev[key] = e.originalEvent[key];
}
}
doc.dispatchEvent(ev);
});
</script>
<body>
<iframe id="targetFrame" src="eventlistener.html"></iframe>
</body>
Here is my solution with jQuery. You can detect multiple events as I do below. Putting the .on() event handler inside the .on('load') event handler is necessary, because it would stop detecting the iframe content events when the iframe navigates to a new page otherwise. Additionally, I believe this only works if the iframe content is on the same domain as the parent page due to security, and there is no way around that.
$(document).ready(function() {
$('#iframe_id').on('load', function() {
$('#iframe_id').contents().on('click mousemove scroll', handlerFunction);
});
});
handlerFunction() {
//do stuff here triggered by events in the iframe
}
Basic way in document
var IE = document.all?true:false;
// If NS -- that is, !IE -- then set up for mouse capture
if (!IE) document.captureEvents(Event.MOUSEMOVE);
// Set-up to use getMouseXY function onMouseMove
document.onmousemove = getMouseXY;
// Temporary variables to hold mouse x-y pos.s
var tempX = 0;
var tempY = 0;
// Main function to retrieve mouse x-y pos.s
function getMouseXY(e) {
if (IE) { // grab the x-y pos.s if browser is IE
tempX = event.clientX + document.body.scrollLeft;
tempY = event.clientY + document.body.scrollTop;
} else { // grab the x-y pos.s if browser is NS
tempX = e.pageX;
tempY = e.pageY;
}
// catch possible negative values in NS4
if (tempX < 0){tempX = 0}
if (tempY < 0){tempY = 0}
// show the position values in the form named Show
// in the text fields named MouseX and MouseY
console.log(tempX, tempY);
return true;
}
Detect Mouse Move over Iframe
window.frames['showTime'].document.onmousemove = getMouseXY;
Detect Mouse Move over in Child Iframe under parent's Iframe
window.frames['showTime'].document.getElementById("myFrame").contentWindow.onmousemove = getMouseXY;
Trigger an IDLE detect function when no mouse move in Browser.
you can add a overlay on top of iframe when drag begin ( onmousedown event ) , and remove it when drag end ( on mouserup event ).
the jquery UI.layout plugin use this method to solve this problem.

Get absolute mouse position from inside iframe

I have a webpage with an iframe rendering another page (same domain). I need to get the mouse position in relation to the parent document. Keep in mind the iframe can scroll both ways. I've tried using offset with no luck.
$('#iframe').contents().find('html').on('mousemove', function (e) {
//gives me location in terms of the iframe but not the entire page.
var y = e.pageY;
//gives me 0
var y = $(this).offset().top;
//more code here....
})
One way to do it would be to get the position of the iframe in the parent window and add it to the mouse position relative to the iframe itself. Extending your code below,
var iframepos = $("#iframe").position();
$('#iframe').contents().find('html').on('mousemove', function (e) {
var x = e.clientX + iframepos.left;
var y = e.clientY + iframepos.top;
console.log(x + " " + y);
})
event.clientX, event.clientY do not work in every browser. However, jQuery has a solution which does. Also, what do you do when your iframe is inside another iframe? I have a solution which works cross browser with nested iframes.
GetPosition: function (event) {
var $body = $("body");
var offsetLeft = event.pageX - $body.scrollLeft();
var offsetTop = event.pageY - $body.scrollTop();
if (window != parent.window) {
// event was fired from inside an iframe
var $frame = parent.$("iframe#" + window.frameElement.id);
var framePos = $frame.position();
offsetLeft += framePos.left;
offsetTop += framePos.top;
}
if (parent.window != parent.parent.window) {
// event was fired from inside an iframe which is inside another iframe
var $frame = parent.parent.$("iframe#" + parent.window.frameElement.id);
var framePos = $frame.position();
offsetLeft += framePos.left;
offsetTop += framePos.top;
}
return [offsetLeft, offsetTop];
}
I wish this were a perfect solution. It works if your iframe is positioned in a fixed layout or absolutely positioned as a modal dialog. However, if your iframe is inside another absolutely positioned container, you will have to get the .position() of that container as well and add it to the total offsets.

Trigger mouse click by window offset in javascript [duplicate]

This question already has answers here:
How to simulate a click by using x,y coordinates in JavaScript?
(5 answers)
Closed 4 years ago.
How can I trigger mouse left button click by specifying X and Y pixels offset from upper left website corner via JavaScript?
Well, using just Javascript as you asked, you can use mouse events, as you can read X and Y properties to get coordinaties from the event object, for sample:
// mouse move
document.body.onmousemove = function(e) {
var x = e.X;
var y = e.Y;
console.log(e);
}
// mouse down
document.body.onmousedown = function(e) {
var x = e.X;
var y = e.Y;
console.log(e);
}
To simulate an mouse click, you can call the event onmousedown manually, but you have to provide the event parameter (passing the coordinates, etc..), for sample:
document.body.onmousedown({X:120, Y:120 /* other properties */});
bind onclick event on document body, Try this code
document.body.onclick = function(e){
if(e.clientX < 100 && e.clientY < 100){
// your code here
}
alert("X =" + e.clientX +" Y"+ e.clientY)
};
Use jquery mousemove to get the x y coords when moving and then fire the click within it if necessary. Something like:
$("body").mousemove(function( event ) {
if(event.pageX == 50 && event.pageY == 50)
{
$("targetclickelement").click();
}
});
Would be pretty inefficient though...
Edit - without jquery, use the same principle but with the handlers in Felipe Oriani's answer.
I don't believe you can do such a thing, you could however catch the click then check the offsets and call function if it is within range
$('#d').click(function(event){
if(event.offsetX > 50 && event.offsetX < 100 && event.offsetY > 100 && event.offsetY < 200)
{
/// Execute function
}
});
You can fire an element's click event, and you can get an element using x/y co-ordinates - so you could fire a click event on the element at x/y. Since you tagged jQuery:
$(document.elementFromPoint(x, y)).click();
https://developer.mozilla.org/En/DOM:document.elementFromPoint
Solution from How to simulate a click by using x,y coordinates in JavaScript?

How do I get the absolute position of a mouse click from an onClick event on the body?

I am trying to get the absolute position (top and left) of a mouse click relative to the browser/body, not any parent elements within the body.
I have a listener bound to the body, but e.pageX and e.pageY are giving me the position relative to a div.
Note that I can leverage jQuery and YUI functions.
Code that currently does not work correctly:
//getting the position
function _handleClick(e) {
var data = { absX: e.pageX, absY: e.pageY};
_logClickData(data);
}
//binding the function
var methods = {
init: function () {
$("body").click(_handleClick);
}
};
The commenter is correct. pageX and pageY give you the mouse position relative to the entire document not its parent div. But if you're interested you can get the position relative to the document from the position relative to a div.
Get the position of the parent div relative to the body, then add the two values.
x = parentdiv.style.left + e.pageX;
y = parentdiv.style.top + e.pageY;
(0,0)
_____________________
|
|
| __________
|----100----| |
| |---60---* |
| |__________|
|
|
* = Mouse Pointer
I made the diagram because it was fun. Not because I felt you needed one!!
Also, for the above to work you may need to parseInt.
According to this (http://docs.jquery.com/Tutorials:Mouse_Position), those should give you absolute positions. offsetX/Y gives you the relative position.
Edit November 2013: the original "Mouse Position" link seems to be broken, but the documentation for pageX contains an example that utilizes jQuery pageX/Y. The page about the offset method also contains relevant examples.
If I understood your question well this would be the solution
$("body").click(function(e){
var parentOffset = $(this).offset();
var relX = e.pageX - parentOffset.left;
var relY = e.pageY - parentOffset.top;
window.alert(relX);
window.alert(relY);
});
I guess you can use window.pageXOffset, window.pageYOffset property
document.body.addEventListener('click',(e)=>{
console.log(e.clientX + window.pageXOffset, event.clientY + window.pageYOffset)
}
)
The solution, hinted at by #Mrchief's link of http://docs.jquery.com/Tutorials:Mouse_Position, was to bind to the document and not the body element.
//binding the function
var methods = {
init: function () {
$(document).click(_handleClick);
}
};

Categories