Understanding the execution of Jquery - javascript

I have a cell <td>:
And I have a script in jquery that when you double click it, it creates an <input type="text"> like this:
$("td").dblclick(function(event){
event.stopPropagation();
if($(event.target).prop("id")!="inputeditar"){ //WHEN I DOUBLE CLICK IN THE CELL
// I paste the value of the cell into the value of the input
$(document).one("click",function(event2){ //IF I CLICK OUT OF THE INPUT
if($(event2.target).prop("id")!="input")
{
$("#input").remove(); //THEN I REMOVE IT
}
});
}
});
So If I double click on the space in the cell, then the input gets the text from the cell, and if I click outside of the input then it dissappears.
It works fine but if I click in the input (instead of outside) then it will never dissappear whenever I click outside of it. I would like to keep checking if I am clicking outside and then, removing the input.

Add events inside event handlers is generally a bad idea, but you can acheive what you want like this:
$(document).on("click",function(event2) {
if ($(event2.target).prop("id")!="input")
{
//IF I CLICK OUT OF THE INPUT
//THEN I REMOVE IT
$("#input").remove();
$(document).off("click");
}
})
However $(document).off("click") seems like a really bad idea!
Following KevinB's comment about naming event handlers, you should be able to add a namespace to the event handler and turn it off as required:
$(document).on("click.removeinput",function(event2) {
if ($(event2.target).prop("id")!="input")
{
//IF I CLICK OUT OF THE INPUT
//THEN I REMOVE IT
$("#input").remove();
$(document).off("click.removeinput");
}
})
(but I've personally never used event namespaces, so see how it goes)
Alternatively you can re-attach the one() by using a named function, eg :
..."dblclick".., function() { ...
$(document).one("click", removeinput);
function removeinput(e) {
if ($(e.target).prop("id")!="input")
{
//IF I CLICK OUT OF THE INPUT
//THEN I REMOVE IT
$("#input").remove();
}
else
$(document).one("click", removeinput);
};

Related

JavaScript catch onfocus event

I have some inputs and a button. I want to implement function which allows to delete one of recently focused/focused out input.
I set onfocusout function which sets a click listener on button. If I focus on first input then focus out from it and click on button - works fine. But when I focus on first input, then on second and click on button - i get deleteCell() function performed n times i focused out.
How to let it remember only last onfocusout event? It seems to count my onfocusout events before clicking on button.
Thank you.
var input = document.createElement("input");
input.setAttribute("onfocusout", "myFunction()");
function myFunction() {
document.getElementById("delete-cell").addEventListener("click", function () {
deleteCell();
});
}
function deleteCell() {
alert(1);
}
Try adding an on-focusout listener to the relevant class of elements, and then add a "to-delete" class for the element focusedout (using "this" property). But only add this "to-delete" class after you have first removed it from all elements. This should keep you dialed into the element related to the most recent focusout event.
$(".element-class").on("focusout", function() {
$(".element-class").removeClass("to-delete");
$(this).addClass("to-delete");
})
Then simply write a function that will delete the element with the "to-delete" class, triggered by an on-click event.
Here is fiddle: https://jsfiddle.net/gbrodzik/ej4czqrc/6/

How to tell what triggered jQuery focus()?

I have an input field and a button. It is necessary that when the button is clicked the input field gets focus.
I need the behaviour to be slightly different depending on whether the input field was focused manually by the user or if it was focused due the button being clicked.
It seems this would be relatively simple, but I couldn't come up with a solution so far. Any ideas very welcome.
$("button").click(function() {
target_input = $("input");
target_input.focus();
});
$("input").focus(function() {
// if focus done manually by user
// do something
// if focus done via button
// do something else
});
Here is a solution that uses no extra variables, instead it checks the event.
$("button").click(function() {
target_input = $("input");
target_input.focus();
});
$("input").focus(function(e) {
// if focus done manually by user
// do something
// if focus done via button
// do something else
if(e.originalEvent.relatedTarget){
// only from button events
}
// here is from all events
});
this e.originalEvent.relatedTarget will return null if we didn't use the button to originate the focus.
remember to add e to the function.
You should be able to use Event.isTrusted for this:
The isTrusted read-only property of the Event interface is a boolean
that is true when the event was generated by a user action, and false
when the event was created or modified by a script or dispatched via
dispatchEvent.
$("input").focus(function(e) {
if(e.isTrusted) {...} else {...}
});
As noted in the comments, neither IE nor Safari like this.
This works without global variables and it is cross-browser working solution:
$('button').click(function () {
$(this).prev('input').focus()
})
$('input').click(function (e) { // yes, listen to click instead
// original event exists only if input was clicked directly
if (e.originalEvent) {
console.log('manually triggered')
}
})
<div style="background-color: yellow;">
<input type="text">
<button>Focus input</button>
<br>
<input type="text">
<button>Focus input</button>
</div>
<script src="https://unpkg.com/jquery"></script>

Putting restrictions on button

In my program an area called 'validDrop' is highlighted for the user to drag and drop items into.
A new area is highlighted when the button, 'minibutton' is clicked.
I want to tell the program to only allow the button to be clicked if the current area (validDrop) is styled by 'wordglow2' and 'wordglow4'.
I have tried this, Why won't it work?
if ($(validDrop).hasClass('wordglow2', 'wordglow4')) {
$('.minibutton').click(true);
} else {
$('.minibutton').click(false);
}
Because hasClass doesn't take more than one parameter, and because .click either triggers a click or binds a click listener, it doesn't set clickability.
Depending on what .minibutton is, you could do something like:
var valid = $(validDrop).hasClass('wordglow2') && $(validDrop).hasClass('wordglow4')
$('.minibutton').prop('disabled', !valid);
If it's not a type that can be disabled, you might consider something like this:
$('.minibutton').toggleClass('disabled', !valid);
And bind the click listener like so:
$(document).on('click', '.minibutton:not(.disabled)', function() {
// click action here
});
As ThiefMaster points out in comments, $(validDrop).is('.wordglow2.wordglow4') is a functionally equivalent way of checking that the drop has both classes.
You can alsou use .bind() and .unbind() to add and remove click event to your button as in my example http://jsfiddle.net/Uz6Ej/

jQuery bind to keyup only, not focus

This seems like a simple thing but google hasn't turned up anything for me:
How can I bind to a text / value change event only, excluding an input gaining focus? Ie, given the following:
$(function(){
$('input#target').on('keyup', function(){
alert('Typed something in the input.');
});
});
...the alert would be triggered when the user tabs in and out of an element, whether they actually input text or not. How can you allow a user to keyboard navigate through the form without triggering the event unless they input/change the text in the text field?
Note: I'm showing a simplified version of a script, the reason for not using the change event is that in my real code I have a delay timer so that the event happens after the user stops typing for a second, without them having to change focus to trigger the event.
Store the value, and on any key event check if it's changed, like so:
$(function(){
$('input#target').on('keyup', function(){
if ($(this).data('val')!=this.value) {
alert('Typed something in the input.');
}
$(this).data('val', this.value);
});
});​
FIDDLE
Simply use the .change event.
Update: If you want live change notifications then do you have to go through the keyup event, which means that you need to program your handler to ignore those keys that will not result in the value being modified.
You can implement this with a whitelist of key codes that are ignored, but it could get ugly: pressing Del results in the value being changed, unless the cursor is positioned at the end of the input in which case it does not, unless there happens to be a selected range in the input in which case it does.
Another way which I personally find more sane if not as "pure" is to program your handler to remember the old value of the element and only react if it has changed.
$(function() {
// for each input element we are interested in
$("input").each(function () {
// set a property on the element to remember the old value,
// which is initially unknown
this.oldValue = null;
}).focus(function() {
// this condition is true just once, at the time we
// initialize oldValue to start tracking changes
if (this.oldValue === null) {
this.oldValue = this.value;
}
}).keyup(function() {
// if no change, nothing to do
if (this.oldValue == this.value) {
return;
}
// update the cached old value and do your stuff
this.oldValue = this.value;
alert("value changed on " + this.className);
});
});​
If you do not want to set properties directly on the DOM element (really, there's nothing wrong with it) then you could substitute $(this).data("oldValue") for this.oldValue whenever it appears. This will technically have the drawback of making the code slower, but I don't believe anyone will notice.
See it in action.
This will do it, set a custom attribute and check against that:
$('input').focus(function(){
$(this).attr('originalvalue',$(this).val());
});
$('input').on('keyup',function(){
if($(this).val()===$(this).attr('originalvalue')) return;
alert('he must\'ve typed something.');
});
Be wary of events firing multiple times.
Here is another version that plainly tests if the input field is empty.
If the input is empty then the action is not performed.
$(function(){
$(selector).on('keyup', function(){
if ($(this).val()!='') {
alert('char was entered');
}
})
});

Change event precedence with JQuery

I have the following html code:
<input type="text" id="theInput" value=""/>
Click me
I want to detect when the input changes and perform an operation in this case, but ONLY when the user has not clicked in the link. I have tried this:
$('#theLink').live('click', function(){
alert('click');
});
$('#theInput').live('change', function(){
alert('change');
});
However change is always executed before click when the value in the input changed, due to Javascript event precedence rules, and therefore only "change" message is displayed.
I would like it to display change only if the input value changed and the user exited the input clicking in any other place instead of the link. In that last case I would like to display click.
The example is here.
I use jQuery 1.6.4.
As far as I know, the click event fires after the blur and change events in every browser (have a look at this JSFiddle). The order of blur and change is different across browsers (source: Nicholas Zakas).
To solve your problem, you could listen to click events on the document and compare the event's target with #theLink. Any click event will bubble up to the document (unless it is prevented).
Try this:
var lastValue = '';
$(document).click(function(event) {
var newValue = $('#theInput').val();
if ($(event.target).is('#theLink')) {
// The link was clicked
} else if (newValue !== lastValue) {
// Something else was clicked & input has changed
} else {
// Something else was clicked but input didn't change
}
lastValue = newValue;
});
JSFiddle: http://jsfiddle.net/PPvG/TTwEG/
Both events will fire but in your example the alert in the onchange event handler fired when the onmousedown event occurs will stop the onmouseup event required for the onclick event to fire. Using console.log will show both events firing.
http://jsfiddle.net/hTqNr/4/
Ok, now i got it, you could do
$('#theLink').live('click', function(e){
alert('click');
});
$('#theInput').live('change', function(e){
//Check if the change events is triggerede by the link
if(e.originalEvent.explicitOriginalTarget.data === "Click me"){
//if this is the case trigger the click event of the link
$('#theLink').trigger("click");
}else{
//otherwise do what you would do in the change handler
alert('change');
}
});
Fiddle here http://jsfiddle.net/hTqNr/19/
why you dont pick the value of input box. you have to store initial value of input box on ready function
initialvalue= $('#theInput').val();
then compare the value
$('#theLink').live('click', function(){
var newvalue =$('#theInput').val();
if(newvalue!=initialvalue) {
//do something
}
});

Categories