Capture div focusout - html

I have a main div (parent) with a input (child) and 2 other child div (clickable).
I want to capture focus out event for the main div - not when input or other 2 clickable div are clicked or focused. I have set up an event handler using jQuery to capture focusin focusout events on all the elements.
What I see is when I click on the input:
first input is focused
then the main div.
If I click on any other clickable divs
event fires first focusout for input
then main div and then other div gets focus in and main div get focusin.
I don't want main div to loose focus when clicked on other clickable divs.
How can I achieve this? I want to validate the input on lose focus but not when clicked other divs.
So far this is what I have : Fiddle
HTML :
<div id="main">
<input id="i" type="text" />
<div id="Div2" class="icons" style="background-color:blue; right: 25px;" onclick="log('Clear Clicked');"></div>
<div id="Div1" class="icons" style="background-color:red;" onclick="log('DD Clicked');"></div>
</div>
CSS :
* {
-webkit-box-sizing: border-box;
/* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box;
/* Firefox, other Gecko */
box-sizing: border-box;
/* Opera/IE 8+ */
}
#main {
top: 50px;
left: 200px;
position: absolute;
border: 1px solid #00bfff;
width: 250px;
height: 27px;
}
input {
border: none;
width: 248px;
height: 25px;
position: absolute;
z-index: 200;
}
.icons {
text-align:center;
border:1px solid blue;
height: 23px;
width: 23px;
position: absolute;
top: 2px;
right: 2px;
z-index: 99999999999999999999999;
background-position: center;
background-repeat: no-repeat;
}
jQuery :
$("#main").focusin(function () {
log("Main div got focused");
});
$("#i").focusin(function () {
log("input got focused");
});
$("#Div2").focusin(function () {
log("dropdown div got focused");
});
$("#Div1").focusin(function () {
log("clear div got focused");
});
$("#main").focusout(function () {
log("Main div lost focused");
});
$("#i").focusout(function () {
log("input lost focused");
});
$("#Div2").focusout(function () {
log("dropdown div lost focused");
});
$("#Div1").focusout(function () {
log("clear div lost focused");
});
function log(msg) {
//window.console.log(msg);
$("body").append("<p>" + msg + "</p>");
}
Any help or guidance appreciated

Here is a best way to solve, because I had the same problem too ^_^
There is a attr of event: "relatedTarget"
relatedTarget will provide the next element of this event
So, if next element is not your box OR anything inside your box, trigger focus out.
But FIRST you have to let your <div> element focusable, you have to add tabindex='-1' on div like this
<div id="main" tabindex='-1'>
the script is short:
$("#main, #main *").blur(function(e){
if(!$(e.relatedTarget).is("#main, #main *")){
//focus out.
}
});
The focus will lost and get inside #main, but you can do anything when the focus is lost from #main area.
This is a little different to your request, but I guess this may be what you want.
If this is, the code would be very clean.

Based on this accepted answer Is there a way to use event.preventDefault with focusOut? If not, why?
$(document).on('mousedown', function (event) {
target = event.target;
main = document.getElementById("main");
input = document.getElementById("i");
if (target == input) return true;
parent = event.target.parentNode;
if (parent == main) {
event.preventDefault(); //prevent default DOM action
event.stopPropagation(); //stop bubbling
return false; // return
}
});

OK, so it looks like you are constructing some sort of input widget. I see that the #main div is the outer container of the widget, the input is for entering text, and then you have two other divs serving as buttons or something. You want to validate the value of the input when the user tries to exit the widget, and you are trying to capture this event by listening for focusout on #main. This won't work because a div isn't an element that can receive focus. See the answer here for more.
I can prove to you that your div isn't focusable with a little experiment:
If you put e.stopPropagation() in both your focusin and focusout listeners for your input, you'll see that your main div is never actually focused or unfocused itself; it was just receiving the focusin and focusup events as they bubbled up the DOM tree from your input.
So, this means we have to tackle your problem from another angle.
Let's describe what it means for your widget to lose focus with a short user story:
User clicks on the input/#main/#Div1/#Div2 -- widget gains focus
User clicks on input (if he/she hasn't already) and types some text -- widget focus is not lost
User clicks somewhere on #main -- widget focus is not lost
User clicks #Div1 and then #Div2 -- widget focus is not lost
User clicks somewhere else on the page -- widget focus is lost -> validation runs
We now know exactly which events during which states should cause validation to run.
First, let's keep track of the 'focus' state of the widget with a boolean variable:
var isFocused = false;
The widget starts out in the unfocused state and becomes focused when there is a click anywhere in #main or its children OR when the input is somehow focused (could be via tabbed-into with the keyboard):
$("#main").on('click',function(){
isFocused = true;
});
$("#i").on('focus',function(){
isFocused = true;
});
The only time the widget becomes unfocused is when a) it's focused and b) the user clicks somewhere else on the page:
$(document).on('click',function(){
if(isFocused){
isFocused = false;
//kick-off the validation check!
}
});
But since all events bubble-up the DOM tree by default, multiple clicks within #main will bubble up to document.body and trigger a validation check. To prevent this, we call stopPropagation on the click event in the #main's click handler:
$("#main").on('click',function(e){
isFocused = true;
e.stopPropagation();
});
That's it!
I hope I was correct about what you're after.
Here's a working fiddle with above code.

Here is simple way to do it (As far as i understood)
$('#Div1').click(function(){
log('Clear Clicked');
//$('#main').focusin();
$('#i').focus();
});
$('#Div2').click(function(){
log('DD Clicked');
//$('#main').focusin();
$('#i').focus();
});
here is fiddle

The other way to workaround is to add a small setTimeout before running focusout handler.
You can easily whitelist a list of elements to exclude with and clearTimeout when they get focusin.

Related

Style dropdown icon that toggles on click using just CSS?

I am able to style the drop-down icon for the select box. However, I want to toggle the icon depending if the dropdown is visible or not.
when dropdown is not visible, show icon1
when user clicks on dropdown, show icon2
when user closes the dropdown, show again icon1.
What I did is to use the :focus on select to manipulate the icon.
The problem is with the last step. When user clicks anywhere on the screen - or press ESC for example - to close the dropdown, the focus is still on the select tag, and the style is not changed back. Only until user clicks one more time, the focus is removed and everything is back to normal.
Is there way to force focus removal when dropdown is closed?
This is examined in Chrome.
https://codepen.io/igorspasic/pen/GQqKqy
p.s. javascript is welcome, of course.
You can include jQuery library and add the following jQuery code in <script> tag.
$(document).ready( function() {
$(document).keyup(function(e) {
if (e.keyCode == 27) {
$("#x").blur();
}
});
$("#x").change( function() {
$("#x").blur();
});
});
You should be able to set it to blur with JavaScript. Here I've just used a change and mouseout event to remove the focus:
var select = document.querySelector('#x');
function blurSelect() {
select.blur();
}
document.onkeyup = function(e){
if (e.keyCode === 27) {
blurSelect()
}
};
select.onmouseout = function() {
blurSelect()
};
select {
color: white;
background-color: blue;
font-size: 20px;
}
select:focus {
background-color: red;
}
<select id="x">
<option>One</option>
<option>Two</option>
</select>
<br><br><br>
Q: How to remove focus on select when dropdown is closed and turn back to blue?
Hope this helps.

HTML Button with Hyperlink Characteristics

I'm looking for a way to use the functionality of a html button where I can bind the OnClick events and deal with it accordingly but I'm also looking to see if we can have hyperlink functionality for that button so they can right click on it and click "Open in new tab" which will fire off the button event but push it to a new tab.
Does anyone know if this is doable?
Hoping for it to look something like this. Currently this is a button with an image and a span inside of it which has a hover over effect.
I'm looking for a way to use the functionality of a html button where I can bind the OnClick events and deal with it accordingly...
You can bind click handlers to almost any DOM element.
...but I'm also looking to see if we can have hyperlink functionality for that button so they can right click on it and click "Open in new tab" which will fire off the button event but push it to a new tab.
So use an <a> element. All you need to do is check which mouse button was used, and that the Ctrl, Alt, and Shift keys are not pressed (otherwise the user is trying to open the link in a new tab, or other such shortcut behaviors).
document.querySelector('.btn').addEventListener('click', function (e) {
if (e.button === 0 && !e.ctrlKey && !e.altKey && !e.shiftKey) {
alert('button was clicked!');
e.preventDefault();
}
}, false);
.btn {
background-color: #8CF;
border: 1px solid #00F;
display: inline-block;
padding: 2px 5px;
text-align: center;
text-decoration: none;
}
.btn:focus {
border-color: #000;
}
.btn__icon {
display: block;
margin: 0 auto;
padding: 17px 17px 0;
}
<a href="http://example.com/" class="btn">
<img class="btn__icon" src="http://placehold.it/40x40/FFF/000"/>
<span class="btn__label">Details</span>
</a>
I would use a link styled like a button. You can set it up to look like a button and set up click events, as well as opening it in a new tab.
Perhaps try something like this - style the <a> as a button (as proposed by previous answers) and then prevent default on click:
HTML
<a id = "btn" href = "http://www.google.com">CLICK ME</a>
jquery
$('#btn').click(function(e){
e.preventDefault();
alert('hello');
});
FIDDLE
This gives you a click function on the link, prevents the default action, but retains the right click context menu.
I'm not 100% sure I understood the question but I think this is what you mean..
<input type="button" id="button1" onclick="clickFunction()" value="Click Me!">
<script>
function clickFunction() {
document.getElementById("button1").onmousedown = function(event) {
if (event.which == 3) { <!--3 = right click-->
window.open('target', '_blank'); <!--Opens target in a new tab-->
}
}
}
</script>
I don't think that you can change the context menu that pops up to add "Open in new tab" on right click but you can tell how to handle a right click.
Edit: Actually you can change the default context menu I believe but I don't think you can do it without 3rd party libs? Again not sure about that someone else will have to give you a better answer sorry :/
Edit2: After seeing your initial edit I'd agree with #Surreal Dreams. Use styling and make a normal link with an image and hover effect :)

Html - Space Key Press is Causing OnClick to be Triggered

[Note: this flaw only occurs in Internet Explorer 11. It is fine in IE9, Chrome and Firefox.]
I have the following Css:
/*** pop-up div to cover entire area ***/
.divModalDialog {
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
/*! important !*/
display:none;
/* last attribute set darkness on scale: 0...1.0 */
background-color:rgba(0,0,0,0.8);
text-align:center;
z-index:101;
}
/*** ! target attribute does the job ! ***/
.divModalDialog:target { display:block; }
An Html:
<div id="divModalDialogUpdate" class="divModalDialog">
<div>
<input type="text" id="divModalText" />
<button onclick="doStuff();">Press</button>
</div>
</div>
<div id="divCanvas" style="display: none; width:100%; height: 100%;">
<canvas id="m_Canvas" width="200" height="200" oncontextmenu="return false;"></canvas>
</div>
As you can see, I am using the divModalDialog as a Modal Dialog Box which appears over the canvas div.
On the canvas div, a game is running. When I need to fire up the modal dialog I pause the game and then have the code:
window.location = "#divModalDialogUpdate";
The person enters some stuff in the text box, clicks the button which triggers the onclick event which runs the function doStuff(). Within doStuff() is the following line of code which returns to just the canvas div being visible:
window.location = "#";
This works all great.
Now the problem. The game state is paused, and my prefered key to toggle the pause state is the Space key. (Any other key and things would be fine, but the problem is I want to use the space key).
So I tap the space key and this is (unwantedly) triggering the onclick event of the button in the modal dialog div again (even though the modal div is no longer visible) which obviously calls the doStuff() function again.
How do I stop the space key triggering the Modal Div's button onclick event when the Modal Div is no longer visible?
You could use a global variable ignore before any logic in doStuff(), e.g.,
function doStuff() {
if(ignore == true) return;
/* logic here ... */
}
Then change your other code to something like:
ignore = false;
window.location = "#divModalDialogUpdate";
and
ignore = true;
window.location = "#";
There might be a way to do this using event.stopPropagation() but I could not find a way to make that work.

Prevent screen from moving when clicking on <a href=></a>

I'm using <a href> element along with :target css selector to show a <div> which by default is set to display:none. Problem is, that when I click on the link to show that <div>, it is automatically scrolling down my site towards that <div>.
Is there a way to stop the screen movement?
Unfortunately I am not yet proficient in anything besides CSS and HTML.
You can use event.preventDefault() to avoid this. Something like this:
$('a.yourclass').click(function(e)
{
//your code
e.preventDefault();
});
OR:
link
in the link enter:
Link here
You'll need JS anyway:
// (in jQuery)
$el.on('click', function(e) {
// find current scroll position
var pos = document.body.scrollTop || document.documentElement.scrollTop;
// let normal action propagate etc
// in the next available frame (async, hence setTimeout), reset scroll posiion
setTimeout(function() {
window.scrollTo(0, pos);
}, 1);
})
I don't know if this will flicker the screen. It might. It's a horrible hack either way.
In my Chrome, there's no flicker: http://jsfiddle.net/rudiedirkx/LEwNd/1/show/
There are two ways to tell the browser we don't want it to act:
The main way is to use the event object. There's a method
event.preventDefault().
If the handler is assigned using on (not by
addEventListener), then we can just return false from it.
Example:
Click here
or
here
This is a bit of a hack but you could use a basic css work around:
CSS only Example
#div1 {
height: 0;
overflow:hidden;
}
#div1:target {
height: auto;
margin-top: -110px;
padding-top: 110px;
}
#div2 {
background:red;
}
Click to show
<div id="div1">
<div id="div2">Content</div>
</div>
If you need it to be a little more flexible you can add some js...
More Flexible Example with JS
$('a').click(function () {
$('#div1').css({
'margin-top': 0 - $('#div1').position().top + $(window).scrollTop(),
'padding-top': $('#div1').position().top - $(window).scrollTop()
});
});
Basically you're pulling the top of div1 up with the negative margin and then pushing div2 back down with the padding, so that the top of div1 rests at the top of the window... Like I said its a hack but it does the trick.
Those links are anchor-links and by default made for those jumps :) You could use JS to prevent the default behaviour in some way. For example using jQuery:
$('a').click(function(e){e.preventDefault();});
or by default add return false; to the links
Avoid using :target all together and just use onclick event.
function myFunction()
{
document.getElementById('hiddenDiv').style.display = 'block';
return false;
}

How to make specific areas in a div clickable with css / js / anything

I'd like to show you an image of my page content so you'd understand what am I talking about:
Now, I have two main divs on a page: the wrapper (the red one) and the purple:
<div id="purple" style="position:fixed; z-index:0; left:0; top:0; width:100%; height:100%; filter:alpha(opacity=50); opacity:0.5; cursor:pointer;" onclick="javascript:alert('purple clicked');"></div>
<div id="wrapper"></div>
The wrapper contains many controls and other divs, and the purple is basically supposed to be clickable and perform some event, lets say alert('purple clicked');
The thing is that when I press inside the wrapper it also fires the purple event.
So what I did was to add the following code:
<script type="text/javascript">
$("#purple").click(function (e)
{
window.event.cancelBubble = true;
e.stopPropagation();
})
</script>
I understood that through this code I'll manage to click on the purple area and get the alert fire, the problem is that when I click inside the red area this alert is fired also - and this is not what I wanted!
So, eventually, if you haven't given up yet reading this post, here's the question:
How to avoid the "purple events" fire when clicking the red zone?
p.s.
I must have the purple div be like - this can't be changed:
width:100%; height:100%
There is no direct way to prevent bubbling down. You have to use event.target.id to differentiate the purple div with others,
Try this,
$("#purple").click(function(e){
if(e.target.id == "purple")
{
alert("purple clicked.!");
}
});
DEMO
Note: Just realized your purple div does not encapsulate red/green divs. This answer won't solve your problem in that case. It relies on the nested div structure as per the included example below. I'll leave this answer in case someone else comes across it with a similar issue. Maksym Stepanenko's answer below regarding z-index is the most correct one.
There are two properties of the event object: currentTarget and target.
currentTarget is the current element in the event bubbling phase.
target is the element that is responsible for initiating the event.
Within the purple click event handler you could test to see if that element was the target in the event chain:
$('#purple').click(function(e) {
if ( e.currentTarget == e.target ) {
console.log('clicked purple',Date.now());
}
});
$('#red').click(function(e) {
console.log('clicked red',Date.now());
});
This is helpful when:
you don't want to constrain the event phasing to only the red object
you don't want to have to remember to put e.stopPropagation in every click handler whose element is a child of #red/#purple
Here's a complete working example:
<!doctype html>
<html>
<head>
<title>Bubble Test</title>
<style type="text/css">
#purple {border:3px solid #3c1e40;background:#b459bf;}
#red {margin:auto;width:958px;border:3px solid #400Aa0a;background:#ff2829;}
.green {margin:20px;padding:30px;border:3px solid #1c401c;background:#54bf55;}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#purple').click(function(e) {
if ( e.currentTarget == e.target ) {
console.log('clicked purple',Date.now());
}
});
$('#red').click(function(e) {
console.log('clicked red',Date.now());
});
});
</script>
</head>
<body>
<div id="purple">
<div id="red">
<p class="green">Hello World</p>
<p class="green">Lorem ipsum dolor sit amet.</p>
</div>
</div>
</body>
</html>
You could take this a step further and also compensate for #red:
$('#purple').click(function(e) {
if ( e.currentTarget == e.target ) {
console.log('clicked purple',Date.now());
}
});
$('#red').click(function(e) {
if ( e.currentTarget == e.target ) {
console.log('clicked red',Date.now());
}
});
$('.green').click(function(e) {
console.log($(this).text(),Date.now());
});
This should solve your problem:
CSS
#wrapper
{
z-index:1;
margin: 0 -50px;
left:50%;
position:absolute;
}
Fiddle
You have a problem because your purple div overlays the red one, the reason for that is:
z-index only works on positioned elements (position:absolute,
position:relative, or position:fixed).
you should read more about it Z-index