onchange event not tracking properly - javascript

I have a form that I want to track any changes. Right now I have it set so when the user exits the page, an alert box displays saying how many changes were made to the form. However, it keeps registering 0. I've tested with adding an alert to the inputChanges function telling me a change has occurred and the alert fires, but the count still registers as 0 when I exit the page...
Here's my script:
window.onload = function() {
var totalChanges = "";
var inputHandles = 0;
var selectHandles = 0;
var textAreaHandles = 0;
window.onbeforeunload = function(){
alert("Total Form Changes:" + totalChanges);
}//onbeforeunload
var totalChanges = inputHandles + selectHandles + textAreaHandles;
function inputChanges() {
inputHandles++;
alert("Change");
}
var inputs = document.getElementsByTagName("input");
for (i = 0; i < inputs.length; i++){
inputs[i].onchange = inputChanges;
}
function selectChanges(){
selectHandles++;
}
var selects = document.getElementsByTagName("select");
for (i = 0; i < selects.length; i++){
selects[i].onselect = selectChanges;
}
function textAreaChanges(){
textAreaHandles++;
}
var textAreas = document.getElementsByTagName("textarea");
for (i = 0; i < textAreas.length; i++){
textAreas[i].onchange = textAreaChanges;
}
}//Onload

You declare totalChanges here:
var totalChanges = "";
...and then re-declare it here:
var totalChanges = inputHandles + selectHandles + textAreaHandles;
...at which point the things you're adding up are all 0.
You need to do that calculation at the point where you need the value:
window.onbeforeunload = function(){
totalChanges = inputHandles + selectHandles + textAreaHandles;
alert("Total Form Changes:" + totalChanges);
}
Or set totalChanges = 0 initially and then increment it every time the other variables change, but that's clunkier.
Note also that you're not tallying the number of fields that now have values different to their starting values, you're tallying the number of individual edits. So if the user changes a field twice with the second change being back to the original value your code will track that as two changes (when logically it's kind of zero changes).

Since the user can change values back to what they were, I suggest you compare all input.value with input.defaultValue and check select.options[select.selectedIndex]defaultSelected
also you might want to move the } and the alert to after the sum of total changes
something like this
window.onload = function() {
var totalChanges = 0;
window.onbeforeunload = function(){
var inputs = document.getElementsByTagName("input"); // ditto for "textarea"
for (var i = 0; i < inputs.length; i++){
totaChanges += inputs[i].value != inputs[i].defaultValue;
}
var selects = document.getElementsByTagName("select");
for (var i = 0; i < selects.length; i++){
totalChanges += !selects[i].defaultSelected;
}
alert("Total Form Changes:" + totalChanges);
}//onbeforeunload
}

Related

Javascript Run one click then another

What I'm trying to do is make it open the breed_selector dropdown menu, and then select breed1, then .click, then move onto the next breed and click, and continue, It needs to do this three times, but unfortunately it only selects the first breed of dog and clicks, not all three.
Thanks
(function() {
var x = document.getElementById("breed_selector).options;
for(var i=0;i<x.length;i++){
if(x[i].text=="Labrador"){
x[i].selected=true;
document.getElementsByClassName("shop")[0].click();
break;
}
}
var x = document.getElementById("breed_selector").options;
for(var i=0;i<x.length;i++){
if(x[i].text=="poodle"){
x[i].selected=true;
document.getElementsByClassName("shop")[0].click();
})();
At the moment, it just doesn't do anything,
I have tried
var = document.getElementById("breed_selector").options;
for(var i=0;i<x.length;i++){
if(x[i].text=="poodle", "Labrador", "pug"){
x[i].selected=true;
document.getElementsByClassName("shop")[0].click();
break;
But the above doesn't work either, any input would be great, Thanks :)
UPDATED CODE which still doesn't work
(function() {
var x = document.getElementById("breed_selector").options;
for(var i=0;i<x.length;i++){
var text = x[i].text;
if(x[i].text === "Labrador" && text === "Pug"){
x[i].selected=true;
document.getElementsByClassName("shop")[0].click();
break;
}
}
})();
You could try this to click on ALL the options of the select element:
var breedSelector = document.getElementById("breed_selector");
var howMany = breedSelector.length;
var buttonShop = document.querySelector(".shop");
for (var i = 0; i < howMany; i++) {
breedSelector.selectedIndex = i;
buttonShop.click();
}
Note, though, that it will click the button several times in quick succession.
In order to select only certain options based on their value, you could try something like:
var breedSelector = document.getElementById("breed_selector");
var whichOnes = ["Labrador", "Poodle", "Golden"]; //whichever you want.
var buttonShop = document.querySelector(".shop");
whichOnes.forEach(function(breed){
breedSelector.selectedIndex = [].findIndex.call(breedSelector, function(option) { return option.textContent == breed});
buttonShop.click();
}

Check if inputs are empty or have text instead of numbers

as you can see here https://jsfiddle.net/kztnmm9o/ I am trying to check if the inputs are empty. If they are empty I want to display the div id="fehler", if every input has a value (must be a number, if not it shall display id="fehler" as well) I want to do the function. I am pretty new to javascript, might be a obvious mistake.
Thank you for your help!
This is the orignal javascript code without checking the inputs, which works:
var selectors = document.querySelectorAll("#eing1, #eing2, #eing3");
for (var i = 0; i < selectors.length; i++) {
selectors[i].addEventListener('keyup', function(event) {
event.preventDefault();
if (event.keyCode == 13) {
document.getElementById("button").click();
}
});
}
function ausgeben(){
var kostentisch = parseInt(document.getElementById("eing1").value)
var bruttogehalt = parseInt(document.getElementById("eing2").value)
var arbeitstage = parseInt(document.getElementById("eing3").value)
var stundenlohn = bruttogehalt/arbeitstage/8;
var arbeitszeit = arbeitstage*8;
var produktivitaetssteigerung = arbeitszeit*0.12;
var produktivitaetssteigerung2 = arbeitstage/produktivitaetssteigerung;
var gewinnprotag = produktivitaetssteigerung2*stundenlohn;
var amortisationszeit = Math.round(kostentisch/ gewinnprotag);
document.getElementById("arbeitszeit").innerHTML=arbeitszeit + " Stunden";
document.getElementById("produktivitaetssteigerung").innerHTML=produktivitaetssteigerung + " Stunden";
document.getElementById("amortisationszeit").innerHTML=amortisationszeit + " Tage";
}
updated fiddle: https://jsfiddle.net/kztnmm9o/3/
Changed the testing to this:
var test = document.querySelectorAll('input[type="text"]');
var error = false;
for (var i = 0; i < test.length; ++i) {
if (test[i].value == "")
{
test[i].style.borderColor = "red";
error = true;
}
}
I also made some minor changes following this logic, but it should be pretty simple to understand.
I also added this.style.borderColor = "transparent"; to keyup event but I'm not sure whether you like or not. So change on will.

Deselect a radio button in qualtrics

Is there a way to use the qualtrics javascript api (or, if not, a workaround) to programatically clear all entries made to radio buttons on a page?
My usage case is in a matrix table question that "pipes" (actually uses embedded data) values from the previous question to puts calculated numbers into the statements. However, if the respondent navigates back then when the return to the following question the numbers have changed but the responses have remained. As such, if it is the second time a respondent is viewing a page constructed like this, I want to clear all their previous answers.
I want to make sure that qualtrics' data is updated properly.
My survey is currently using the JFE engine if that makes a difference.
Qualtrics.SurveyEngine.addOnload(function() {
var QID = this.questionId;
var that = this;
var counts = [];
var radioButtonsClean = [];
var radioButtons = $(QID).getElementsByTagName('input');
var radioIndex = [];
for(var i=0; i<radioButtons.length; i++) {
if(radioButtons[i].type == 'radio') {
radioButtonsClean.push(radioButtons[i]);
radioIndex.push(radioButtons[i].id);
}
}
// Set counts for each displayed radio button to 0
for(var i=0; i<radioButtonsClean.length; i++) {
counts[i] = 0;
}
this.questionclick = function(event,element){
if (element.type == 'radio') {
var thisId = element.id;
var spotCheck = radioIndex.indexOf(thisId);
var count = counts[spotCheck];
if (count == 0) {
for(var i=0; i<counts.length; i++) {
counts[i] = 0;
}
counts[spotCheck] = 1;
}
else {
this.setChoiceValue(element.id.split('~')[2], element.id.split('~')[3], false);
counts[spotCheck] = 0;
}
}
}
});

Can we get radiobuttonList.Items.Count in .aspx page

Can we get the count of total radiobuttonlist items from .aspx page. I have to call a javascript function onclientclick of a button and i want to loop through the total number of radiobuttonlist items. So can anyone tell me that can we get it from .aspx page. Because in my scenario i can not use code behind for this.
function ClearRBL() {
for (i = 0; i < RBLCOUNT; i++) {
document.getElementById('rblWorkerList_' + [i]).checked = false;
}
}
How can i get RBLCOUNT here from .aspx page only? If not possible then in Javascript please.
I don't know how the aspx side would work, but if you want to do it just in JavaScript you could do something like the following that doesn't need to know the total number of elements in advance:
function ClearRBL() {
var i = 0,
rbl;
while (null != (rbl = document.getElementById('rblWorkerList_' + i++)))
rbl.checked = false;
}
The above assumes that the element ids end in numbers beginning with 0 counting up by 1s; the while loop will keep going until document.getElementById() doesn't find a matching element (in which case it returns null). A less cryptic way of writing it is as follows:
function ClearRBL() {
var i = 0,
rbl = document.getElementById('rblWorkerList_' + i);
while (null != rbl) {
rbl.checked = false;
i++;
rbl = document.getElementById('rblWorkerList_' + i);
}
}
P.S. When the while loop finishes i will be equal to the number of radio buttons, which may be useful if you want to do something with that number afterwards.
Try this:- This is not exactly what you want but hope it will help you.
function GetRBLSelectionID(RadioButtonListID) {
var RB1 = document.getElementById(RadioButtonListID);
var radio = RB1.getElementsByTagName("input");
var isChecked = false;
var retVal = "";
for (var i = 0; i < radio.length; i++) {
if (radio[i].checked) {
retVal = radio[i].id;
break;
}
}
return retVal;
}
you can give a name all radio button and then get them like this.
var RBLCOUNT= document[groupName].length;
or
var RBLCOUNT= 0;
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; ++i) {
if(inputs[i].type =="radio"){
RBLCOUNT++;
}
}
I just created a javascript function as mentioned by Karthik Harve and found the total number of rows generated dynamically as below: -
function ClearRBL() {
var rblLen = document.getElementById('rblWorkerList');
for (i = 0; i < rblLen.rows.length; i++) {
document.getElementById('rblWorkerList_' + [i]).checked = false;
}
}
It's working on both Mozila and IE.
Thanks alot to all who tried to help.

Get the value from only selected checkbox

I am trying to get the value from a checkbox using javascript.
I want only one checkbox value to be passed to the javascript function, and if multiple are selected, an alert box informing that only one box can be checked for the function.
I've tried this:
var publish_trigger = document.querySelector("#publish_trigger");
publish_trigger.onclick = function() {
var _posts = document.getElementsByName('post_id[]');
var check = _posts.checked;
var boxes = _posts.length;
var txt = "";
if(check.length > 1) {
alert("Only one at a time");
} else {
for (i = 0; i < boxes; i++) {
if (_posts[i].checked) {
txt = txt + _posts[i].value + " "
}
}
}
alert(txt);
return false;
}
This code is wrong:
var _posts = document.getElementsByName('post_id[]');
var check = _posts.checked;
getElementsByName() returns a NodeList (effectively an array) of elements, so your variable _posts doesn't have a checked property. You need to loop through _posts to count the checked property on the individual elements within _posts.
You already have a for loop so add the validation in there:
var count = 0;
for (var i = 0; i < boxes; i++) {
if (_posts[i].checked) {
if (++count > 1) {
alert("Only one checkbox may be checked at a time.");
return false;
}
// I don't know what you're trying to do with the following line
// but I've left it in.
txt = txt + _posts[i].value + " "
}
}
(Note: unrelated to your question, you should declare the loop counter i within your function otherwise it will be global and might lead to hard to debug problems if you are using it in other places too.)

Categories