.focus() not working on textarea in hover event - javascript

So I have this code here.
timeline.afterMilestonePrototypeCreated = function() {
$(MILESTONE_PROTOTYPE_SELECTOR).hover(function(e){
$(this).find('textarea').focus();
});
}
Which should focus the textarea element after it was created. Everything works fine, I've even checked if the event is being called, after creation and hovering. Every other code works, but I'm not able to focus that textarea element. After some googling I've tried to add a setTimeout, which didn't work neither.
Thanks!
SOLVED:
The parent element of the textarea is a dot, and after hovering the dot it becomes a bigger circle and than it's inner elements are becoming visible. The problem was, that when adding the timeout the duration I've set was to short so the css transition for making the textarea visible was still going that's way it wasn't focusing.

Instead of this:
$(this).find('textarea').focus();
Try this:
$(e.target).find('textarea').focus();

This may work, as long as $(this).find('textarea') works as expected:
timeline.afterMilestonePrototypeCreated = function() {
$(MILESTONE_PROTOTYPE_SELECTOR).hover(function(e){
e.preventDefault();
$(this).find('textarea').focus();
});
}
A hover event triggers a focus event, so preventing it will allow the manual focus to occur.

Related

e.preventDefault() - issues with applying it to all but one div

I've read quite a few things on stack related to this issue, but I can't seem to solve my problem.
Essentially, I'm using jQueryModal (http://jquerymodal.com/).
What I want to have happen is, when the modal is launched, aka:
$(".buttonSpacing").click(function() {
$("#page").modal();
}
the modal opens up as expected. Contained in a div in that modal is a contenteditable div. Basically, I want to prevent default on everything except the contenteditable div. When the modal closes, I want events to then be unbound.
Something like this:
$(".buttonSpacing").click(function() {
$("#page").modal();
$(':not(#myContentEditableDiv)').bind('mousedown',function(e)
{
e.stopPropagation(); // Tried with and without this line
e.preventDefault();
});
}
doesn't seem to work. #myContentEditableDiv loses the default functionality as well as everything else.
If a previous question has answered this, I guess I wasn't able to apply it correctly to my situation.
The reason for this is I want the cursor to always remain in the editable area, wherever it is they left it, even when I'm having them select things to dynamically add to the editable area, or if they accidentally click outside of it.
Given my situation, how can I make this happen?
Thanks for your help.
EDIT:
Here's a js fiddle showing the problem:
https://jsfiddle.net/7Lwudpr4/2/
The problem is that the mouse down event is propagating from the text area to the parent elements, which are then preventing the default action. To fix this issue, add the following:
$('#textArea').bind('mousedown', function(e) {
e.stopPropagation();
})
Updated JSFiddle: https://jsfiddle.net/gp43028d/1/
Note that you'll probably need to handle the mouseup events on your other elements, as they won't fire click events since preventDefault() is called on the mousedown event.

Unexpected ionicons behaviour

Consider this code.
I cannot figure out why it behaves as it does. All I need is the play icon alternating with pause icon everytime I click anywhere inside the <td>. It behaves as expected when I click inside the <td> but outside the icon itself. However, if I click on the icon itself, it behaves fine the first time, and then stops.
'The ionicon is wrapped in the <a> tag, which is a child of the <td> element. The event listener is on the <td>, so what could be the problem?
Thanks.
As #Vijai said your problem with the hover event .. And While I don't know a lot about your project and you really need .empty() on hover or you just need to hide() the icon .. You can try this part of code instead of yours
var hovOn = function(event) {
if($(this).find('a').length < 1){
$(this).html(playButtonTemplate);
}else{
$(this).find('a').show();
}
};
var hovOff = function(event) {
$(this).find('a').hide();
}
Codepen Here
Ok, figured it out. It seems like an artefact that arises from creating an element from a template and the way mouseenter is implemented.
The problem is that the mouseenter event (hoverOn part of the .hover()) triggers when it shouldn't. Each time a new ionicon is created from a template it will trigger the mouseenter event if the cursor moves a little.
Logically mouseenter shouldn't be triggered when the element appears, because mouseenter should trigger when a listener element or its descendent is hovered over, and then only call when the cursor leaves all of the elements associated with the event and then enters again. I think this is an artefact of creating an element from a template like that. Maybe it's because DOM get updated and it discards the fact that the cursor is already within the element. So mouseenter triggers again and in turn triggers creating a new play icon. Then it repeats..
This codepen should explain it well. If you hover over the play button the mouseenter counter will increment each time you move your mouse even a little, because each time a mouse is moved, a new play button is created. If you delete the line that creates a new play button, it behaves as mouseenter should, triggering only when the cursor enters the element.
When you click on the <a> tag it seems it is also triggering the parent <td> hover event. Once solution is try the below code for hover.
var hovOn = function(event) {
if(playOrPause==='play') {
$(this).html(pauseButtonTemplate);
playOrPause = 'pause';
} else {
$(this).html(playButtonTemplate);
playOrPause = 'play';
}
};

Why is there a delay when blurring in CKEDITOR and can I get around it?

I'm trying to add a class to my body tag when I focus on an input, textarea, or CKeditor instance. And remove the class when I blur from any of these. The problem is that when I blur from a CKeditor instance and immediately focus on an input or textarea, the focus event happens before the blur event does. There is a significant delay when blurring from a CKeditor instance. I've tried using delay() and setTimeout() in addition to many other things and I can't get it to work. Since it's blurring after I focus, the focus event is adding the class to the body and then the blur event is removing the class.
I'm doing this because I need to reposition the header and hide the footer when the user is on a mobile device the keyboard displays. Below is the code I current have. Does anyone have any ideas on how I can get around this? Thanks!
if ($("html").hasClass("touch")) {
// Set focus and blur listeners for all editors to be created.
CKEDITOR.on( 'instanceReady', function() {
var editor = txtEditor.get_instance();
editor.on('focus', function(e) {
$("body").addClass(fix);
});
editor.on('blur', function(e) {
$("body").removeClass(fix);
});
});
$("input").on("focus", function(e) {
$("body").addClass(fix);
})
.on("blur", function(e) {
$("body").removeClass(fix);
});
}
The delay is caused by the focus manager. It waits 200ms for the next editor UI component to receive focus. It has to do wait, because in various cases and depending on browsers focus may be moved from one component (e.g. editable element) to another component (toolbar, elements path, dialog) with a significant delay. I know from my own experience that it can even exceed 100ms. If it wasn't waiting the editor#blur and editor#focus events would be fired many times when working within editor.
In your case, the input element should behave like editor's UI component. If it gets focus the same should happen as when editor gets focus and vice versa. I think that the easiest solution is to register it as editor's UI component:
CKEDITOR.on('instanceReady', function() {
var editor = txtEditor.get_instance();
editor.focusManager.add(new CKEDITOR.dom.element(inputEl));
editor.on('focus', function(e) {
$("body").addClass(fix);
});
editor.on('blur', function(e) {
$("body").removeClass(fix);
});
});
Thanks for your feedback, but I got it. I was able to place an editor.focusManager.forceBlur() statement in the focus statement of my input fields. That way the blur from any previous ckeditors is immediate. Thanks again though!
Jesse

JavasScript changing DOM in mouse-event

I have 2 DIVs and in each DIV there's a Button which does something on click.
Now I've added a piece of code to bring the DIVs to front when they get a mousedown. Which works very well. The problem is, that they swallow the mousedown of the inner button... The inner button can only be clicked by double clicking it.
http://jsfiddle.net/nUtz6/
$('div').mousedown(function (event) {
$(this).parent().append($(this));
});
how could I solve this problem? I did it this way because I don't want to increment the z-index of the CSS property to some magic number everytime I click the div. I read that jquery also does the DOM manipulation trick.
The problem seems to occur because I change the DOM right before the click-Event of the button. If I don't do anything in the mousedown, everything works fine.
Just check that the DIV is actually the target of the event :
$('div').mousedown(function (event) {
if (event.target.tagName.toLowerCase() != 'button')
$(this).parent().append($(this));
});
FIDDLE

How can I bind a JQuery event to make it only fire once?

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);
})

Categories

Resources