Add Mouse Event to all Child Elements in DIv - javascript

Here is what I am trying to do:
$(window).mousedown(function(e) {
switch (e.which) {
// left click
case 1:
e.preventDefault()
$(e.target).css("border", "2px solid red");
break;
// Middle click
case 2:
e.preventDefault()
$(e.target).css("border", "");
break;
}
});
The following code works great.
Whenever I click on any elements it would create a red box and when I click the middle button from the mouse
it removes the red box.
BUT:
what i want is I want the same functionality but want to apply to particular div elements only.
<div class="col-md-5" style="border: 1px solid black; margin: 1px; overflow-y: scroll; height: 450px;" >
<div id="webappcontents">
{{{this.html}}}
</div>
</div>
I want to add mouse click events on
div #webappcontents. Hhow can I achieve this?
This way all contents inside #webappcontents is clickable and creates red box.
Any help is great.

Your code: $(window).mousedown(function(e) { is catching any mouse click on the page
To specify the webappcontents div change that to
$('#webappcontents').mousedown(function(e) {
though you might want to only make certain elements that way, like all with the class='clickable' inside that container...
$('#webappcontents div.clickable').mousedown(function(e) {
// now you can access the element to modify with $(this)
// $(this).addClass('clicked')
Also, make sure this function registers after page load.. One way is using the jQuery document.ready
$(document).ready(function() {
$('#webappcontents').mousedown(function(e) {
// do stuff
})
});

Related

How long does it take until click event is triggered?

I try to make a select box whose entries are opened after clicking into the input box. After selecting one of the items, the dropdown should be closed again.
I want to achieve the open/close part of the dropdown without the use of javascript.
The html looks like this:
<div id="outer">
<input type="text" id="input">
<div id="results">
<div>Test 1 </div>
<div>Test 2 </div>
<div>Test 3 </div>
<div>Test 4 </div>
</div>
</div>
<div id="label">
</div>
After clicking onto an item, the selected value should appear below the #outer div (just for demonstration purposes).
The Javascript for assigning click events to the dropdown values:
document.querySelectorAll("#results div").forEach(setClick);
function setClick(node) {
node.addEventListener("click", setText.bind(null, node.innerHTML))
}
function setText(t) {
document.getElementById("label").innerHTML = t;
}
Now I will show you my first draft of css code:
#outer {
width: 200px;
position: relative;
}
#input {
width: 100%;
}
#results {
position: absolute;
width: 100%;
display: block;
visibility: hidden;
background-color: white;
}
#results > div:hover {
background-color: lightblue;
cursor: pointer;
}
#outer:focus-within #results, #results:hover {
visibility: visible;
}
This works like a charm but fails in one point:
After clicking an item, the dropdown is not closed. This is because of the #results:hover selector which is needed to keep the dropdown open after clicking onto an item. The click takes the focus out of the input field, thus the focus-within selector is not applied anymore. As the focus is removed from the input before the click occurs, the dropdown is hidden when the final click arrives in the document (this is my understanding of the problem).
Thus I use the hover selector which forces the div to keep open as long as the mouse is above the div.
You can test this here:
https://jsfiddle.net/hcetz1og/3/
My solution for this was a transition that hides the dropdown after the focus has been taken away:
#outer:not(:focus-within) #results:hover {
visibility: hidden;
transition-property: visibility;
/*use 10 ms and the clicked value in the drop down won't be shown */
transition-delay: 100ms;
transition-timing-function: step-end;
}
This works on my machine when I use 100ms as a delay. If I use 10ms, I have the same problem again. It seems that the click event is triggered "very" late.
Feel free to test it here:
https://jsfiddle.net/hcetz1og/2
Question:
How long will it take until the click event arrives at the document? Is there a fixed time span I have to wait or can the delay depend on every machine?
If so, I am forced to not use plain CSS but must use javascript for this I think.
Edit:
Feel free to post an alternative solution using plain css. But please be aware that I mainly want to focus on getting an answer to this question, not alternative solutions.
As #Mark Baijens said in the comments, using timeouts is a bad practice, so here is a pretty clean solution.
I used JavaScript to render the dropdown, not the CSS, because the CSS is where Your issue is coming from.
I don't know why would You want to set the innerHTML, but not some other property, like style.visibility for example. It just doesn't make sense to me, so with that in mind, let's get our hands on this :)
Working demo >> HERE <<.
Step 1 - remove the #outer...:hover parts of CSS
So, You are left with this:
#outer {
width: 200px;
position: relative;
}
#input {
width: 100%;
}
#results {
position: absolute;
width: 100%;
display: block;
visibility: hidden;
background-color: white;
}
#results > div:hover {
background-color: lightblue;
cursor: pointer;
}
Step 2 - add the onfocus event to the input field
Just assign a function call to the onfocus attribute of the input. Everything else in the HTML stays the same.
<div id="outer">
<input type="text" id="input" onfocus="showElements()">
<div id="results">
<div>Test 1 </div>
<div>Test 2 </div>
<div>Test 3 </div>
<div>Test 4 </div>
</div>
</div>
<div id="label">
</div>
Step 3 - create the showElements and hideElements function:
function showElements() {
document.getElementById("results").style.visibility = 'visible';
}
function hideElements() {
document.getElementById("results").style.visibility = 'hidden';
}
Step 4 - call the hideElements() when clicked outside the input element
There are two cases for the click outside the input element:
Case 1 - we clicked on one of the divs inside the #results wrapper
Case 2 - clicking outside the input field, but not on one of the divs inside the #results wrapper
In the first case, we will modify the assignment of the onclick handler like this:
document.querySelectorAll("#results div").forEach(setClick);
function setClick(node) {
node.addEventListener("click", setTextAndHideElements.bind(null, node.innerHTML));
}
So, the setText function now becomes setTextAndHideElements and looks like this:
function setTextAndHideElements(t) {
document.getElementById("label").innerHTML = t;
hideElements();
}
For the second case (clicking outside the input field, but not on one of the divs inside the #results wrapper), we must watch for the click on the whole page (document element), and respond to the action like this:
document.onclick = function(e) {
if (e.target.id !== 'input'){
hideElements();
}
}
Note: this will override any previously assigned onclick events assigned to the document element.
As mentioned in the beginning, working demo is >> HERE (codepen.io) <<.
I tried another solution which requires no setting of additional JS events.
See: https://jsfiddle.net/hcetz1og/4/
I gave every result item a tabindex of "0" to ensure, those items can be focusable.
Then i removed the #outer:not() part from the css and replaced the hover selector with this: #results:focus-within. Additional I called node.blur() on the node after clicking onto them.
Summary:
Change in HTML:
<div tabindex="0">Test 1 </div>
Change in JS:
function setText(t, node) {
document.getElementById("label").innerHTML = t;
node.blur();
}
Change in CSS:
#outer:focus-within #results, #results:focus-within {
visibility: visible;
}
What do you think about this one? Should be stable I think because the focus onto the #results div is set before the click event is triggered onto the result item.
Event order should be (based on my observation):
input focus -> input blur -> item focus -> item click
Not sure if the step between blur and focus can lead to a visible problem. Theoretically, the results div must be hidden and shown again in a very small amount of time.
But I investigated this with chrome's performance timeline and did not recognize a new render between both events. One can see, that the result item is focused (outline is set onto it) and then it disappears as expected.

mouseout closes the trigger and not the target

I have set a popup to open at mouse over on an element. The popup should close when the cursor is off it.
For some reason the popup window closes when the cursor is right off its opener button, instead.
You can see an example here:
http://www.friends.wwz.co.il/Lab/Gefen/Generali/es/popup.html
Please try to hover with the mouse on the "lee mas" button. A popup will open. It should close at hovering off it. But instead it closes at hovering off the lee mas button, so it closes immediately.
Any idea where do I go wrong?
Many thanks in advance for you advice
The main problem is you are attaching hover events to the button. Once you hover out of the button element, it fires the hoverOut button.
So the ideal course of action can be:
Bind hover event to the button.
Once hovered, a pop-up is dynamically added.
Then, a hover event is bounded to the pop.
And the code of dissolving the pop-up is attached in the hover-out function.
So that when actually the cursor is hovered out of the pop-up it dissolves.
Apart from that, Just have a look at this fiddle. It has two hyperlinks for hover. The first is the one you are facing. The second one is the one you are looking for. :D
Code for it:
$(document).ready(function() {
$("#toggleSwitch_j").hover(
function() {
$("#theBox_3").slideDown(500);
}, function() {
$("#theBox_3").slideUp(500);
});
$("#StayOpen").hover(
function() {
$("#theBox_2").slideDown(500);
}, function() {
$("#theBox_2").slideUp(500);
});
});
body {
background-color: #eef;
}
#theBox_3,
#theBox_2 {
display: none;
border: 1px solid #000;
width: 200px;
height: 100px;
background-color: #ddf;
}
#toggleSwitch_j,
#StayOpen {
background-color: #cacaca;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
This layout will only keep the hidden div visible as long as you point to the link
<br>You'll never be able to reach anything inside the div
<br>jQuery Hover
<div id="theBox_3">Peek-a-boo!</div>
<hr>This layout puts the link and hidden div inside a wrapper - hovering anywhere inside the wrapper expands the hidden div, so you can reach content inside it. This would be handy if you need to put links or form elements inside the hidden div, instead of
just text to read.
<div id="StayOpen">
jQuery Hover
<div id="theBox_2">Peek-a-boo!</div>
</div>

How do I make a div tappable but make the anchor links take precedence/cancel the div tap?

Web development isn't my strongest point, so apologies if this is foolish, but I want to have a div that is tappable on mobile so I can intercept the tap and do things.
I'm attaching a touchdown event listener to the div in JavaScript, and when I tap, I color the div to indicate it's been selected.
However, if there's an anchor tag within the div with some text in it (totally valid in this case), I don't want the div to be highlighted when you're just clicking the link.
I'm not sure the term in web development, but is there a way to make the anchor tag intercept touches so they don't get sent to the div if the anchor tag is selected?
You can use a conditional in the event handler to test if the event target is an anchor. I used the click event in my example, but it should work with touchdown also.
var tapDiv = document.querySelector('#tap');
tapDiv.addEventListener('click', function(e) {
//conditional ensures the clicked element isn't an <a>
if (e.target.tagName.toLowerCase() !== 'a') {
e.currentTarget.style.backgroundColor = 'orange';
}
});
#tap {
padding: 8px;
background-color: black;
}
#tap a {
display: inline-block;
padding: 8px;
background-color: white;
}
<div id="tap">This is the anchor</div>

HTML button does not click even when is focused and the CSS rules kick in

Take a look at this button: http://jsfiddle.net/vtortola/Dnxpe/
I Chrome, if you click on the top border, even when the ":hover" and ":active" css rules triggers, the event is not triggered. If you click more in the center, then it works fine.
In IE9, if you do the same it miss the 50% of the clicks.
The problem are the margins, when you click the margins switch, giving the effect of the button being pushed, but this makes the pointer be out of the button if you are clicking the top border but... the event should be already triggered.... why this happen?
Thanks.
This probably happens because a click() is considered complete only once both mousedown() and mouseup() are completed in succession. In the case of clicking near the top border mouseup() never gets triggered and the same holds true for click().
If you use mousedown() it'll work every time, but it'll happen before the entire click is completed.
$('button').mousedown(function(e){
$('#clicks').append('<span>click </span>');
});
To solve this you could do the following:
Add a container to the button and then add a mousedown handler to the button and a mouseup handler to the container. If you make sure they were both invoked, then you can be sure that a click event on the button has been performed.
Like so:
HTML
<div id="cont"><button>Click me</button></div>
<div id="clicks">
</div>​​​​​​​​
JavaScript
var mdown = false;
$('button').mousedown(function(e){
mdown = true;
});
$('#cont').mouseup(function(e){
if (mdown)
{
$('#clicks').append('<span>click </span>');
mdown = false;
}
});
​
I checked out you code and find an interesting bug.Its because of CSS.
Even you can regenerate that bug.
Steps:
1. Click on button near top border but do not release your finger from mouse.
2. Now, look at the button,your button is actually pushed down and that's why,it does not able to fire button click event.
Solution:
Remove margin when button is active.
button:active,input[type=submit]:active
{
box-shadow: 0px 0px 3px 3px #D8F6CE;
}
I hope it helps.
Here's the solution I came up with that uses a css psudo element to capture the click event. The benefit here is that you don't need javascript. The click events are always captured by the :after and bubble up to the button.
http://jsfiddle.net/kevinrockwood/fUuUB/1/
The main thing to note is the css:
button:after{
content: " ";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

Turn a function on or off after scrolling to bottom

I have a div with "Terms and Conditions". It is a vertically scrollable div. The idea is to scroll all the way down which will allow a user to then Submit (by hitting the submit button). But it is not really a button, but an anchor with a javascript function inside.
<a onclick="showDialog();"><img
name="continue" value="Continue" alt="Continue"
src="${resource(dir: 'images/buttons', file: 'submit.gif')}"
border="0" /></a>
So what I need to do is when a user scrolls down, it will then turn on the javascript function but it will remain off if not.
Any advice?
The scrollTop of the div (#terms) is how far down inside the top of the viewable area is. The height of the div is how much the user sees. It thus follows that the scrollTop of the div plus the height of the div must be at least as much as the total height of the entire terms of service document inside (which we will call #termsInner).
Here's some example HTML code: (Note: You can try this out at http://jsfiddle.net/8U7GY/6/.)
<p id="instructions">Please read these terms and conditions now.
<b>You must scroll to the bottom before continuing.</b></p>
<div id="terms">
<div id="termsInner">
<p>Lorem ipsum...</p>
</div>
</div>
<span><a id="submit">Register me!</a></span>
Some CSS code:
p {
padding: 0.25em;
}
#terms {
border: solid 1px;
height: 24em;
overflow: auto;
margin-bottom: 1em;
}
#termsInner {
padding: 0.5em 0;
}
.highlighted {
background-color: #ff0;
}
#submit {
color: blue;
text-decoration: underline;
}
And some JavaScript code: (This must be in $(function() { ... }); so that it is executed only once the document is ready.)
// Select the elements of the HTML page.
var instructions = $('#instructions'),
terms = $('#terms'),
termsInner = $('#termsInner'),
submit = $('#submit');
// Bind an event handler that will run when the user
// has not scrolled through the terms of service.
submit.bind('click', function() {
// Highlight the instructions.
instructions.addClass('highlighted');
// Remove the highlighting after two seconds.
setTimeout(function() {
instructions.removeClass('highlighted');
}, 2000);
});
// Once the user scrolls through, call showDialog instead
// when the user clicks.
terms.scroll(function() {
if (terms.scrollTop() + terms.height() >= termsInner.height()) {
submit.unbind('click').bind('click', showDialog);
}
});
// This is where you would continue the user registration process.
function showDialog() {
alert('whatever');
}
There are several important things to notice.
We do not use the onclick HTML attribute but rather bind event handlers programmatically using bind and unbind. This allows us to make a different thing happen depending on whether the user has scrolled down or not.
jQuery provides the scroll method to register a function to run whenever the user scrolls the div. We check the sum of scrollTop and height against the height of the content inside the div, and if that is OK, we unbind the original click handler and bind a new one.
We highlight the instructions (if the user has not yet scrolled down but clicks the anchor anyways) for usability. If the user clicks and finds that nothing happens, he would think that the registration form does not work, would leave your site, and be left with a bad experience.
Edit: Fixed it to work on Internet Explorer. Because of the way IE works, you cannot have padding set on the div #terms itself, so set any padding on #termsInner instead.
You need to check the if the <div>'s scrollTop+height is equal to the scrollHeight.
With jQuery:
$('a').click(function(){
var myDiv = $('div')
if (myDiv.scrollTop() + myDiv.height() == myDiv.get(0).scrollHeight)
{
showDialog();
}
else
{
return false;
}
});
You can also check the <div>'s scrollTop+height on the scroll event, and then enable/disable the anchor depending on whether or not the scrollHeight has been reached.

Categories

Resources