Input with clear icon - loss of focus issue - javascript

I have a clearable input like this:
+-----------------+
| x |
+-----------------+
The clear icon is a span with a font glyph in the :before:
<wrapper>
<input>
<icon span>
</wrapper>
Validation of inputs is done on blur (which re-renders the input View for validation message and icon changes - this keeps the architecture simple). The issue I am experiencing is that by clicking the icon the input triggers a blur and then the icon click.
Can you think of a way to either:
a) Avoid triggering a blur -- I can only think of ditching font glyph and using a background image, but I am already using other glyphs for required, invalid etc in that position so it is undesired
b) Detecting that the blur was caused by the icon and not something else
Thanks.
Edit: Here is one idea, a bit lame using a setTimeout though: http://jsfiddle.net/ferahl/td5VR/

Consider using mousedown and mouseup events to set/remove a flag.
http://jsfiddle.net/td5VR/4/
var wasClicked = false;
$('input').blur(function(){
$(".results").text(wasClicked ? "was clicked": "wasn't clicked");
});
$('.something').mousedown(function(){
wasClicked = true;
}).mouseup(function() {
wasClicked = false;
});
Though you still need to disable keyboard navigation to the link by setting tabindex="-1".

Here's a few ideas of what might be happening and some approaches to try:
This is a guess, but perhaps what you're experiencing is something called event bubbling. Take a look at this page to learn more about it. You can prevent event bubbling in your click handler like this:
IconElement.onclick = function(event) {
event = event || window.event // cross-browser event
if (event.stopPropagation) {
// W3C standard variant
event.stopPropagation()
} else {
// IE variant
event.cancelBubble = true
}
}
(If you're using jQuery, you don't need to worry about the "IE variant")
You could also try adding return false; or event.preventDefault() and see if that works.
And one more approach is to check event.target in your blur handler:
InputElement.onblur = function(event) {
event = event || window.event // cross-browser event
var IconElement = [do something to get the element];
if (event.target == IconElement) {
// Ignore this blur event, or maybe even call "this.focus()"
}
}

Here is the final very simple solution inspired by #Yury's answer:
$('.clearable-icon').mousedown(function() {
// This happens before blur, so return false and stop propagation.
return false;
});

Related

prevent previously defined events on mousedown for right-click only

I have a soundboard with buttons that trigger AJAX posts on mousedown.
The ideal functionality is to play an audio on left-mousedown and cancel playback on right-mousedown.
The code I have so far disables the context menu and cancels the playback...however, if they are over a button when they right-click (that triggers other previously defined events), it will still honor the mousedown and play that audio.
$(document).ready(function(){
document.oncontextmenu = function() {return false;};
$(document).mousedown(function(e){
if( e.which == 3 ) {
e.preventDefault();
Cancel_Playback();
return false;
}
return true;
});
});
I am trying to disable the right-mousedown from triggering the previously defined events but honor the Cancel_Playback. Any ideas?
EDIT
Updated Title and Description to more accurately reflect what I am trying to accomplish. This should also help: http://jsfiddle.net/g9sh1dme/15/
stopImmediatePropagation is probably the function you're looking for.
It cancels all other events bound to the the same element and any other delegates higher in the DOM. Order also matters as events are called in the order in which they were bound. You can only cancel events that were bound after the event doing the canceling.
I'm not sure if these changes maintain the validity of your program, but it demonstrates the function's use. Otherwise, I'd just check for right-mousedown in Play_Sound and exit out instead of banking on another event to cancel its execution.
Live Demo
$(document).ready(function(){
document.oncontextmenu = function() {return false;};
//For this to work you must bind to the same object or you must bind to something lower in the DOM.
$(".sound").mousedown(function(e){
if( event.which == 3 ) {
Cancel_Playback();
e.stopImmediatePropagation();
return false;
}
return true;
}).mousedown(Play_Sound);
})
function Cancel_Playback() {
alert("This is all that should be displayed on right-mousedown")
}
function Play_Sound() {
alert("Display this on left-mousedown... but not on right-mousedown")
}

How to stop CodeMirror from moving cursor on keyup?

I want to skip certain, uneditable (XML-)tags in my code, using CodeMirror. In order to do that, I have to 'stop' (preventDefault) the keyup event, do some logic and move the cursor. PreventDefault and codemirrorIgnore don't work or do not do what I need them to do. Do I have to catch the event outside CodeMirror? :(
Does not work:
codeMirror.on('keyup', function (cm, ev) {
ev.codemirrorIgnore = true;
ev.preventDefault();
return false;
});
By using the below code you can handle the up arrow functionality
codeMirror.setOption("extraKeys", {"Up":function()
{
console.log("Key Up pressed");
if(true) // logic to decide whether to move up or not
{
return CodeMirror.PASS;
}
}});
It sounds like what you actually want is markText with the atomic and readOnly options, rather than messing with key events (which won't really prevent the user from entering/editing the text).

jQuery alternative for document.activeElement

What I wanted to do is figure out whenever the user is engaged with an INPUT or TEXTAREA element and set a variable flag to true... and set that flag to false immediately after the user is no longer engaged with them (ie. they've clicked out of the INPUT/TEXTAREA elements).
I used jQuery's docuemnt.ready function to add the onclick attribute to my body element and assign it to my getActive() function.
The code for the getActive() function is as follows:
function getActive()
{
activeObj = document.activeElement;
var inFocus = false;
if (activeObj.tagName == "INPUT" || activeObj.tagName == "TEXTAREA")
{
inFocus = true;
}
}
I'd really like to keep by project withing the jQuery framework, but can't seem to find a way of accomplishing the same logic above using JUST jQuery syntax.
You want the focus and blur event handlers. For example...
var inFocus = false;
$('input, textarea').focus(function() {
inFocus = true;
});
$('input, textarea').blur(function() {
inFocus = false;
});
I'm pretty sure that a comma will get you input OR textarea, but you get the idea if that doesn't pan out
function getActive(){
return $(document.activeElement).is('input') || $(document.activeElement).is('textarea');
}
For the original question about figuring out if the currently focused element is any of those user input elements, below should work:
function isInputElementInFocus() {
return $(document.activeElement).is(":input");
}
Conceptually I don't like this approach for generic case where you are listening to global events (like key strocks) and trying to decide if these should be handled by your global handler or be ignored because it is meant for someone else. The reason I don't like it because it's not future safe and also who knows what else that someone can be besides input elements.
Another more robust but tricky to implement idea is to test if event is meant for an element that has tabIndex >= 0. The input elements have tabIndex === 0 set by default so it becomes more or less similar to above approach. You can easily check this by event.target.tabIndex >= 0 without need to rely on document.activeElement.
The gotchas here (if you want to be generic) is that you also need to make sure that event.target element is neither in another branch in DOM hierarchy nor there is someone else between event.currentTarget and event.target that has tabIndex >= 0. You get the idea: This can become murky but I just thought to jot it down if someone else is in need of generic solution.
You can do something like this :
var focusItem = null;
$('input, textarea').focus( function() {
focusItem = this;
});
Iis the .blur() event what you're looking for?

how to reverse e.preventDefault() from the body?

I have this:
function dontMove(event) {
// Prevent page from elastic scrolling
event.preventDefault();
}
&
<body ontouchmove="dontMove(event);">
This, on the ipad, stops it from being draggable and does not allow that grey background the ipad has when you drag a whole page around to show up.
I have seen on another website that its possible to reverse that in another div, so that div is completely draggable again.
Does anyone know how to reverse it?
I have also tried using this to prevent it (in the document.ready):
document.ontouchmove = function(e){
e.preventDefault();
}
& this to enable it:
function doTouchMove(state) {
document.ontouchmove = function(e){
return state;
}
}
Then I put this to activate it.
<img ontouchmove="doTouchMove(state);" src="../jpeg/pages/01.jpg" class="touch"/>
This didn't seem to work
Is there anything wrong with this?
Or any other way that might work?
This is exactly why bubbles is slightly better(at least in my opinion).
bubbles is cross browser, so you should be able to replace.
e.preventDefault()
with
e.bubbles = false;
and then latter in your code, you could potentially reset bubbles to true.
If the above isn't an option then just ignore. :D
An alternative(if you are just working with an iPad) is to just reverse how the DOM works.
document.addEventListener('click', function(){}, true );
This will force the event to work in the other direction.
Document click execute
|
|
v
Element click execute
try this post, HTML with event.preventDefault and erase ontouchmove from body tag.
Mine looks like this
<script>
// Get touch move enevt from IOS
document.ontouchmove = function (event) {
if (!event.elementIsEnabled)
event.preventDefault();
};
// Get touch move enevt from IOS
function enableOnTouchMove(event) {
event.elementIsEnabled = true;
};
</script>
then enable ontouchmove on every tag you want. ie:
<div ontouchmove="enableOnTouchMove(event)" id="listing">
I managed to solve it with
$('#form1').unbind('submit').submit();
You can solve it by preventing the event only if it comes from the body:
document.ontouchmove = function(event){
if(event.target.tagName == "BODY"){
event.preventDefault();
}
}

Jquery Listbox Change event does not fire on Keyboard scrolling

I've got a simple Listbox on a HTML form and this very basic jQuery code
//Toggle visibility of selected item
$("#selCategory").change(function() {
$(".prashQs").addClass("hide");
var cat = $("#selCategory :selected").attr("id");
cat = cat.substr(1);
$("#d" + cat).removeClass("hide");
});
The change event fires fine when the current item is selected using the Mouse, but when I scroll through the items using the keyboard the event is not fired and my code never executes.
Is there a reason for this behavior? And what's the workaround?
The onchange event isn't generally fired until the element loses focus. You'll also want to use onkeypress. Maybe something like:
var changeHandler = function() {
$(".prashQs").addClass("hide");
var cat = $("#selCategory :selected").attr("id");
cat = cat.substr(1);
$("#d" + cat).removeClass("hide");
}
$("#selCategory").change(changeHandler).keypress(changeHandler);
You'll want both onchange and onkeypress to account for both mouse and keyboard interaction respectively.
Sometimes the change behavior can differ per browser, as a workaround you could do something like this:
//Toggle visibility of selected item
$("#selCategory").change(function() {
$(".prashQs").addClass("hide");
var cat = $("#selCategory :selected").attr("id");
cat = cat.substr(1);
$("#d" + cat).removeClass("hide");
}).keypress(function() { $(this).change(); });
You can chain whatever events you want and manually fire the change event.
IE:
var changeMethod = function() { $(this).change(); };
....keypress(changeMethod).click(changeMethod).xxx(changeMethod);
The behavior you describe, the change event triggering by keyboard scrolling in a select element, is actually an Internet Explorer bug. The DOM Level 2 Event specification defines the change event as this:
The change event occurs when a control
loses the input focus and its value
has been modified since gaining focus.
This event is valid for INPUT, SELECT,
and TEXTAREA. element.
If you really want this behavior, I think you should look at keyboard events.
$("#selCategory").keypress(function (e) {
var keyCode = e.keyCode || e.which;
if (keyCode == 38 || keyCode == 40) { // if up or down key is pressed
$(this).change(); // trigger the change event
}
});
Check a example here...
I had this problem with IE under JQuery 1.4.1 - change events on combo boxes were not firing if the keyboard was used to make the change.
Seems to have been fixed in JQuery 1.4.2.
$('#item').live('change keypress', function() { /* code */ });

Categories

Resources