Click event works on third or fourth try on button - javascript

This is a continuation of This
I used setTimeout() to place cursor on the input fields on pressing the tab, without which the focus goes to a link outside the <div> for some reason I am not aware of.
setTimeout() fixed that issue, but now:
On clicking on submit button the form does nothing but place cursor on the input fields for three or four times then proceeds with submitting.
Here is the submit button functions
$(“#submitbtn”).click(function(e) {
console.log(“click”);
e.preventDefault();
var s = setTimeout(function() {
removeTimeouts();
startValidation();
});
e.stopPropagation();
e.cancelBubble = true;
});
Here is hover function for Submit button
$(“#submitbtn”).mouseover(function(e) {
console.log(“Hover”);
removeTimeouts();
$(“#submitbtn”).focus();
e.preventDefault();
e.stopPropagation();
e.cancelBubble = true;
});
The function removeTimeouts() has all clearTimeout() for all setTimeout() through out the JavaScript file.
But somehow the click function is never works until third or fourth try.
The hover function works on first mouse move though, it prints “Hover” on console, every time the mouse it moves over submit button.
Even after clearing all setTimeout() somehow the focus is moved to input fields instead of proceeding with the console.log() onclick.
Can someone help me understand the issue and help fix the form gets submitted on first click?
Update:
1) This is typed from mobile app, even after re-editing the quote appearing as “” It’s correct in my code just not here.
2) Focus and timeout event is to validate the input fields while moving out of the input field, like if the field is empty, the cursor won’t move to next input field. But just focus is not working, and tab just takes the cursor out of the input fields to a link below it, so time-out helps keeping the cursor the input field.
3) Snippet - This does not replicate the issue as this is by far I can post the code sorry :(
(function ($) {
// Behind the scenes method deals with browser
// idiosyncrasies and such
$.caretTo = function (el, index) {
if (el.createTextRange) {
var range = el.createTextRange();
range.move("character", index);
range.select();
} else if (el.selectionStart != null) {
el.focus();
el.setSelectionRange(index, index);
}
};
// Another behind the scenes that collects the
// current caret position for an element
// TODO: Get working with Opera
$.caretPos = function (el) {
if ("selection" in document) {
var range = el.createTextRange();
try {
range.setEndPoint("EndToStart", document.selection.createRange());
} catch (e) {
// Catch IE failure here, return 0 like
// other browsers
return 0;
}
return range.text.length;
} else if (el.selectionStart != null) {
return el.selectionStart;
}
};
// The following methods are queued under fx for more
// flexibility when combining with $.fn.delay() and
// jQuery effects.
// Set caret to a particular index
$.fn.caret = function (index, offset) {
if (typeof(index) === "undefined") {
return $.caretPos(this.get(0));
}
return this.queue(function (next) {
if (isNaN(index)) {
var i = $(this).val().indexOf(index);
if (offset === true) {
i += index.length;
} else if (typeof(offset) !== "undefined") {
i += offset;
}
$.caretTo(this, i);
} else {
$.caretTo(this, index);
}
next();
});
};
// Set caret to beginning of an element
$.fn.caretToStart = function () {
return this.caret(0);
};
// Set caret to the end of an element
$.fn.caretToEnd = function () {
return this.queue(function (next) {
$.caretTo(this, $(this).val().length);
next();
});
};
}(jQuery));
var allTimeouts = [];
function placeCursor(id) {
id.focus(function(e) {
e.stopPropagation();
//e.cancelBubble();
id.caretToEnd();
});
id.focus();
}
function removeTimeouts(){
for(var i = 0; i < allTimeouts.length; i++) {
clearTimeout(allTimeouts[i]);
}
}
function focusInNumber (id) {
var thisID = id;
var nextID = id + 1;
var preID = id - 1;
//$("#number" + thisID).prop("disabled", false);
var s = setTimeout(function() {
placeCursor($("#number" + thisID));
});
allTimeouts.push(s);
if(preID != 0) {
if($("#number" + preID).val().length <= 0) {
var s = setTimeout(function() {
placeCursor($("#number" + preID));
});
allTimeouts.push(s);
}
}
}
function focusOutNumber (id) {
var thisID = id;
var nextID = id + 1;
var preID = id - 1;
var value = $("#number" + thisID).val();
var regex = new RegExp(/^\d*$/);
var regex1 = new RegExp(/^.*[\+\-\.].*/);
var l = $("#number" + thisID).val().length;
if(!value.match(regex)) {
alert("Just enter numerical digits");
var s = setTimeout(function() {
placeCursor($("#number" + thisID));
},5000);
allTimeouts.push(s);
} else {
if (l<=0) {
alert("This field cannot be empty");
var s = setTimeout(function() {
placeCursor($("#number" + thisID));
},5000);
allTimeouts.push(s);
} else {
if(value.match(regex)) {
var s = setTimeout(function() {
placeCursor($("#number" + nextID));
}, 100);
allTimeouts.push(s);
}
}
}
}
$(document).ready(function(){
$("#number1").focusin(function(){
focusInNumber(1);
});
$("#number1").focusout(function(){
focusOutNumber(1);
});
$("#number2").focusin(function(){
focusInNumber(2);
});
$("#number2").focusout(function(){
focusOutNumber(2);
});
$("#number3").focusin(function(){
focusInNumber(3);
});
$("#number3").focusout(function(){
focusOutNumber(3);
});
$("#number4").focusin(function(){
focusInNumber(4);
});
$("#number4").focusout(function(){
focusOutNumber(4);
});
$("#submitbtn").click(function(e) {
console.log("click");
e.preventDefault();
var s = setTimeout(function() {
removeTimeouts();
alert("startValidation()");
});
e.stopPropagation();
e.cancelBubble = true;
});
$("#submitbtn").mouseover(function(e) {
console.log("Hover");
removeTimeouts();
$("#submitbtn").focus();
e.preventDefault();
e.stopPropagation();
e.cancelBubble = true;
});
});
.SubmitBtn {
width: 100%;
background-color: #cccccc;
}
.Submitbtn:hover {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" class="reqField" id="number1" placeholder="Enter Number only"></input>
<input type="number" class="reqField" id="number2" placeholder="Enter Number only"></input>
<input type="number" class="reqField" id="number3" placeholder="Enter Number only"></input>
<input type="number" class="reqField" id="number4" placeholder="Enter Number only"></input>
<div id="submitbtn" class="SubmitBtn">Submit</div>

After breaking my head and console.log on all the statement to figure out the flow of code, I was able to find that on $("#submitbtn").click() there is some .focusout() is called.
As these .focusout() were necessary for on the go validation on the <input> fields, i tried to add $.(":focus").blur() and it worked along with adding a return false; on placeCursor() function.
The $.(":focus").blur() removes focus from any currently focused element. And this is a live saver for our logic of code.
So the code looks like
$("#submitbtn").mouseover(function(e) {
console.log("Hover");
$.(":focus").blur();
removeTimeouts();
$("#submitbtn").focus();
e.preventDefault();
e.stopPropagation();
e.cancelBubble = true;
});
....
function placeCursor(id) {
id.focus(function(e) {
e.stopPropagation();
//e.cancelBubble();
id.caretToEnd();
});
id.focus();
return false;
}
Hope this helps someone someday.
Thank you!

Related

Limit text input to numbers only

I want to implement a text input with the following implementations:
Only allow numbers
Limit numbers from 0 - 255
If an 'illegal' character was entered (non numbers, or over or under 255), the input should get disabled, wait a second, then delete the invalid char, and get back to focus.
I got all that implemented thanks to this answer. There's an issue though. If you enter 35 (that's 'legal'), then move the cursor between 3 and 5, then enter 1, which comes out to 315. That becomes 'illegal' because it's more than 255. So the 5 gets deleted. I don't want the 5 to get removed, I want the 1 to get deleted because that was the last one entered.
But if you enter 31, then 5, 5 should get removed. Basically, I want the last number entered to get deleted when an illegal amount gets inserted.
Also, I want the cursor to go to the position of the last removed character, whether it's a number or letter.
Here's the code:
JSFiddle
function disableInput(el) {
var checks = [/\D/g.test(el.value), el.value > 255];
if (checks.some(Boolean)) {
$(el).prop("disabled", true)
.queue("disabled", function() {
$(this).prop("disabled", false)
});
setTimeout(function() {
if (checks[0]) {
el.value = el.value.replace(/\D/g, '');
}
if (checks[1]) {
el.value = el.value.slice(0, 2);
};
$(el).dequeue("disabled").val(el.value).focus()
}, 1000)
}
}
$('input[name="number"]').keyup(function(e) {
disableInput(this)
$(this).focus();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input name="number" />
You can use selectionStart and selectionEnd to see where the cursor is in the input and then use those values to remove the correct character.
Fiddle: http://jsfiddle.net/o4bz0wr7/3/
function disableInput(el) {
var checks = [/\D/g.test(el.value), el.value > 255];
if (checks.some(Boolean)) {
$(el).prop("disabled", true)
.queue("disabled", function() {
$(this).prop("disabled", false)
});
setTimeout(function() {
if (checks[0] || checks[1]) {
el.value = el.value.slice(0, el.selectionStart - 1) + el.value.slice(el.selectionEnd);
}
$(el).dequeue("disabled").val(el.value).focus()
}, 1000)
}
}
$('input[name="number"]').keyup(function(e) {
disableInput(this)
$(this).focus();
});
EDIT: You can set the cursor position using setSelectionRange.
Fiddle: http://jsfiddle.net/o4bz0wr7/7/
function disableInput(el) {
var checks = [/\D/g.test(el.value), el.value > 255];
if (checks.some(Boolean)) {
$(el).prop("disabled", true)
.queue("disabled", function() {
$(this).prop("disabled", false)
});
setTimeout(function() {
var start = el.selectionStart - 1;
if (checks[0] || checks[1]) {
el.value = el.value.slice(0, start) + el.value.slice(el.selectionEnd);
}
$(el).dequeue("disabled").val(el.value).focus();
el.setSelectionRange(start, start);
}, 1000)
}
}
This should work fine with you, however if there is still any problem add it in comment.
Check it out in action here
var which = null;
function disableInput(el, $which) {
console.log(el.value);
var checks = [/\D/g.test(el.value), el.value > 255];
if (checks.some(Boolean)) {
$(el).prop("disabled", true)
.queue("disabled", function() {
$(this).prop("disabled", false)
});
setTimeout(function() {
console.log(String.fromCharCode($which));
el.value = el.value.replace($which, '');
// el.value = el.value.slice(0,el.value.length - 1);
$(el).dequeue("disabled").val(el.value).focus()
}, 1000)
}
}
$('input[name="number"]').keypress(function(e) {
which = String.fromCharCode(e.which);
$(this).focus();
}).keyup(function(){
disableInput(this, which);
})

Jquery : swap two value and change style

i need to make a script for select a black div by click(go red), and put black div value into a white div value by another click, this is ok but when i try to swap values of two white case, the change do correctly one time, but if i retry to swap two value of white case the values swap correctly but whitout the background color red.
This is my code :
var lastClicked = '';
var lastClicked2 = '';
$(".blackcase").click(function(e) {
var i = 0;
if ($(this).html().length == 0) {
return false;
} else {
e.preventDefault();
$('.blackcase').removeClass('red');
if (lastClicked != this.id) {
$(this).addClass('red');
var currentId = $(this).attr('id');
var currentVal = $(this).html();
$(".whitecase").click(function(e) {
$('.blackcase').removeClass('red');
var currentId2 = $(this).attr('id');
if (i <= 0 && $("#" + currentId2).html().length == 0) {
$("#" + currentId2).html(currentVal);
$("#" + currentId).html("");
i = 1;
}
});
} else {
lastClicked = this.id;
}
}
});
$(".whitecase").click(function(e) {
var j = 0;
if ($(this).html().length == 0) {
return false;
} else {
e.preventDefault();
$('.whitecase').removeClass('red');
if (lastClicked2 != this.id) {
$(this).addClass('red');
var currentId0 = $(this).attr('id');
var currentVal0 = $(this).html();
$(".whitecase").click(function(e) {
e.preventDefault();
var currentId02 = $(this).attr('id');
var currentVal02 = $(this).html();
if (j <= 0 && currentVal0 != currentVal02) {
$('.whitecase').removeClass('red');
$("#" + currentId02).html(currentVal0);
$("#" + currentId0).html(currentVal02);
j = 1;
return false;
}
});
} else {
lastClicked2 = this.id;
}
}
});
This is JSfiddle :
https://jsfiddle.net/12gwq95u/12/
Try to take 12 and put into first white case, put 39 into second white case, click on the white case with 12 (go red) then click on the white case with 39, the values swap correctly with the red color when it's select, but if you try to reswap two whitecase values thats work but without the red color.
Thanks a lot
I have spent some time to rewrite your code to make it more clear. I don't know what exactly your code should do but according to the information you have already provided, my version of your code is the following:
var selectedCase = {color: "", id: ""};
function removeSelectionWithRed() {
$('div').removeClass('red');
}
function selectWithRed(element) {
removeSelectionWithRed();
element.addClass('red');
}
function updateSelectedCase(color, id) {
selectedCase.color = color;
selectedCase.id = id;
}
function moveValueFromTo(elemFrom, elemTo) {
elemTo.html(elemFrom.html());
setValueToElem("", elemFrom);
}
function setValueToElem(value, elem) {
elem.html(value);
}
function swapValuesFromTo(elemFrom, elemTo) {
var fromValue = elemFrom.html();
var toValue = elemTo.html();
setValueToElem(fromValue, elemTo);
setValueToElem(toValue, elemFrom);
}
function isSelected(color) {
return selectedCase.color == color;
}
function clearSelectedCase() {
selectedCase.color = "";
selectedCase.id = "";
}
function elemIsEmpty(elem) {
return elem.html().length == 0;
}
$(".blackcase").click(function (e) {
if (elemIsEmpty($(this))) {
return;
}
alert("black is selected");
selectWithRed($(this));
updateSelectedCase("black", $(this).attr("id"), $(this).html());
});
$(".whitecase").click(function (e) {
removeSelectionWithRed();
if (isSelected("black")) {
alert("moving black to white");
moveValueFromTo($("#"+selectedCase.id), $(this));
clearSelectedCase();
return;
}
if(isSelected("white") && selectedCase.id !== $(this).attr("id")) {
alert("swap whitecase values");
swapValuesFromTo($("#"+selectedCase.id), $(this));
clearSelectedCase();
return;
}
alert("white is selected");
selectWithRed($(this));
updateSelectedCase("white", $(this).attr("id"), $(this).html());
});
Link to jsfiddle: https://jsfiddle.net/12gwq95u/21/
If my answers were helpful, please up them.
It happens because you have multiple $(".whitecase").click() handlers and they don't override each other but instead they all execute in the order in which they were bound.
I advise you to debug your code in browser console by setting breakpoints in every click() event you have (in browser console you can find your file by navigating to the Sources tab and then (index) file in the first folder in fiddle.jshell.net).
In general I think you should rewrite you code in such a way that you won't have multiple handlers to the same events and you can be absolutely sure what your code does.

How would I toggle the state of a setInterval function in jQuery?

I want to be able to click a an element with an id of pause to start a count of the elements in a time object and if I re click the pause it will stop it and reclick start it exactly like the toggle feature in JQuery but with a setInteval function how would I go about doing this?
$("#pause").click(function(ffe) {
if(on == true) {
on = false
alert("on");
}
else {
on = true;
alert("off");
}
if(on == false) {
setInterval(function() {
$("#timet ul").append("<li>" + $("#time ul")
.children('li').length +"</li>");
}, 100);
}
else {
alert("Error");
}
});
A classic technique is to use a single master setInterval loop and simply use if..else logic to determine what needs to run. This is how a lot of javascript games work:
var on = true;
// Our master scheduler:
setInterval(function() {
if (on) {
$("#timet ul").append("<li>" + $("#time ul")
.children('li').length +"</li>");
}
}, 100);
// Code to handle the pause button
$("#pause").click(function(ffe) {
on = !on;
}
You can use the setTimeout function, if you want to run the function once, setInterval runs continuously, try the following:
var on = false;
$("#pause").click(function(ffe) {
if (on) {
on = false;
setTimeout(function() {
$("#timet ul").append("<li>" + $("#time ul")
.children('li').length +"</li>");
}, 100);
} else {
on = true;
}
});
You need to use .clearInterval() to stop the execution.
Here is the code: (THE WORKING DEMO)
$("#pause").click((function () {
var interId = null;
var $ul = $("#timet ul");
return function (e) {
if (interId) {
$(this).text("start");
clearInterval(interId);
interId = null;
} else {
$(this).text("pause");
interId = setInterval(function () {
$ul.append($('<li>').text($('li', $ul).length));
}, 100);
}
};
}()));​

integrating two javascripts codes into one code to show alerts

In my first javascript i am showing alerts if any text box having class check is left empty before submitting, if all are filled then in second javascript i am showing an alert that confirm submit?. But how to make these two as one javascript code?
<script type="text/javascript">
jQuery('input.test').not('[value]').each(function() {
var blankInput = jQuery(this);
//do what you want with your input
});
function confirmation(domForm) {
var jForm = jQuery(domForm);
var jFields = jForm.find('.check');;
var values = jFields.serializeArray();
var failedFields = [];
for(var i = 0; i < values.length; i++) {
var o = values[i];
if(o.value == null || o.value.length == 0) {
failedFields.push(jFields.filter('[name=' + o.name + ']').attr('title'));
}
}
if(failedFields.length > 0) {
var message = '';
if(failedFields.length == values.length) {
message = 'fill all fields please';
}
else {
message = 'please fill the fields:';
for(var i = 0; i < failedFields.length; i++) {
message += "\n";
message += failedFields[i];
}
}
csscody.alert(message);
return false;
}
var answer = confirm("Confirm save?")
if (answer){
window.location = "confirmsubmit.jsp";
}
else{
return false;
}
return true;
}
</script>
javascript to show confirm submit alert after text boxes having class check are filled
<script type="text/javascript">
$().ready(function() {
$('#btn_submit').click(function(e) {
e.preventDefault();
var that = this;
var text = "Confirm save?";
csscody.confirm(text, {
onComplete: function(e) {
if (e) {
window.location = "confirmsubmit.jsp";
}
else {
return false;
}
}
})
});
});
</script>
html
<form action="confirmsubmit.jsp" onsubmit="return confirmation(this)" method="POST">
<input type="text" class="check"/>//alert if text box is left empty
<input type="submit" id="btn_submit"/>
</form>
I don't get why you need the second script. You call the validator function onsubmit. Why do change the window.location when you have set the same action? There is not point in binding the same function the the click-event of the button.
You don't need the second script, but have to change the first script.
function confirmation(domForm) {
// Your other code
// ...
if(failedFields.length > 0) {
// Your other code
// ...
csscody.alert(message);
return false;
}
// Your other code
// ...
/* Solution before your comment:
var answer = confirm("Confirm save?")
// This is already the action-target: window.location = "confirmsubmit.jsp";
return answer;
*/
var text = "Confirm save?";
csscody.confirm(text, {
onComplete: function(e) {
if (e) {
// Probably doesn't work because this seems to be asynchronous?
return true;
}
else {
return false;
}
}
});
}

Infield label not reappearing on empty field

I have the following code jquery plugin which was based on one from a while back (demo here: http://jsfiddle.net/3rNpb/) that allows a label to fade in and out based on the user inputting to a field.
The label fades out 50% when a user focuses and then back in if they blur. When they begin typing the label hides completely. And then if the field is empty and they blur again then the label fades back in.
The issue is that when the field is focused and the user deletes the value it does not show the label at 50% again until they blur the field (unfocus).
Can anyone help fix this?
Thanks
In your keydown.infieldlabel event handler, you have this call:
f.hideOnChange(e)
...and your hideOnChange function contains this code:
f.hideOnChange = function (e) {
if ((e.keyCode == 16) || (e.keyCode == 9)) return;
if (f.showing) {
f.$label.hide();
f.showing = false
};
f.$field.unbind('keydown.infieldlabel')
};
It looks to me that the unbind call at the end of your function will cause the keydown event handling to stop; perhaps you have no event handling attached for your backspace or delete key anymore because the event is unbound.
Try this, working fine
<label class="placeholder" for="test">Test Label</label>
<input type="text" id="test" />
(function ($) {
$.InFieldLabels = function (b, c, d) {
var f = this;
f.$label = $(b);
f.label = b;
f.$field = $(c);
f.field = c;
f.$label.data("InFieldLabels", f);
f.showing = true;
f.init = function () {
f.options = $.extend({}, $.InFieldLabels.defaultOptions, d);
if (f.$field.val() != "") {
f.$label.hide();
f.showing = false
};
f.$field.focus(function () {
f.fadeOnFocus()
}).blur(function () {
f.checkForEmpty(true)
}).bind('keydown.infieldlabel', function (e) {
f.hideOnChange(e)
}).change(function (e) {
f.checkForEmpty()
}).bind('onPropertyChange', function () {
f.checkForEmpty()
})
};
f.fadeOnFocus = function () {
if (f.showing) {
f.setOpacity(f.options.fadeOpacity)
}
};
f.setOpacity = function (a) {
f.$label.stop().animate({
opacity: a
}, f.options.fadeDuration);
f.showing = (a > 0.0)
};
f.checkForEmpty = function (a) {
if (f.$field.val() == "") {
f.prepForShow();
f.setOpacity(a ? 1.0 : f.options.fadeOpacity)
} else {
f.setOpacity(0.0)
}
};
f.prepForShow = function (e) {
if (!f.showing) {
f.$label.css({
opacity: 0.0
}).show();
f.$field.bind('keydown.infieldlabel', function (e) {
f.hideOnChange(e)
})
}
};
f.hideOnChange = function (e) {
if ((e.keyCode == 16) || (e.keyCode == 9)) return;
if (f.showing) {
f.$label.hide();
f.showing = false
};
f.$field.unbind('keydown.infieldlabel')
};
f.init()
};
$.InFieldLabels.defaultOptions = {
fadeOpacity: 0.5,
fadeDuration: 300
};
$.fn.inFieldLabels = function (c) {
return this.each(function () {
var a = $(this).attr('for');
if (!a) return;
var b = $("input#" + a + "[type='text']," + "input#" + a + "[type='password']," + "input#" + a + "[type='email']," + "input#" + a + "[type='tel']," + "textarea#" + a);
if (b.length == 0) return;
(new $.InFieldLabels(this, b[0], c))
})
}
})(jQuery);
$("label.placeholder").inFieldLabels();
What you want to do is listen for a keyup event and check to see if your input is empty upon each keyup. If it is, then you fadeIn your label.

Categories

Resources