window.parent jQuery selector not working in IE8 - javascript

This code below works fine
$('html').bind('mousewheel', function(event, delta) {
window.parent.scrollBy(-120 * delta,0);
return false;
});
but this one doesn't, can anyone tell me why. I'd love to know.
$(window.parent).bind('mousewheel', function(event, delta) {
window.parent.scrollBy(-120 * delta,0);
return false;
});
I'd like to clarify that the window selector doesn't work in this case either.

The problem may be that jQuery's event handler wrapper must use window.event to retrieve the current event in IE. If you set a handler from window A on an event in window B, the script in window A will be looking at window A's window.event, whilst the event is actually occurring on window B.
But there may be more issues than that, too. Cross-window/frame scripting is fraught with difficulties and jQuery is not particularly designed to work around them. To make jQuery work properly cross-frame you will generally need an instance of jQuery in both windows, and you should only use the corresponding instance of jQuery ($) to interact with each window.
eta re comment:
OK, having looked into mousewheel further, I don't know how your code can be working in Firefox (it certainly doesn't for me). Firefox doesn't support mousewheel events at all; instead it supports DOMMouseScroll events. Also for the other browsers that support mousewheel, it should be bound to a DOM Node rather than the window. So I guess what you're looking for is:
if ('MouseScrollEvent' in window) {
$(document).bind('DOMMouseScroll', function(event) {
return scroll(event.detail*-40);
});
} else {
$(document).bind('mousewheel', function(event) {
return scroll(event.wheelDelta);
});
}
function scroll(d) {
window.scrollBy(-d, 0);
return false;
};
(However in WebKit this will stop scrolling when the mouse moves out of the horizontal area corresponding to the viewport width. You may prefer to bind the events to the wider element like the div, if it fills the browser.)

Related

Mobile firefox click and hold events

I am trying to make simple webapp where an element can be clicked or hold to call different function.
$(document).on("click",'.element', function() {
clickFunction();
});
let timeoutId = 0;
$(document).on('pointerdown','.element', function() {
timeoutId = setTimeout(holdFunction, 500);
}).on('pointerup pointerleave', '.element', function() {
clearTimeout(timeoutId);
});
And it was tested and worked fine on Chrome, Firefox and mobile Chrome.
The problem is that on mobile Firefox the 'pointerdown' event is not called at all and i don't really know why.
It turns out that mobile firefox browser is not supporting pointer events.
To check if browser supports pointer events simply use
if (window.PointerEvent)
On mobile firefox one should use touch events (touchstart, touchend, etc.)
It is also worth mentioning that if you don't want to call holdFunction while holding element and scrolling the the same time, the code for pointer events given in the question will work fine but when using touch events you probably will need additional check if window was scrolled
$(window).scroll(function(event){clearTimeout(timeoutId);});

mouseleave event for document, with consideration for Chrome bug

I need to safely detect when the mouse leaves the window. I have jQuery included, so normally this would be fine:
$(document).on("mouseleave", function(event) {
doSomething();
});
However, there is a major bug in Chrome currently where this mouseleave function fires randomly when clicking in the element.
Normally, there's an easy work around for this:
$("#some-id").on("mouseleave", function(event) {
var e = event.originalEvent;
if (!e.relatedTarget || !e.toElement) {
// BUG in Chrome
return;
}
doSomething();
}
However, this doesn't work for document, or for any element when the mouse leaves the window, since in this case, e.relatedTarget and e.toElement are null exactly like when the bug occurs. So I'm trying to come up with something that will be able to safely determine when Chrome is acting up, and when the mouseleave event actually should fire.
Update: Just tried an approach with mouseout instead. The same chrome bug affects this event too, so no good. :/
UPDATE: this was apparently fixed, the Chrome issue was marked "fixed", and my tests show that the current version of Chrome no longer has the issue. :D
For now, this is the solution I came up with. Hopefully someday this major bug in Chrome gets enough attention to get a fix.
In the event that mouseleave occurs as a bug, it is usually almost immediately by the mouseenter event. So what I did here was just wait 1/10 of a second after the mouseleave event to make sure it's not a Chrome fluke.
var documentMouseLeaveTimeout = null;
$(document).on("mouseleave", function() {
documentMouseLeaveTimeout = setTimeout(function() {
doSomething();
}, 100);
});
$(document).on("mouseenter", function() {
clearTimeout(documentMouseLeaveTimeout);
});
Still hoping there's a better answer.
UPDATE: this was apparently fixed, the Chrome issue was marked "fixed", and my tests show that the current version of Chrome no longer has the issue. :D

JS - keyboard events - listen / unlisten

I have an issue concerning the keyboards events in JS.
First of all, please do not answer me to use jQuery methods, I know most of it (bind/unbind, on/off, one...) but I work with an internal framework that have to work without jQuery, even if jQuery is used on most of our projects.
So, I have a module, in fact a swipe tool based on Swipe.js and extended to work on web and mobile environments (compatibility needed for IE 7+, WebKit (Chrome & Safari), Moz, Opera and IE10 / Windows Phone)
In do not have any problem with mouse/touch events, the binding and unbinding methods inspired from the mobile HTML5 BP seems to work very well with a small correction for the detachEvents method.
And then I would to implement a keyboard control feature based on 'keydown' events.
(BTW, I am not sure to make a good difference between keydon and keypress events, except the keypressEvent.preventDefault() do not prevent the small scroll effect, so I use keydown.)
As it is possible to add many Swipes on the same page, I start to listen the keydown events only when any Swipe is focused (Note that I add a "tabindex" attribute to allow the element to get focused).
<div id="swipe1" class="swipe" tabindex='0'>
<ul>
[...]
</ul>
</div>
Then when the Swipe handle a 'touchstart' / 'click' / ' MSPointerDown' event,
I focus it :
onTouchStart: function(e) {
this.container.focus(); // Refers to the div#swipe1.swipe element
[...]
return false;
}
onFocus: function (e) {
if (this.activateKeyboardControls) { // Keyboard control is optional
this.addListener(document, 'keydown', this, true);
}
}
onBlur: function (e) {
if (this.activateKeyboardControls) { // Keyboard control is optional
this.removeListener(document, 'keydown', this, true);
}
}
But unfortunately, the removeListener does not work.
I mean, when the element loses the focus (blur event fired), it still handle the keydown events...
Is it because it is binded on the document object ?
I have read some solutions working with some booleans but I am looking for a cleaner way the manage it.
This is annoying, because when I give the focus to many Swipes, each of them is swiping when I press the keyboard.
I'm not sure of the reason why my answer has been deleted - more than 2 weeks after posting - but anyway, this is how I solved it :
It comes from the 'type' parameter of the addEventListener / attachEvent method, the first of one so...
I bind it on the object instead of on the window, and without bubbling.
var target = e.target || e.srcElement;
if (this.activateKeyboardControls) {
this.addListener(target, 'keydown', this, false);
}

`return false` in an event handler attached by addEventListener or element.on*

Right let’s get this out the way first. Yes, I want to hide the context menu. No, I’m not trying to prevent someone lifting content off my page. Its intended use is input for an in-browser game and it will be limited to a specific area on the webpage.
Moving from the ideological to the technical...
var mouse_input = function (evt) {
// ...
return false;
}
document.onmousedown = mouse_input; // successful at preventing the menu.
document.addEventListener('mousedown', mouse_input, true); // unsuccessful
Could someone explain to me why the addEventListener version is unable to stop the context menu from firing? The only difference I was able to see in Safari's Web Inspector was that document.onmousedown had a isAttribute value that was true whilst the addEventListener version had the same value as false.
So my unfruitful search suddenly became fruitful.
var mouse_input = function (evt) {
evt.preventDefault();
}
document.addEventListener('contextmenu', mouse_input, false);
Works for Safari, Firefox, Opera. preventDefault() stops the usual actions from happening. I had to change the event that was listened for to accommodate for Safari and it is more logical anyway. Further information: functions that implement EventListener shouldn’t return values so return false had no effect.
To explain the difference .. element.onmousedown = somefunction; is an absolute assignment; you are replacing the event handler on the element. element.addEventListener(...) is, as the name implies, adding a handler in addition to any handler(s) already attached for the event.

Capture mouse in Firefox

In IE exists .setCapture(); .releaseCapture() functions.
What's the equivalent of these functions in Firefox without using jQuery? (my client does not want to use it)
As it has been said above, Firefox does not offer this functionality, and you can work around it by monitoring events on the entire document. To be sure that there is no a better trick, I’ve just checked jQuery UI, and it appears they use the same approach. So for instance if you wanted to capture mouse movements when mouse is down in jQuery, you would do:
$("#someElement").
mousedown(function() { $(document).mousemove(captureMouseMove) }).
mouseup(function() { $(document).unbind("mousemove", captureMouseMove) });
function captureMouseMove(event)
{
// ...
}
https://developer.mozilla.org/en-US/docs/DOM/element.setCapture
setCapture and releaseCapture were added to Firefox 4 (with the release of Gecko 2) on March 22, 2011. However, WebKit (Chrome/Safari) still lacks these functions.
I believe element.setCapture() and document.releaseCapture() were added to Firefox as of FF4:
https://developer.mozilla.org/en/DOM/element.setCapture
"Call element.setCapture() method during the handling of a mousedown event to retarget all mouse events to this element until the mouse button is released or document.releaseCapture() is called."
To capture the mouse at anytime is not good behavior, I think that's why setCapture is not provided.
However, to capture the mouse for a drag-and-drop, you just need to handle the mouse events (mouse{up,down,move}) of the document object, which may be triggered when dragging even outside the client area.
<html>
<head>
<title>Capture test</title>
</head>
<body>
<script type="text/javascript">
document.onmousedown = function () {
state.innerHTML = "Dragging started";
};
document.onmousemove = function (e) {
coord.innerHTML = e.clientX + ',' + e.clientY;
}
document.onmouseup = function (e) {
state.innerHTML = "Dragging stopped";
}
</script>
<p id="state">.</p>
<p id="coord">.</p>
</body>
</html>
#JanZich's solution works great except it doesn't capture the mouse up event if the mouse is outside the element. This worked better for me:
$("#someElement").mousedown(function() {
$(document).mousemove(captureMouseMove);
$(document).mouseup(captureMouseUp);
});
function captureMouseMove(event) {
console.log("mouse move");
}
function captureMouseUp(event) {
console.log("mouse up");
$(document).unbind("mousemove", captureMouseMove);
$(document).unbind("mouseup", captureMouseUp);
}
Use event bubbling: add event listeners for the bubbling mouse events to a high-level container (possibly even document) and use a variable to track which element should be the capturing one.
Without further information on what you're trying to do, there's not really any more to say.
setCapture() and releaseCapture() are Internet Explorer specific non-standard methods. There is no implementation in Firefox. There is a framework called Gimme that gives you some mouse capture functionality. http://www.codeplex.com/gimme/
SetCapture and ReleaseCapture are IE propriatory functions as you've discovered. There is no native way to manipulate the content menu in the same way in Firefox.
It seems like it might be possible with Gimme which can be found at http://www.codeplex.com/gimme/Wiki/Recent.aspx. There is a blog post here: http://blog.stchur.com/2007/11/21/setcapture-with-gimme which describes one scenario of using this to replace the functions.
Use true as the third parameter of the addEventListener method to capture. For example:
document.addEventListener("click", function(event){location.hash=event.target}, true)
Use removeEventListener with the same parameters to release:
document.removeEventListener("click", function(event){location.hash=event.target}, true);
References
DOM Level 3 Event Flow
Netscape 6, Part III: The Event Model
Current Events: A Client Side Tipsheet
There is no such function in FF / JavaScript. The capture functions only exists in JScript.

Categories