Focus event firing after a focus inside of a function - javascript

I'm using a hidden input to keybind my app with it but without triggering events when i write on other input-fields
-clicks on element {
-hide element
-creates an input text-field(to edit the element)
-focus the input
- on blur or submit changes the element and remove the input
}
but if you add this new event :
- click anywhere in the container {
-focus the hidden app input (so it can use keybinding)
}
when user clicks on the element it ends firing the blur event without letting the user edit it first because its activating the second block event.
so it's either skipping the focus part of the first block
or the focus of the second block is activating after the focus on the first one
I'm maybe using the wrong approach to solving it
but I don't know why it's behaving that way.
actual code:
$("#hiddenInput").focus()
var elem = $("#nameClip");
function evenConditional(id) {
if ($(id).val() !== "") {
elem.text($(id).val())
storedObj.name = $(id).val();
}
$(id).parent().remove();
elem.show();
}
$("#name").on("click", function() {
elem.hide();
elem.after(
$("<form/>").append(
$("<input/>").addClass("rename")
)
);
$(".rename").focus();
});
$(".rename").blur(function() {
evenConditional(this);
});
$(".rename").closest("form").on("submit", function(e) {
e.preventDefault();
evenConditional(this);
});
/// regaining focus on click
$(".container").on("click", function(e) {
$("#hiddenInput").focus()
});
css:
#hiddenInput {
position:absolute;
top: -2000;
}

Since the #name element is in the .container element, when you click on it, the click event bubbles up to the container, causing the click-event handler for the container to get executed.
One way to fix this would be to stop the click event from bubbling:
$("#name").on("click", function(e) {
e.stopPropagation();
There can be side effects from doing that though. Particularly, there may be other event handlers that will not get executed because of that. Such as handlers that close opened menus.
The other option would be to place conditional logic in the click handler for the container so it does not execute if the click originated with the name element.
$(".container").on("click", function(e) {
var nameElement = $("#name")[0];
if ((e.target != nameElement) and !$.contains(nameElement , e.target)) {
$("#hiddenInput").focus();
}
});

Related

Logic for showing elements and hiding them on body click

I have some piece of code.
This code on button click open menu.
When i click on button again, menu is hidden (i remove .show class, show class has display:block rule, so i toggle visibility of this item by clicking on button).
In next line, i have event, which check what element is clicked. If i "click" outside" of menu, menu become hidden, beacuse i remove .show class.
And now i have a problem, it looks like first part of code dont work anymore (button.on('click')) - i mean, work, but second part of code is also executed, and this logic is now broken.
Have you got any idea for workaround?
Thanks
var menu = $('.main-menu');
var button = $('.burger');
button.on('click',function() {
if (menu.hasClass('show')) {
menu.removeClass('show');
$(this).removeClass('opened');
} else {
menu.addClass('show');
$(this).addClass('opened');
}
});
$(document).bind( "mouseup touchend", function(e){
var container = menu;
if (!container.is(e.target)
&& container.has(e.target).length === 0) {
container.removeClass('show');
button.removeClass('opened');
}
});
maybe use jQuery toggle() method ? For example:
button.on('click',function() {
menu.toggle();
});
You need to bind an outer click event only when the button click event has been triggered, and remove the outer click event when the outer click event has been triggered:
var menu = $('.main-menu');
var button = $('.burger');
button.on('click',function() {
if (menu.hasClass('show')) {
menu.removeClass('show');
$(this).removeClass('opened');
} else {
menu.addClass('show');
$(this).addClass('opened');
}
var butbindfunc = function(e){
var container = menu;
container.removeClass('show');
button.removeClass('opened');
$(this).unbind("mouseup touchend", butbindfunc);
};
$(document).not(button).bind( "mouseup touchend", butbindfunc);
});
Note, that I have removed your condition in the document binding callback, and simple excluded it from the select set.

Gracefully bubble up with a clicktarget

I am working with this plugin that runs off of the data attribute. Basically when you click anywhere on the body it will determine if the click target has this specific data-vzpop. The problem is lets say I have a div and inside the div is an a href. It only acknowledges the a href as the click target and not the div (which makes sense).
What I want to try and do in some cases is put the data attribute on the containing div that way anything within the div works on click.
Here is a sample of the issue with jsfiddle it requires viewing the console so you can actually see which element is registered as being clicked.
<div data-vzpop>
Click Me
</div>
$('body').on('click', function(evt){
var clickTarget = evt.target;
if ($(clickTarget).attr('data-vzpop') !== undefined){
evt.preventDefault();
console.log('called correctly')
} else {
console.log('not called correctly')
}
console.log(clickTarget)
});
fiddle
You would use Event delegation:
$('body').on('click', '[data-vzpop]', function(evt) {
This will only trigger when the evt.target has a data attribute of data-vzpop, no matter the value.
If you want items inside the [data-vzpop] to trigger it as well, you would use your original click event but check that the $(clickTarget).closest('[data-vzpop]').length > 0 to determine if it's a nested target.
$('body').on('click', function(evt){
var clickTarget = evt.target;
if ($(clickTarget).attr('data-vzpop') != null ||
$(clickTarget).closest('[data-vzpop]').length > 0){
evt.preventDefault();
console.log('called correctly')
} else {
console.log('not called correctly')
}
console.log(clickTarget)
});

How to change this code to mouse hover

I want to change this code to mouse hover.
// Login Form
$(function() {
var button = $('#loginButton');
var box = $('#loginBox');
var form = $('#loginForm');
button.removeAttr('href');
button.mouseup(function(login) {
box.toggle();
button.toggleClass('active');
});
form.mouseup(function() {
return false;
});
$(this).mouseup(function(login) {
if(!($(login.target).parent('#loginButton').length > 0)) {
button.removeClass('active');
box.hide();
}
});
});
When they hover on loginbox and Login form it should be visible otherwise the login form should be hidden.Right now when we click on it it shows up and when we click again it hides.
You want to use mouseover and mouseout instead of mouseup:
$(function() {
var button = $('#loginButton');
var box = $('#loginBox');
var form = $('#loginForm');
button.removeAttr('href');
button.mouseover(function() {
box.show();
button.addClass('active');
});
button.mouseout(function() {
box.hide();
button.removeClass('active');
});
});
From the docs:
The mouseover event is sent to an element when the mouse pointer enters the element. Any HTML element can receive this event.
and
The mouseout event is sent to an element when the mouse pointer leaves the element. Any HTML element can receive this event.
Here's a simple jsFiddle to demonstrate:
http://jsfiddle.net/bryanjamesross/58TqM/1/
NOTE: You probably want to attach these events to a common parent of the box and button, so that the box doesn't hide when the mouse pointer leaves the button. Since the parent container will expand to fit the box when it gets shown, you will then be able to interact with the form until the mouse leaves the parent container area.
*EDIT*: Here's an updated version that uses CSS to achieve the intended effect, rather than manually showing/hiding the form: http://jsfiddle.net/bryanjamesross/58TqM/2/
Just use mouseenter and mouseleave instead. The last event handler seems to close the loginBox when clicked outside it, and you don't really need it, but there's no harm in keeping it as an extra precaution so the user can close the box if mouseleave for some reason should fail :
$(function() {
var button = $('#loginButton'),
box = $('#loginBox'),
form = $('#loginForm');
button.removeAttr('href').on('mouseenter mouseleave', function(e) {
box.toggle();
button.toggleClass('active');
});
$(document).on('click', function(e) {
if( !($(e.target).closest('#loginButton').length)) {
button.removeClass('active');
box.hide();
}
});
});

X-Editable: stop propagation on "click to edit"

I have an editable element inside a div which itself is clickable. Whenever I click the x-editable anchor element, the click bubbles up the DOM and triggers a click on the parent div. How can I prevent that? I know it's possible to stop this with jQuery's stopPropagation() but where would I call this method?
Here's the JSFiddle with the problem: http://jsfiddle.net/4RZvV/ . To replicate click on the editable values and you'll see that the containing div will catch a click event. This also happens when I click anywhere on the x-editable popup and I'd like to prevent that as well.
EDIT after lightswitch05 answer
I have multiple dynamic DIVs which should be selectable so I couldn't use a global variable. I added an attribute to the .editable-click anchors which get's changed instead.
editable-active is used to know if the popup is open or not
editable-activateable is used instead to know if that .editable-click anchor should be treated like it is
$(document).on('shown', "a.editable-click[editable-activateable]", function(e, reason) {
return $(this).attr("editable-active", true);
});
$(document).on('hidden', "a.editable-click[editable-activateable]", function(e, reason) {
return $(this).removeAttr("editable-active");
});
The check is pretty much like you've described it
$(document).on("click", ".version", function() {
$this = $(this)
// Check that the xeditable popup is not open
if($this.find("a[editable-active]").length === 0) { // means that editable popup is not open so we can do the stuff
// ... do stuff ...
}
})
For the click on the links, simply catch the click event and stop it:
$("a.editable-click").click(function(e){
e.stopPropagation();
});
The clicks within X-editable are a bit trickier. One way is to save a flag on weather the X-editable window is open or not, and only take action if X-editable is closed
var editableActive = false;
$("a.editable-click").on('shown', function(e, reason) {
editableActive = true;
});
$("a.editable-click").on('hidden', function(e, reason) {
editableActive = false;
});
$("div.version").click(function(e) {
var $this;
$this = $(this);
if(editableActive === false){
if ($this.hasClass("selected")) {
$(this).removeClass("selected");
} else {
$(this).addClass("selected");
}
}
});
Fixed Fiddle
It's not pretty, but we solved this problem with something like:
$('.some-class').click(function(event) {
if(event.target.tagName === "A" || event.target.tagName === "INPUT" || event.target.tagName === "BUTTON"){
return;
}
We're still looking for a solution that doesn't require a specific list of tagNames that are okay to click on.

How to detect clicking off of an element

Basically I want user to click on any .editable item, which makes an input appear, copy its styles, and then if they click anywhere else, I want the input to disappear and the changes to save. I'm having difficulty making this work. I've seen a solution using event.stopPropagation, but I don't see how to include it the way I have my code structured:
$(function() {
var editObj = 0;
var editing = false;
$("html").not(editObj).click(function(){
if (editing){
$(editObj).removeAttr("style");
$("#textEdit").hide();
alert("save changes");
}
});
$(".editable").not("video, img, textarea")
.click(function(event) {
editObj = this;
editing = true;
$("#textEdit")
.copyCSS(this)
.offset($(this).offset())
.css("display", "block")
.val($(this).text())
.select();
$(this).css("color", "transparent");
});
}
copyCSS function from here
I need to distinguish between clicks on the editable object, and clicks away from it, even if that click is onto a different editable object (in which case it should call 2 events).
Try this:
$('body').click(function(event) {
var parents = $(event.target).parents().andSelf();
if (parents.filter(function(i,elem) { return $(elem).is('#textEdit'); }).length == 0) {
// click was not on #textEdit or any of its childs
}
});
$(".editable").not("video, img, textarea")
.click(function(event) {
// you need to add this, else the event will propagate to the body and close
e.preventDefault();
http://jsfiddle.net/dDFNM/1/
This works by checking if the clicked element, or any of its parents, is #textEdit.
The event.stopPropagation solution can be implemented this way:
// any click event triggered on #textEdit or any of its childs
// will not propagate to the body
$("#textEdit").click(function(event) {
event.stopPropagation();
});
// any click event that propagates to the body will close the #textEdit
$('body').click(function(event) {
if (editing) {
$("#textEdit").hide();
}
});
http://jsfiddle.net/dDFNM/2/
The problem is that you are not correctly binding to the editObj. Perhaps it will help if you move the binding to inside your .editable click handler, or even better use live() or delegate().
$("html").not(editObj)... is bound once at document ready time, and at that time editObj is false

Categories

Resources