Fix double call and get before value - javascript

I am learning JQuery by example. Please check this fiddle: http://jsfiddle.net/4tjof34d/2/
I have two problems:
1 : showText() gets called twice when a person hits enter and thus console.log(this.id+ " " +this.value); gets called twice, What do I add so that it only gets called once?
2: I get the id and value of the textbox, but I also want to know what was the old id and value so that I can do a comparison test. How do I do that?
eg:
var oldValue = ? // How do I do this?
var newValue = this.value;
Then I can do something like:
if(newValue != oldValue)
{
// Do .ajax() - update DB
}

for your first issue showText is called twice ie,on blur and on enter
change your blur function as follows
$('.input').blur(showText).keyup(function (e) {
if(e.which === 13) {
this.blur();
}
});
for second issue i will go with a global variable as flag
http://jsfiddle.net/x1ez7Lek/6/

Related

Keep value after submit form

I have this category checkbox where if I select certain values it will display div size but also in the same time when I select the checkbox it will submit the form. The problem is if I add this.form.submit() , the code below won't work and the form won't submit the value, but if I don't add it, the code will work.
How do I display div size and submit the form at the same time?
function getIds(checkboxName) {
let checkBoxes = document.getElementsByName(checkboxName);
let ids = Array.prototype.slice.call(checkBoxes)
.filter(ch => ch.checked==true)
.map(ch => ch.value);
return ids;
}
$(".category").on('change', function() {
this.form.submit();
let catIds = getIds("category[]");
$.each(catIds, function(index, value){
if (value == '1' || value == '2') {
$("#size").show();
} else if (value == '3') {
$("#size").hide();
}
});
});
This sounds like a racing problem. The form gets put into a different thread by the browser and gets handled first before the rest of the javascript is able to finish.
A quick (but dirty) hotfix for me is usually to use the setTimeout() method.
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
That way the javascript can work it's magic and afterwards the form gets submitted.

Prevent Select from changing selected option if condition is not met

I have a select box. Currently, this select box make an ajax call on change.
Now, I want to make call only when a condition is met.
So, here is my code:
$('#buildingSelect').on('change', function(){
var result = checkDirtyStatus();
//this checkDirtyStatus alert message if there is some changes on the form.
//if cancel return false, if confirm return true.
if(result === false) {
return;
}
//make ajax call
});
This prevents from making ajax call, however, this change the selected option of the select i.e, if option1 is selected at the begining and if I try to select next option then it will change the selected option to option2 then only check the status.
On searching on the internet, I got the option of focusin.
$('#buildingSelect').on('focusin', function(){
// console.log("Saving value " + $(this).val());
var result = checkDirtyStatus();
if(result === false) {
return;
}
}).on('change', function(){
g_building_id = $(this).val();
getAmenitiesDetails(g_building_id);
});
However, using this focusin options makes the alert box to appear everytime no matter either I click cancel or ok. This might be because, it call focusin again whenevr I click Ok or Cancel.
What would be the best option to check this status, and if result is false, I don't want to change the selected option as well.
Update
Answer from marked as duplicate not preventing from changing the selected option. Its making ajax call on click i.e. before checking condition.
CodePen Link
function checkDirtyStatus(){
dirtyStatus = true;
if(dirtyStatus === true){
if (confirm("Changes you made may not be saved.")) {
return true;
}else{
return false;
}
}
}
Finally, by mixing the link from Rory and idea of organizing code from some. I have find a solution for my problem. So, if anyone got stuck on the similar problem here is my solution.
$(function(){
var lastSel;
$('#buildingSelect').on('focusin', function(){
lastSel = $("#buildingSelect option:selected");
}).on('change', function(){
if(!checkDirtyStatus()) {
lastSel.prop("selected", true);
return;
}else{
//made ajax call
//$.ajax({})
}
});
});
function checkDirtyStatus(){
let dirtyStatus = getDirtyStatus();
if(dirtyStatus){
return confirm("Changes you made may not be saved.");
}
return true;
}
Let us look at your function:
function checkDirtyStatus(){
dirtyStatus = true; // I assume this is only for testing
if(dirtyStatus === true){ // This can be simplified.
if (confirm("Changes you made may not be saved.")) {
return true;
}else{
return false;
}
}
}
confirm returns a Boolean that is either true or false, so you can simplify your function like this:
function checkDirtyStatus(){
dirtyStatus = true;
if(dirtyStatus){
return confirm("Changes you made may not be saved.");
}
// Notice that you do not return anything here. That means that
// the function will return undefined.
}
Your other function can be simplified like this:
$('#buildingSelect').on('change', function(){
if(!checkDirtyStatus()){
// Here you probably want to set the value of the select-element to the
// last valid state. I don't know if you have saved it somewhere.
return;
}
//make ajax call
});
I played with your codepen and you have some errors in your selectors. As I get confused by your explanation I will try to explain what you could update and how to use it in your code and I hope this is what you need to solve your problem.
First I would change your js to this:
var lastSel = $("#buildingSelect").val();
$("#buildingSelect").on("change", function(){
if ($(this).val()==="2") {
$(this).val(lastSel);
return false;
}
});
The proper way to get the value of a select box in jquery is with the .val(). In your case you selected the entire selected option element.
I store this value in the lastSel variable. Then in the change function the new value of the select list is $(this).val(). I check against this value and if it equals 2 I revert it to the value stored in the lastSel variable with this $(this).val(lastSel).
Keep in mind that the value of a select list is always a string, if you want to check against a number you must first cast it to a numeric value e.g. by using parseInt.
If you want to use the checkDirtyStatus for the check then you should only call this function in the change and pass as parameters the lastSel and the newSel like this:
$("#buildingSelect").on("change", function(){
checkDirtyStatus(lastSel, $(this).val());
});
Then you can transfer the logic from the change function into the checkDirtyStatus function and do your checks there. In this case if you wish to revert the select value instead of $(this).val(lastSel) you will do a $("#buildingSelect").val(lastSel).
I hope this helps.

Javascript capturing keydown

I have a form with many fields and when the user does a "double Enter" in any of the fields doSomething() should happen.
The code below basically works ok, apart from the fact that doSomething() gets called as many times as there are characters in that field. It should only be called once, while if I put "ABC" in the field, doSomething() gets called 3X. It only needs to be called once after 2X Enter, regardless of what was entered in the field.
I (kind of) understand why it's happening (keydown was called 3 times) but have no idea how to fix it. Do I need to unbind something? Resetting the counter to 0 when e.keyCode isn't 13 doesn't seem to make a difference.
EDIT - http://jsfiddle.net/hzr8cezn/ - I'm using 2X SPACE bar character to test since Enter tries to submit the form on jsfiddle. Hit 2X space (in Chrome) and check your console
$("#dynamicFields").on('keydown', 'input', function(e) {
var counter = 0
var field = $(this)
field.keydown(function (e) {
if(e.keyCode == 13) {
counter++;
if(counter == 2) {
console.log('twice!')
doSomething()
}
}
else {
counter = 0
}
})
})
You are attaching to the "keydown" event twice, once using on() and the other using keydown(). You only need to do this once.
Since you are tracking the counter per element, you can use a data() call to track it on the element itself.
// init counter to 0
$("#dynamicFields input").data('counter',0);
// bind to keypress event
$("#dynamicFields").on('keydown', 'input', function(e) {
// the input field
var $field = $(this);
// enter key?
if ( e.keyCode == 13 ){
// how many times?
var counter = $field.data('counter');
// increment it
$field.data('counter',++counter);
// do the stuff
if ( counter >= 2 ){
alert('well, you did it.');
}
} else {
// reset
$field.data('counter',0);
}
})
See it working in this jsFiddle.

KeyboardState.pressed is always true after .prompt or alert - Why?

As the title says, I have tried THREEx and Stemkovskis standalone KeyboardState.js , and neither of them seems to update properly.
This is my code:
m_vKeyboard = new THREEx.KeyboardState();
// m_vKeyboard.update(); // if using stemkovskis
if (m_vKeyboard.pressed("F")) {
alert("And now it is always true!");
}
you click the F key once, release it; alert window pops up, click OK, it pops up again for all eternity. How come?
Many browsers repeat keydown. Read more here and here (ctrl+f : auto-repeat).
Here's a proposed solution for your specific problem :
A. when keydown store its state as true in some array and make it false on keyup.
wasPressed['F'] = true; //on keydown
wasPressed['F'] = false; //on keyup
B. when checking for next keydown check its state as well.
if (m_vKeyboard.pressed("F") && !wasPressed['F'])
Find full implementation : Here
UPDATE
var wasPressed = {};
if( keyboard.pressed('F') && !wasPressed['f'] ){
alert("F was pressed");
prompt("Enter data : ");
wasPressed['f'] = true;
}
UPDATE 2
keyboard.domElement.addEventListener('keydown', function(event){
wasPressed = {};
})
I'm wondering if it has something to do with alert() being a blocking call. Using the code below gives me your same issue. If I comment out the alert() and un-comment the console.log() it seems to work fine. However, I'm not sure if that helps your issue.
var m_vKeyboard = new THREEx.KeyboardState();
setInterval(function () {
var key = "F";
var pressed = m_vKeyboard.pressed(key);
alert("And now it is always true!");
//console.log("key", key, "pressed", pressed);
}, 100);
Just add this to the beginning of onKeyDown in KeyboardState.js:
if (event.repeat) return;

jQuery keydown event: Value coming delayed

I have following issue:
I got an event listener on an input field. On every keydown event the value of the input field should get validated. The problem is that the value assigned to the event-target is delayed:
You have an empty input field and type down one letter:
$('form.registration').keydown(function(e) {
var $el = $(e.target);
if ($el.val() == "") {
$el.closest("div.control-group").addClass("error");
}
console.log($el.val()); // this logs ""
});
You type in the second letter
$('form.registration').keydown(function(e) {
var $el = $(e.target);
if ($el.val() == "") {
$el.closest("div.control-group").addClass("error");
}
console.log($el.val()); // this logs the first letter (for example: "a")
});
As you see the value is always delayed by one letter.
How can I fix this?
I will suggest you use keyup instead. This will prevent your program running intensively when user presses the key and holds it, the content is being processed only after user releases the key. This method is very convenient in many cases.

Categories