Trouble with multiple choice quiz - javascript

Having trouble with the code below. When user clicks a button, I want to set the value of clickedAnswer accordingly. Then I can validate the button clicked against the answer later on. Currently, I'm logging a 4 every time. Any help is greatly appreciated!
let clickedAnswer = 1;
function setClickedAnswer(button) {
if (button.id === "option1") {
clickedAnswer = 1;
} else if (button.id === "option2") {
clickedAnswer = 2;
} else if (button.id === "option3") {
clickedAnswer = 3;
} else {
clickedAnswer = 4;
}
validateAnswer();
console.log(clickedAnswer);
}
answer1.addEventListener("click", setClickedAnswer);
answer2.addEventListener("click", setClickedAnswer);
answer3.addEventListener("click", setClickedAnswer);
answer4.addEventListener("click", setClickedAnswer);

The function is expecting the button itself to be passed:
function setClickedAnswer(button) {
However, no such button is passed:
answer1.addEventListener("click", setClickedAnswer);
What is sent to an event handler by default is the event object itself, which has a target property referring to the element invoking the event. So you can do this:
if (button.target.id === "option1") {
(repeat for the other conditions, of course)
Alternatively, if you prefer the function to expect a button element, you can wrap a function around your event handler invokation and pass the element there:
answer1.addEventListener("click", () => setClickedAnswer(answer1));
or:
answer1.addEventListener("click", function () { setClickedAnswer(answer1); });

Related

Supress on click event in react

This is an on-click function for the identifier button. This function will trigger a popup design function when the user clicks on some feature on the map. I want this click functionality on that feature to be suppressed when the user clicks the identifier button a second time. This means the identifier button should act like a start-stop switch.
This function is inside useEffect() and the #IdentifierClick is the id for the button which is in return{} part which will trigger the click event.
const IdentifierClick = () => {
console.log("working");
// clicktimes = clicktimes+1;
// console.log("Button click times ",clicktimes)
if((enableIdentify == false))
{
initialMap.on('singleclick', function (evt)
{
console.log(evt, "printevt");
var myLayerChecked;
console.log(layerlist, "printlayerlist");
for (let i = 0; i <= 4; i++)
{
layerlist[1].values_.layers.array_[i].values_.layers.array_.forEach(arrayItem => {
myLayerChecked = arrayItem.state_.visible;
console.log("myLayerChecked", myLayerChecked);
// console.log(layerlists,"printlayerlist");
if (myLayerChecked == true) {
document.getElementById('popup-content').innerHTML = '<p class="identifier_p"><b>Identifier Details</b></p>';
console.log("My Array Data", arrayItem.values_.source)
designHtml(evt, arrayItem.values_.source, arrayItem.values_.title);
enableIdentify = true;
}
else
{
console.log("No Layer is checked");
}
});
}
})
}
else {
}
});
The intialMap.on('singleclick',function()) should be enabled and disabled by IdentifierClick function when we click to trigger the function. Please help me achieve this task.

Focus on inputfield after DOM is loaded with Blazor

I want that my inputfield is focused when when I open the Website, it always focus the Link when I start it.
Secondly I have to Sacn muliple numbers into my inputfield with a Scanner. It triggers my function addToTable. So my number will be added to a list. after that It should clear the inputfield and focus on it again, so I can scan in the next number:
<input id="LeNumber" name="LeNumber" #onkeydown="addToTable" #onclick:preventDefault="#isPreventDefault"/>
private async void addToTable(KeyboardEventArgs args)
{
if (args.Key != "Tab")
{
LeNumber += args.Key.ToString();
}
else
{
if (!string.IsNullOrWhiteSpace(LeNumber))
{
if (todos.Contains(LeNumber))
{
LeNumber = null;
await SetValueBack("LeNumber");
await TurnRed("table");
await Focus("LeNumber");
}
else
{
if (LeNumber == "submit")
{
generateXml();
b += 1;
}
else
{
todos.Add(LeNumber);
LeNumber = null;
await SetValueBack("LeNumber");
await TurnNormal("table");
await Focus("LeNumber");
}
}
}
}
}
The Problem now is that it doesn't set the focus back on my inputfield. To set my Focus I have a JS Function witch do: document.getElementByID(id).focus().
That doesn't work but it works if I put a delay in like the following:
function focusElement(id) {
setTimeout(function () {
document.getElementById(id).focus();
}, 3000);
}
I Think it doesnt work because the focus gets lost when it displays the List:
#{
for (int i = 0; i < todos.Count; i++)
{
if (i % 2 == 0)
{
#:<tr>
<td>#todos[i]</td>
}
else
{
<td>#todos[i]</td>
#:</tr>
}
}
}
Is there a way to set the focus after everything is done? Because It would be very "ugly" to do this with the delay
Blazor has a method for this. FocusAsync().
I believe if you call it in the OnAfterRender handler, or in your event handlers, you will achieve what you want.
https://www.youtube.com/watch?v=lLypM7oBwyA

How to preventDefault from external function and not in the event Listener?

I have this event listener, to submit a form.
document.getElementById("form").addEventListener("submit", (e) => {
const inputs = document.querySelectorAll('#form input');
// Check for empty fields
if ([...inputs].some(input => !input.value)) {
e.preventDefault(); // Prevent form submitted until all fields are not empty
}
for (var i = 0; i < inputs.length; i++) {
// Validate specific inputs - where "name" starts with "actual-temp"
if(inputs[i].name.startsWith("actual-temp")) {
validateActualTemp(inputs[i].value, inputs[i]); // This is another function to check values
}
}
});
And after this event Listener I have this function:
function validateActualTemp(value, item) {
if(value === '10') {
item.style.backgroundColor = 'red';
console.log(item);
}
}
This validates input fields - and checks if the number is shown. What I need to do now is, if the value === '10' then stop submitting the form, even if the fields are all filled out.
I have tried this:
function validateActualTemp(value, item) {
if(value === '10') {
preventDefault();
item.style.backgroundColor = 'red';
console.log(item);
}
}
But it is not working - How can I preventDefault(); in an external function?
Simply pass the event to the other function:
//...
validateActualTemp(inputs[i].value,inputs[i],e)
//...
function validateActualTemp(value, item,e) {
if(value === '10') {
e.preventDefault();
item.style.backgroundColor = 'red';
console.log(item);
}
}
Or return true/false from your validation function and handle everything else in the event handler callback.

How to remove previously bind event in jquery

On a checkbox change event, one of a javascript bind the toggle action.
Later on(in a different script) I want to change toggle action based on a condition.
Ex.
script 1:
$(document).ready(function () {
var shipFields = $('.address1 input');
$("input[name = 'same_as_bill']").on("change", function (evt) {
toggleFields(shipFields, !$(this).is(":checked"));
});
function toggleFields(fields, show) {
var inputFields = $("li", fields).not(".sameas, .triggerWrap");
inputFields.toggle(show);
}
}
Script 2:
$(document).ready(function () {
$('li.sameas input').click(function (sender) {
var target = $(sender.target);
var selectedCountryValue = $('li.country select', target.closest('fieldset')).val();
// determine data method based on country selected
if (selectedCountryValue === "xxx") {
ShowAddress(true, target);
} else {
ShowAddress(false, target);
}
});
function kleberShowAddress(show, target) {
if (show) {
$('li.address).hide();
} else {
$('li.address).show();
}
}
});
Issue I have here is, my site load the script 1 first and then the script 2. So by the time script 2 performs the action, toggle action is queued and will trigger that after the changes from script 2, that will revert the changes which I want.
Is there a way to remove the action in the queue? or stop happening first request. I do not want to use .unbind() which will stop triggering script 1 function. I just want to stop the action when ever it meets the condition in script 2.
Please note: above functions are trimmed to show less codes.
add var isActive = true; and use it to check in first script.
In script 2, you can call isActive = false any time you want to disable the first script's function or isActive = true for re-enable them.
Your code will look like:
//script1
var isActive = true;
$(document).ready(function() {
var shipFields = $('.address1 input');
$("input[name = 'same_as_bill']").on("change", function(evt) {
if (isActive) {
toggleFields(shipFields, !$(this).is(":checked"));
}
});
function toggleFields(fields, show) {
if (isActive) {
var inputFields = $("li", fields).not(".sameas, .triggerWrap");
inputFields.toggle(show);
}
}
});
//script2
$(document).ready(function() {
isActive = false;
$('li.sameas input').click(function(sender) {
var target = $(sender.target);
var selectedCountryValue = $('li.country select', target.closest('fieldset')).val();
// determine data method based on country selected
if (selectedCountryValue === "xxx") {
ShowAddress(true, target);
} else {
ShowAddress(false, target);
}
});
function kleberShowAddress(show, target) {
if (show) {
$('li.address').hide();
} else {
$('li.address').show();
}
}
});

problem in run some js codes after click

why after search and click on result search and click on plus(button add input) in the example on part Adding input, Date formating($('.find_input').delegate('input.date:text', 'keyup', ....) and normal number formatting($('.find_input').delegate('input.numeric:text','keyup',...) not work.
EXAMPLE: http://www.binboy.gigfa.com/admin/tour_foreign/insert_foreign
Js full code: http://jsfiddle.net/ZpDDR/
...
///// Date formating /////////////////////////////////////////////////////////////////////////////////////////
$dateSet = 0;
$monthSet = 0;
$yearSet = 0;
$('.find_input').delegate('input.date:text', 'keyup', function () {
$val = $(this).val().replace(/[^\d]+/g, "").match(/\d{1,12}$/);
if($val == null) {
return;
} else {
$val = $val.join("");
}
if($(this).val().match(/\d{4,}$/) && $val.length%2 == 0) {
$val = $val.match(/\d{2}/g);
if($yearSet < $monthSet) {
if($val.length == 4) {
$(this).val($val.join("").replace(/(\d{2})(\d{2})(\d{4})$/,'$3/$1/$2'));
$yearSet++;
} else if($val.length == 6){
$(this).val($val.join("").replace(/(\d{4})(\d{2})(\d{2})(\d{4})$/,'$4/$2/$3'));
$yearSet++;
}
} else {
if($monthSet < $dateSet) {
$(this).val($val.join("").replace(/(\d{4})(\d{2})(\d{2})(\d{2})$/,'$1/$4/$3'));
$monthSet++;
} else {
if($val.length == 2) {
$(this).val($val.reverse().join("/"));
$dateSet++;
$monthSet++;
} else {
$(this).val($val.join("").replace(/(\d{4})(\d{2})(\d{2})(\d{2})$/,'$1/$2/$4'));
$dateSet++;
}
}
}
}
});
///normal number formatting/////////////////////////////////////////////////////////////////////////////////////////
$('.find_input').delegate('input.numeric:text','keyup',function () {
$val = $(this).val().match(/[0-9]/g).reverse().join("").match(/[0-9]{1,3}/g).join(",").match(/./g).reverse().join("");
$(this).val($val)
});
The problem is that the element that you're delegating from,.find_input, doesn't exist yet when you're setting up the delegation function. delegate allows for defining event handlers for elements that aren't created yet, but only elements that match the second selector E.g., $('#must-exist-now').delegate('.can-be-created-later', ...);
I'm not sure if I described that well, but the solution is to change your statement to delegate from something that already exists on DOM load. For example: $(document).delegate('input.date:text', ...).

Categories