I'm wanting to click an image (img#first) and have it split into three smaller versions of another image (img.cat). Each time img.cat is clicked, it throws the cloned elements in random directions and temporarily shows a lion in place of the img.cat that was clicked.
The cat replication and lion popup both work properly (as you can see by clicking the smaller cat in the upper left corner), but I don't know how to make it so a .click() event on img#first will call the function to replicate smaller cats. To reiterate, I want the img#first to spawn 3 smaller img.cat, then disappear, then if the user continues to click new img.cat objects they continue to spawn more of themselves. The problem is just getting that original img#first to start the chain reaction and then disappear forever.
Here's the Fiddle.
If I'm able to just make the entire .click(explode) function work on img#first and then swap that identifier somehow to img.cat after the initial click, wouldn't that do the trick?
For example:
var firstRun = 0
$('img#first').click(function() {
if (!firstRun) {
//do original stuff here
firstRun = 1;
} else {
$(this) = $('img.cat');
//do img.cat stuff here
}
});
Or do I need to isolate the explode function so that it can be called separately on two different objects while achieving the same effect?
I honestly have no idea how to go about accomplishing either of these tasks. Maybe there's a simpler way to get what I want.
Add a separate event which triggers only on clicking #first which programmatically triggers a click on img.cat then removes itself like this:
$('#first').click(function() {
$("img.cat").trigger("click");
$(this).remove();
});
Here is a working jsFiddle.
Update your $('img.cat').click() event listener's selector to $('img.cat, img#first) to select both img.cat and img#first. With this new event listener, you can remove your first $('img#first').click() listener. See my updated JSFiddle.
Related
I understand that you can bind an event listener to dynamic elements, but I want to have the js automatically click them. As in, there is a webpage with a series of buttons that pop up, I want to automatically click thru them, but each successive button is loaded dynamically and so I cannot do it simply.
Here's what I was hoping would work (works if you type it into console one line at a time):
$(".begin").click().delay(200);
$(".answer[value='1']").click().delay(200);
$(".answer[value='10']").click().delay(200);
If I don't misunderstand your problem. You want to click those buttons "once" they exist. Then you might create a timer after $('.begin')(here I assume the begin is to trig the button appear action) and constantly check those buttons and click them once it's active. It would look something like the following with setTimeInvertal(). And yes you need to create your own condition to stop or determine whether trig click or not.
You have to detect them manually, faster check = once (I assume you are not doing something illegally or abusing websites). The below code is a sample idea.
var btn_timer;
function startAction() {
//for example check every 3s
btn_timer = setTimeout(function(){
//check if btn exists or not
if($(".answer[value='1']").length) {
$(".answer[value='1']").click().delay(200);
}
//condition to stop your timer, or you can manually call it somewhere else;
if(...some condition) StopAction();
}, 3000);
}
function StopAction() {
clearTimeout(btn_timer);
}
I am using the google search API and I want that when you click on an image, this image will be copied to a different location.
I created a fiddle here: http://fiddle.jshell.net/wjewg062/
It works this way: The user types in a term in the input field and images will be displayed. When he/she clicks on one twice it will displayed in the image div.
I put the onClick event listener on to the searchresults div, hence the extra click in the beginning. However, I want it to be displayed on the first click.
Now, if I comment this out
var searchresults = document.getElementById('searchresults');
searchresults.addEventListener("click", function(event){
event.preventDefault();
imageing();
});
it doesn't work. The images will be links. I believe the reason for this is that the results are displayed in gs-image-box and not created yet. I tried calling the imaging function in different other functions like the searchImg or the OnLoad but nothing work.
I thought of using a check if element is clicked function described here Detect if I'm clicking an element within an element
but I think there must be an easier way.
I'm running out of ideas, can anyone give an idea or hint?
Thanks !
The images are dynamically created right? Check out this post Event binding on dynamically created elements?
In short, events are attached to elements upon pageload. so a newly created dynamic element such as the ones that google creates, aren't attached to the event. so google probably has a way to circumvent the whole "you need to load the page to attach events to elements" thing but it requires an extra click. Using the syntax found in the post should help you.
By the way. Using Jquery doesn't really show down your site because it's usually cached in the client's browser.
The info you need is already in your searchresults eventListener. The target of this event will be the image you click, even if you add the event on a div higher in the structure.
A javascript event will by default be dispatched from the top element (window) all the way through the element that received the click, then will go back to the top. Any element that is an ancestor of the element that was clicked will receive the event info, so you can listen on any ancestor, but the target remains the element that was actually clicked.
In your case, by simply passing the target to your imageing() function, you can apply the behaviors you want without any extra manipulations.
One problem you might face, is if user clicks on searchresult but not on an img element. Then you'll have a bug, so you should handle these cases.
Something like this:
var searchresults = document.getElementById('searchresults');
searchresults.addEventListener("click", function (event) {
console.log(event.target, this);
event.preventDefault();
if(event.target.tagName == 'IMG'){
imageing(event.target);
}
});
function imageing(targetImg) {
var imageresult = document.getElementsByClassName('gs-image-box');
var xu = document.getElementById('companylogo');
var imgsrc = targetImg.src;
xu.src = imgsrc;
}
http://fiddle.jshell.net/pwjLrfnt/3/
http://jsfiddle.net/VhjR7/1/
When you click the my lists menu once, it expands, but if you click it again, it doesn't contract.
The problem is listsExpanded being inexplicably reset to false after it is set properly to true by listsExpand(). This causes the check within $('#mid-wrap').delegate() to inappropriately call listsExpand() again, instead of listsContract() like it should.
I can't figure out where or why this reset is occurring, but I think it has something to do with the sticky light blue menu functionality. Before I started removing and replacing this blue bar after scrolling to fix an IE7 bug, there was no issue with expansion/contraction of the little white menu.
Any ideas on what's causing this?
The issue is that the hover event does not support both function arguments (in and out) when used with .delegate(). You will need to use mouseenter and mouseleave instead of hover.
Change to this:
$('#mid-wrap').delegate('#lists', 'mouseenter', function() {
listsMouseIn = true;
}).delegate('#lists', 'mouseleave', function() {
listsMouseIn = false;
});
FYI, if these HTML objects are static, not added dynamically, you could significantly simplify your code by using direct event handlers on that actual objects rather than .delegate and just stopPropagation() when you've processed the click. Then, you'd see the click first in the object and wouldn't be processing the same click multiple times causing you to need all these global flags to keep track of state.
You could also just use the visibility of the object as your detection mechanism for whether the menu is open/closed too rather than a global variable.
The first part of your hover handler (with listsMouseIn = true;) never actually fires so whenever you click, your $('body').mouseUp() handler assumes that you are not hovering the lists button, and therefore hides the menu just for the $('#mid-wrap').delegate(...) handler to show it again milliseconds later.
Replacing
$('#mid-wrap').delegate('ul#lists', 'hover', funcIn, funcOut);
with
$('#mid-wrap').delegate('ul#lists', 'mouseover', funcIn).
delegate('ul#lists', 'mouseout', funcOut);
seems to do the trick.
Got a simple problem, which it doesn't look like HoverIntent would solve.
I have two elements (lets say a button and a div), one element is the trigger to start the div expanding, which is triggered by a mouseenter event (this would be a suitable candidate for HoverIntent).
However when the mouse leaves the expanded div for a given amount of time I need it to contract again, however if they re-enter the div it should NOT contract. Most hoverintent style plugins would give me this functionality but only for 1 element, and as one element controls the expanding (button - mouseenter) and one controls the contracting (div - mouseleave).
I know I could write some code to just do a setTimeout to delay for a period and make sure that the mouse is still outside of the area, but I would rather use a pre-made plugin if one exists.
So could anyone advise if this exists?
-- Edited --
Edited the above question to make clear that the main intent part is to stop it contracting the div if the mouse re-enters the div within a given amount of time, lets say 2 seconds. So the div should expand on mouseenter button, then contract if mouseleaves the div for >= 2 seconds.
Not something like this?
$('.hover-items').each(function(idx, el){
$(el).mouseenter(function() {
$(this).slideDown(300);
$('#target_div').unbind().mouseleave(function() {$(this).slideUp(300)});
});
});
The unbind is there so that you don't wind up with a bunch of events tied to the element. Just reset and go.
Added to satisfy clarification of question.
$('.hover-items').each(function(idx, el){
$(el).mouseenter(function() {
clearTimeout($(el).data('timer'));
$('#target_div').slideDown(300)
.unbind()
.mouseleave(function() {
var closure = function(){$('#target_div').slideUp(300)};
$(el).data('timer', setTimeout(closure,2000));
});
});
});
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>