Exit a callback method in javascript - javascript

Issue : I am using Cognex MX-1000 to scan barcodes. I have three textboxes and I am trying to scan barcodes and change the focus to next textbox. But after I scan the third textbox the value is always entered in third textbox even when the focus is on first textbox.
Cause : My code is not able to exit the innermost Setresultcallback function. Below is my method does anyone know how to exit the innermost callback function?
me.scanner.setResultCallback(function (result) { //First callback
var barcode = result.readString;
var txt1 = barcode;
document.getElementById("TextBox1").value = txt1;
document.getElementById("TextBox2").focus();
me.scanner.setResultCallback(function (result) { //Second callback
var barcode = result.readString;
var txt2 = barcode;
document.getElementById("TextBox2").value = txt2;
document.getElementById("TextBox3").focus();
me.scanner.setResultCallback(function (result) { //Third Callback & stuck here!!! I want to exit this function
var barcode = result.readString;
var txt3 = barcode;
document.getElementById("TextBox3").value = txt3;
document.getElementById("TextBox1").focus();
return;
});
return;
});
return;
});

That's because you leave the callback for the third field in the last callback. The following should fix the problem.
me.scanner.setResultCallback(/* Change here -> */ function firstFieldCallback(result) { //First callback
var barcode = result.readString;
var txt1 = barcode;
document.getElementById("TextRec1").value = txt1;
document.getElementById("TextRec2").focus();
me.scanner.setResultCallback(function (result) { //Second callback
var barcode = result.readString;
var txt2 = barcode;
document.getElementById("TextRec2").value = txt2;
document.getElementById("TextRec3").focus();
me.scanner.setResultCallback(function (result) { //Third Callback & stuck here!!! I want to exit this function
var barcode = result.readString;
var txt3 = barcode;
document.getElementById("TextRec3").value = txt3;
document.getElementById("TextRec1").focus();
/* Change here -> */ me.scanner.setResultCallback(firstFieldCallback);
return;
});
return;
});
return;
});

The problem is that you don't rebind to your first callback. Since you always do the same things into your callbacks :
Get the value
Write the value to the current input
Focus the next input
It can be simplified to something like this :
var me = {
scanner: {
setResultCallback: function(callback) {
setTimeout(function() {
callback({
readString: Math.floor(Math.random() * 100) + 1
})
}, 1000);
}
}
},
textboxes = ['TextRec1', 'TextRec2', 'TextRec3'],
index = 0;
function readValue(result) {
var barcode = result.readString;
document.getElementById(textboxes[index++]).value = barcode;
index = index === textboxes.length ? 0 : index;
document.getElementById(textboxes[index]).focus();
me.scanner.setResultCallback(readValue);
}
me.scanner.setResultCallback(readValue);
<input type="text" id="TextRec1" />
<input type="text" id="TextRec2" />
<input type="text" id="TextRec3" />
Don't mind var me = { ... I wanted something to simulate the behavior you're describing.

I've made a snippet to demonstrate how this can be done. Each function sets the callback to an existing function rather than creating a new one to set it to. I got it working with setInterval so you can see what's happening better; you can see that each new scan scan overwrites the next box, proving that the focus wraps around.
//Code to make this work in a snippet
var me = {};
me.scanner={};
me.scanner.setResultCallback = function(newcallback){scancallback=newcallback;};
//Set the callback to the first function; each function sets it to the next
me.scanner.setResultCallback(scan1);
//Simulate scanning stuff by manually calling the callback with time intervals; just pretend each time the function is called, it's called naturally by scanning with the scanner
setInterval(function(){
scancallback({randomField:"this is a scan result I guess",readString:Math.floor(Math.random()*10000)});
},1000);
function scan1(scanresult){
//Don't even need the variables, if you need them somehow you can add them back
document.getElementById("TextRec1").value =
scanresult.readString;
document.getElementById("TextRec2").focus();
me.scanner.setResultCallback(scan2);
}
function scan2(scanresult){
//Don't even need the variables, if you need them somehow you can add them back
document.getElementById("TextRec2").value =
scanresult.readString;
document.getElementById("TextRec3").focus();
me.scanner.setResultCallback(scan3);
}
function scan3(scanresult){
//Don't even need the variables, if you need them somehow you can add them back
document.getElementById("TextRec3").value =
scanresult.readString;
document.getElementById("TextRec1").focus();
me.scanner.setResultCallback(scan1);
}
<input type="text" id="TextRec1"/>
<input type="text" id="TextRec2"/>
<input type="text" id="TextRec3"/>

Related

Implement press and hold on a button

Thank you for the previous (deleted by moderator) explanation and the simple implementation but it does not work out for me. The 'holdit' function works but it is not is not steady probably because there is an 'onmouseup' in the 'holdit' function too, Even if I disable the onmouseup at the HTML button it's not very steady. Maybe it's better to use an addEventListener- onmousedown-interval function but again I don't know how to implement it in the simplest possible way. Here's the complete function that shows a pressed button and increases the timeSeconds var by one. For safety the var. number is within a limit.
Please help.
HTML:
<img id="but4" class="button" src= "//:0" onmousedown="timesecPlus();"onmouseup="timesecPlsUp();"/>
JAVASCRIPT:
function timesecPlus() {
var pmknop = document.getElementById('but5');
pmknop.src = secminBtndwn; //inline Base64 data: button image down (pressed)
timeSeconds = ((timeSeconds>wedstrijdperiode.seconden-6)?(timeSeconds):(++timeSeconds)); //You can ++ chase-back the timeseconds until 5 sec's from period start-time
displayTime( timeSeconds );
};
function timesecPlsUp() {
var pmknop = document.getElementById('but5');
pmknop.src = secminBtn; //inline Base64 data: button image up (normal)
};
// Things I tried:
//holdit(pmknop, function () { ++timeSeconds ; displayTime( timeSeconds );}, 2000, 2);
//pmknop = pmknop.addEventListener('mousedown', function() { interval = setInterval(timesecPlus (), 2000); });
function holdit(btn, action, start, speedup) {
var t;
var repeat = function () {
action();
t = setTimeout(repeat, start);
start = start / speedup;
}
btn.onmousedown = function() {
repeat();
}
btn.onmouseup = function () {
clearTimeout(t);
}
};
The holdit function is taking four variables. The first: btn, is the button id. This is used to determine the action performed whenever the mouse is clicked.
The second variable is a reference to a function. Its called a callback function, since you will be passing a function that will be Caaalleed whenever you call holdit.
The last two variables simply determine when and how long to delay the execution of the repetition and and by how much each repetition will speed up by.
var repeat = function () {
action();
t = setTimeout(repeat, start);
start = start / speedup;
}
Repeat is a recursive function that will be called after 'start' number of milliseconds and be repeated more frequently after each iteration.
Simple implementation:
var btn = document.getElementsByClassName('button')[0];
holdit(btn, function () { timeSeconds++ ; displayTime( timeSeconds );}, 1000, 2);
Implementation without holdit:
var btn = document.getElementsByClassName('button')[0];
var couterFunc, couter=0;
btn.addEventListener('mousedown',function(){couterFunc = setInterval(update,1000); update()})
btn.addEventListener('mouseup',function(){clearInterval(couterFunc)})
/* function that will fire when button press*/
function update(){console.log(++couter)};

Change value of first iteration input with next iteration input value

Structure Concept:-
Basically, i am trying to create the modal window containing input and that modal window currently fires when the input on index page get focused for that I have used data attribute to make a link between them by assigning them same attribute value.
Javascript Concept:-
for the modal window, I have created the modal object. and model object contains a bindModal method which takes one argument and that argument is data attribute value. after taking that value bindModal method will search dom elements containing that particular value and after the search, I iterate over them using each loop.
Problem
So basically I want whenever user starts typing on the model input it should get written automatically in input on the index page.
I will appreciate you all if guys help me out to make my code more optimized and well structured and most important thing is that let me know what mistake I have done in overall work Thanks
JavaScript Code
var modal = function () {
this.toggleModal = function () {
$('#modal').toggleClass('content--inActive').promise().done(function () {
$('#modal__close').on('click',function(){
$('#modal').addClass('content--inActive');
});
});
}
this.bindModal = function (bindVal) {
var bindValue = $(document).find('[data-modal-bind = ' + bindVal + ']');
$.each(bindValue, function (index) {
var bind1 = $(this);
if(index === 1) {
var bind2 = $(this);
$(bind1).change(function (){
$(bind2).val(bind1.val());
});
}
});
}
}
var open = new modal();
$('#input_search').on('click',function(){
open.toggleModal();
open.bindModal('input');
});
Here is one way to do what you want:
var modal = function() {
this.bindModal = function(bindVal) {
var bindValue = $('[data-modal-bind = ' + bindVal + ']');
bindValue.each(function(index) {
$(this).keyup(function() {
var value = $(this).val();
bindValue.each(function(i, e) {
$(this).val(value);
});
});
});
}
}
$('#input_search').on('click', function() {
var open = new modal();
open.bindModal('input');
});
Changes done:
I cached the inputs with same binding values in bindValue variable, and then bound the the keyup event for each of them. On keyup, the value of the current input is get in value, which is then assigned to each input using the inner loop.
This makes the inputs to be in sync while typing. Hope that solves your issue.

user input as javascript variable

I have written a small function in javascript to get user input from a text input form to be used as the delay time for fading away but it fails please help
<input type="text" class="form-control" id="new" placeholder="Fade Duration(milliseconds)"/>
var x = document.getElementById("new").value;
$(".fadeInbox").click(function () {
$("#section1").delay(x).fadeIn();
$("#section2").delay(x).fadeIn();
});
$(".fadeOutbox").click(function () {
$("#section1").delay(x).fadeOut();
$("#section2").delay(x).fadeOut();
});
var x from input is a string not a int, so
var x = parseInt(document.getElementById("new").value);
...
or
var x = +document.getElementById("new").value;
...
You should put the
var x = document.getElementById("new").value;
inside the functions, or it will be executed only once immediately after the script loads (and not work).
The delay should be checked inside the functions, otherwise the value will be checked only once - when the page loads. If it's inside the functions it will be checked every time the function is triggered.
$(".fadeInbox").click(function () {
var x = document.getElementById("new").value;
$("#section1").delay(x).fadeIn();
$("#section2").delay(x).fadeIn();
});
$(".fadeOutbox").click(function () {
var x = document.getElementById("new").value;
$("#section1").delay(x).fadeOut();
$("#section2").delay(x).fadeOut();
});

If the value of an input is greater than 0 dynamically populate other inputs on a page

Right now I'm using javascript to get the job done but i'm using onkeyup. This won't work for me because i'm using a button to populate the "var first". When a user pushes the button it populates the var first so there is no actual keyup/keydown.
<script>
window.onload = function () {
var first = document.getElementById('USERDEFINE1'),
//second = document.getElementById('ADDRESS2');
third = document.getElementById('PHONENIGHT');
fourth = document.getElementById('INTERNET');
fifth = document.getElementById('last_purchase');
sixth = document.getElementById('last_purchase_date');
first.onkeyup = function () { // or first.onchange
//second.value = '4444';
third.value = '111-111-1111';
fourth.value = 'NONE';
fifth.value = 'N/A';
sixth.value = 'N/A';
};
};
</script>
could i use something like:
if (document.getElementById(first.value) > 0
and if so how do i implement into my current javascript or should i rewrite it all together? Thanks in advance.
You will simply have to run the same population logic after pressing the button and after pressing a key in that input. You can also rely on other events like change, depending on how dynamic you want your interface to be.
Basically,
function populateInputs() {
//if we are in here, it means the value of first is > than 0
//at this point you can populate your other inputs
}
document.getElementById('your-button-id').addEventListener('click', function () {
first.value = 10; //init the value greater than 0
populateInputs(); //we know value is greater so populate
});
first.addEventListener('keyup', function () {
if (first.value > 0) {
populateInputs();
} else {
//first.value is not greater than 0
//reset input values to N/A or blank?
}
});

Problems to run Jquery code on button click on my Wizard-step Jquery code

I am using Wizard-step for my form in a view, My project is on MVC3.
I have a form that is made on 3 steps which means I have three tags for each step in my form
and two buttons that are following:
<p><input type="button" id="next-step" class="next-step-client-val" name="next-step" value="Next" /></p><
<p><input type="button" value="Back id="back-step" name="back-step"></p>
In my first step I have only a bunch of TextBoxes, DropDownlists and TextAreas, second step have alot of client-side functionality, one example is that user can move rows from a table to another one etc.. And I have a Jquery validation that is following:
var customTbl = $('#CustomPickedTable');
var has1 = customTbl.find('td[data-row="1"]').is('*');
var has2 = customTbl.find('td[data-row="2"]').is('*');
var has3 = customTbl.find('td[data-row="3"]').is('*');
var has4 = customTbl.find('td[data-row="4"]').is('*');
if ((has1 === true) && (has2 === true) && (has3 === true) && (has4 === true)) {
jAlerts("Saved", "Info");
} else {
jAlert('You have to move atleast one row from each table', "Varning"); ;
return false
}
On the 3th step its just a review on what was created and my next-step button submits the form, when a user clicks on it.
What I want to be able to do is that when a user is on the 2th step and clicks on next-step button the jquery validation above should run. With my Wizard-step code I cant do that beacuse it uses next-step button selector for everything. Is there any solutions for this?
I have tried to put my Jquery validation code inside
$("#next-step").click(function () {
}
But then my jquery validation code run everytime a user clicks on next button, beacuse my tables are shown in the form but hidden, the validation triggers on first step when a user click on next. So that solution didnt work.
This is my Wizard-step Jquery Code and right now I have my Jquery validation in the bottom which means that when im on 3th step and click on next-step button it will validate and then post. But I dont want it to be like that. I want the validation to happen on the 2th step.
Here is the code:
$(function () {
$(".wizard-step:first").fadeIn(); // show first step
// attach backStep button handler
// hide on first step
$("#back-step").hide().click(function () {
var $step = $(".wizard-step:visible"); // get current step
if ($step.prev().hasClass("wizard-step")) { // is there any previous step?
$step.hide().prev().fadeIn(4500); // show it and hide current step
// disable backstep button?
if (!$step.prev().prev().hasClass("wizard-step")) {
$("#back-step").hide();
}
}
});
// attach nextStep button handler
$("#next-step").click(function () {
var $step = $(".wizard-step:visible"); // get current step
var validator = $("form").validate(); // obtain validator
var anyError = false;
$step.find("select").each(function () {
if (!this.disabled && !validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
$step.find("input").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
$("#next-step").click(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
if ($step.next().hasClass("confirm")) { // is it confirmation?
// show confirmation asynchronously
$.post("/wizard/confirm", $("form").serialize(), function (r) {
// inject response in confirmation step
$(".wizard-step.confirm").html(r);
});
}
if ($step.next().hasClass("wizard-step")) { // is there any next step?
$step.hide().next().fadeIn(4500); // show it and hide current step
$("#back-step").show(); // recall to show backStep button
}
else { // this is last step, submit form
var selectedQuestions = $("#SelectedQuestions");
var selectedCustomQuestions = $("#SelectedCustomQuestions");
var currentIds = new Array();
var currentText = new Array();
$("#CustomPickedTable td[data-question-id]").each(function () {
var clickedId = $(this).attr("data-question-id");
currentIds.push(clickedId);
});
$('#CustomPickedTable td[data-attr-id]').each(function () {
var ClickedText = $(this).html();
currentText.push(ClickedText);
});
selectedCustomQuestions.val(currentText.join("|"));
selectedQuestions.val(currentIds.join(","));
var customTbl = $('#CustomPickedTable');
var has1 = customTbl.find('td[data-row="1"]').is('*');
var has2 = customTbl.find('td[data-row="2"]').is('*');
var has3 = customTbl.find('td[data-row="3"]').is('*');
var has4 = customTbl.find('td[data-row="4"]').is('*');
if ((has1 === true) && (has2 === true) && (has3 === true) && (has4 === true)) {
jAlerts("saved", "Info");
} else {
jAlert('You have to move atleast one row from each table', "Varning"); ;
}
return false;
}
});
My html code looks something like this:
<div class="wizard-step>
//step 1 content
</div>
<div class="wizard-step>
//step 2 content
</div>
<div class="wizard-step>
//step 3 content
</div>
<p><input type="button" id="next-step" class="next-step-client-val" name="next-step" value="Next" /></p><
<p><input type="button" value="Back id="back-step" name="back-step"></p>
I think it would be better if you detect at which wizard step you are using jquery .index() function. This way you can do the validation in your next step click handler only if you are on second step moving on to the third step. The code would look something like this :
$("#next-step").click(function () {
var $step = $(".wizard-step:visible"); // get current step
var stepIndex = $(".wizard-step").index($step); //index returns 0 based index so second step would be 1.
var validator = $("form").validate(); // obtain validator
var anyError = false;
$step.find("select").each(function () {
if (!this.disabled && !validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
$step.find("input").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
if(stepIndex == 1) //if you are on second step then validate your table
{
var customTbl = $('#CustomPickedTable');
var has1 = customTbl.find('td[data-row="1"]').is('*');
var has2 = customTbl.find('td[data-row="2"]').is('*');
var has3 = customTbl.find('td[data-row="3"]').is('*');
var has4 = customTbl.find('td[data-row="4"]').is('*');
if ((has1 === true) && (has2 === true) && (has3 === true) && (has4 === true)) {
jAlerts("Saved", "Info");
} else {
jAlert('You have to move atleast one row from each table', "Varning"); ;
return false
}
}
else if ($step.next().hasClass("confirm")) { // is it confirmation?
// show confirmation asynchronously
$.post("/wizard/confirm", $("form").serialize(), function (r) {
// inject response in confirmation step
$(".wizard-step.confirm").html(r);
});
}
if ($step.next().hasClass("wizard-step")) { // is there any next step?
$step.hide().next().fadeIn(4500); // show it and hide current step
$("#back-step").show(); // recall to show backStep button
}
else { // this is last step, submit form
var selectedQuestions = $("#SelectedQuestions");
var selectedCustomQuestions = $("#SelectedCustomQuestions");
var currentIds = new Array();
var currentText = new Array();
$("#CustomPickedTable td[data-question-id]").each(function () {
var clickedId = $(this).attr("data-question-id");
currentIds.push(clickedId);
});
$('#CustomPickedTable td[data-attr-id]').each(function () {
var ClickedText = $(this).html();
currentText.push(ClickedText);
});
}
});
I think you could approach this problem by refactoring the code
// validate the inputs in a form
// #param {string|object} jquery selector or jquery object
function validateStep (selector){
var $step = $(selector);
var validator = $("form").validate();
var anyError = false;
$step.find("select").each(function () {
if (!this.disabled && !validator.element(this)) {
anyError = true;
}
$step.find("input").each(function () {
if (!validator.element(this)) {
anyError = true;
}
if (!validator.element(this)) {
anyError = true;
}
return anyError;
}
This way you could validate the second step by calling
// this works because jquery returns an array of objects
// as a result of the css selector we call it with
// the eq() function accepts an index value that returns
// the jquery object at that position
// see. http://api.jquery.com/eq-selector/
validateStep($('.wizard-step').eq(1));
Or the first
validateStep('.wizard-step:first');
Etc
We could incorporate this into your code like this -
$('#next-step').click(function (event){
var $step = $('.wizard-step');
if(validateStep($step.filter(':visible'))){
// go to the next step
if ($step.next().hasClass("wizard-step")) {
$step.hide().next().fadeIn(4500);
$("#back-step").show();
} else {
// submit form
}
}
});
NB: You can read more about jQuery selectors here http://api.jquery.com/category/selectors/

Categories

Resources