I have an application that works like a virtual desktop (icons in a horizontal bar in the bottom). When you click on an icon, a window opens (dynamically created). If you click on another (or the same) icon another window opens 10px down and 10px to the right from the last one, and is moved on the top.
When a window gets created, the function below runs adding a click event to the window. If the window is clicked it gets moved to the top.
Now to the problem. One of the windows contains thumbnails of images. When clicking on an image a new window gets created with the image in full size. I want the new window with the full size image to be placed on top, which doesn't happen because the event (in the moveOnTop function) fires after the new window is created on the thumbnail window (because I clicked that window when I clicked on a thumbnail).
I guess one way to solve this would be if it was possible to prevent the event to be fired if a thumbnail is clicked, though I don't know how. What could otherwise be a good way to solve this? Thanks in advance!
Windows.prototype.moveOnTop = function(){
var container = '#desktop';
$(container).on('click', '.window', function() {
var thisWindow = $(this);
if(thisWindow.next().length > 0){
thisWindow.appendTo('#desktop');
}
});
};
Inside the click event handler for thumbnails you can cancel the the event for other (parent) elements:
$("img.thumbnail").on("click", function(e) {
...
// Finally, prevent the click event from bubbling up to parent elements
e.stopPropagation();
});
See: event.stopPropagation()
That depends on the situation. If both cases are handled by the same event handler, you can simply compare against event.target.
If, on the other hand, you've bound another event handler to the click event of the icon and you're trying to prevent the window's click event from firing when an icon is clicked, you can either let the event handler return false or call event.stopPropagation(), like so:
$('.icon').click(function(event) { // <-- parameter 'event' is automatically passed to handlers
// Open window with icons
event.stopPropagation();
});
NB: from what I can tell, you're still (re-)attaching the click handler to all windows in the moveOnTop function. See my answer to your previous question for a solution.
Related
I'm trying to implement the following functionality and am having some trouble. What I want is when a user clicks a certain image, a popup div will appear containing some information about that image. Then if the user were to click anywhere on the page outside of that popup div, it would simply hide and then remove the popup.
What I am trying to do is register an eventListener after the popUp div is added to the page. Tried with both jquery and without and am after the same issue. (I included both below but only one is active in the code at a time.)
createProfilePopUpEventListener: function(){
$('body').on('click', function(){
$('.profile_pop_up').fadeOut('fast').remove();
});
},
createProfilePopUpEventListener: function(){
var el = document.getElementsByTagName('body')[0];
el.addEventListener("click", $('.profile_pop_up').fadeOut('fast').remove();
},
showPopUp: function(e){
//creates popUp and adds it to the DOM
this.createProfilePopUpEventListener();
}
What seems to be happening is that the event is being triggered right away on the initial click to show the popup and thus it is never displayed. How can I create an eventListener that only starts listening for those clicks at a certain time?
I guess your problem is event propagation. Your image that is used as the trigger to open the popup bubbles your event up the whole DOM, eventually to the body. Thus the fadeout/remove event is triggered at the same time as your open event.
You will need to stop the propagation of that in such a fashion (using :
$('#popup_trigger').on('click', function(event){
event.stopPropagation();
$('.profile_pop_up').fadeIn();
});
Some code that looks like the following is firing the click event via the Enter key, but is not responding to the mouse click.
//a is an anchor element
a.addEventListener('click', function (e)
{
//Do Stuff...
});
This page demonstrates the problem. The relevant bit of code is at line 176. This is in the middle of development and currently only (sort of) works in Chrome.
Also, I just verified that it works if I use mousedown, so it's not just the case of an invisible element sitting in front of the anchor.
Any ideas?
Edit: Now that you've shown us the actual code you're using, the problem is related to the fact that the autoSuggest() function has it's own click handler and in that click handler, it is clearing the container which removes all <a> elements in the container so your link object gets destroyed (probably before your click event gets to process). So, you can get events that happen before the click (like mousedown), but after a click, the element is removed from the DOM.
If you tell us what you're trying to actually do when an auto-suggest item is clicked that is different than the default behavior of the autoSuggest() function and you point to any documentation for that function, then perhaps we could offer a better way to solve your issue.
The link may be firing and taking you off to a new page (or reloading the current page), thus preventing you from seeing the click code run. Usually when you process a click event on a link element, you need to prevent the default behavior:
//a is an anchor element
a.addEventListener('click', function (e) {
e.preventDefault();
//Do Stuff...
});
Another possibility is that you are trying to install the event handler too soon either before the DOM has been loaded or before this particular link has been created and thus no actual click event handler is attached to the DOM object. You can verify whether the event handler is even getting called by temporarily putting an alert("Click handler called"); in the event handler and see if that pops up or not.
Within my Firefox extension I'm trying to keep track when the window is actually the active window. For this, I add the following two listener to the window:
window.addEventListener("deactivate", function(event) { alert("deactivate"); }, false);
window.addEventListener("activate", function(event) { alert("activate"); }, false);
Basically everything works fine. When I toggle between different windows, or minimize/maximize Firefox, the events fire quite as I would expect it. However, both events also fired when I move the window even if it is already active. When I start moving the window, the "deactivate" event is fired; when I stop moving and release the mouse button, the "activate" event is fired. I have no idea how can I detect and ignore this behavior. Intuitively, the window is all the time active.
I tried to check before I handle the "deactivate" event if the mouse button is pressed. However, adding a "click" event listener to the window seem not to include the window's title bar. Anyone any idea how I can distinguish beween "really" de-/activating the window and moving the window? Thanks a lot in advance!
You can use this answer to detect the browser position on the screen. If you do this at the start you can compare if they are changing.
Something like when the page loads:
var x,
y,
win = window;
if(win.screenTop !== undefined) {
x = win.screenleft;
y = win.screenTop;
} else {
x = win.screenX;
y = win.screenY
}
and compare those values to the current values when your events triggers.
(Note that this only works when the position of the window changes)
I have a help popup that I want to close when somewhere else is clicked. Here's what I have:
$('.help[data-info]').click(function(){
$('.info[a complicated selector]').toggle(400);
$('*:not(.info[the complicated selector]).one('click','',function(){
.info[the complicated selector].hide(400);
});
})
But one() isn't what I want before it fires for each element on the page. I only want it to fire once.
It looks like you are attaching event handlers to every element in your dom except the help popup? Hmm...
How about this:
Create a single "mask" div that overlays the entire screen, but is transparent (opacity: 0.0). Attach the click event handler only to that mask div. Then open up the info div on top of the overlay div. Clicking anywhere on the page, other than the info div, the event will be captured by the mask div before it gets to anything under it. In your event handler, hide() the info div, and remove the mask div altogether. While testing/experimenting with this, start with a partially opaque mask, not fully transparent).
Make use of a boolean variable and set it to true after first click, so it doesn't trigger the action again:
$('.help[data-info]').click(function() {
var clicked = false;
$('.info[a complicated selector]').toggle(400);
$('*:not(.info[the complicated selector]').one('click','',function() {
if (!clicked) {
.info[the complicated selector].hide(400);
clicked = true;
}
});
})
A couple of options:
You can use the blur event instead of binding a click event to everything but your popup.
Add a transparent, full-page div between the popup and the rest of the page. A click event on the transparent div could handle the hiding.
If you only want to fire once across all your elements, then you may have to manually unbind all the event handlers when any one is clicked or use a flag:
$('.help[data-info]').click(function(){
$('.info[a complicated selector]').toggle(400);
var sel = $('*:not(.info[the complicated selector]);
function hideInfo() {
.info[the complicated selector].hide(400);
sel.unbind('click', hideInfo);
}
sel.bind('click', hideInfo);
})
I find myself very often in the situation that I open an element in a web page - e.g. a drop-down menu - that I want to close if the user clicks anywhere on the page except the element itself.
To keep things simple, I have mostly written the code myself instead of employing some drop-down menu class.
However, I have never managed to build an implementation of this that was completely satisfying: Event handling and bubbling would work differently in different browsers, there would be the need for nasty workarounds, in some situations clicking the drop-down button would start closing it in the same moment, and so on.
Is there a Prototype based, authoritative, best practice to do this? Something that works across browsers - IE6 being a plus but not a requirement?
Just this:
click on a button - an element opens
(e.g. an absolutely positioned drop-down menu).
click within the element - the element stays open.
click on the button that opened the element - the element stays open.
click anywhere else on the page - the element closes.
I need help with the event handling part only, the displaying of the menu is totally secondary.
Event.observe(document, 'click', function (event) {
switch (event.element().id) {
case 'example_id':
// do different stuff depending on element clicked
// ofc u don't need to pass id, u can simply throw an element itself
break;
default:
// do close action
break;
}
// also check Event.findElement();
});
You can also add specific classes to the items you don't want to trigger close action and check it inside
if (!event.element().hasClassName('dont_close'))
Element.remove(selectDOMElement);
I guess the open button is within the menu.
$('openbutton').observe('click' function(event) {
var menu = $('openbutton').up();
if (menu.hasClassName('collapsed')) {
menu.removeClassName('collapsed');
menu.addClassName('expanded');
document.observe('click', function (event) {
if(!event.target.descendantOf(menu)) {
menu.addClassName('collapsed');
menu.removeClassName('expanded');
}
});
} else {
menu.addClassName('collapsed');
menu.removeClassName('expanded');
}
});
AFAIK, you need to make an invisible div the size of window, put it behind the current element, and add a click event to that.
Just thinking out loud but you might be able to use the blur event on the dropdown to hide it (blur gets fired when an element loses focus) or another idea might be when the dropdown opens attach a click event to the document object that hides the dropdown. Events get propagated through their containers so it should end up at the document object eventually. You might need to call preventPropegation on the event when your dropdown gets clicked so that it doesn't make it to the handler attached to the document.
maybe you could calculate the Position (X,Y) for the clickevent and compare that to the cumulativeOffset (cumulativeScrollOffset) + [el.width|el.height] of the desired container.
Event.observe(window, 'click', function(e) {
var el = $('el')
if( el.cumulativeOffset[0] < e.Event.pointerX(e) ... )
});
<div id="el" style="position:absolute;width:100px;height:100px;background-color:#00F;top:100px;left:300px;">
</div>