I am wondering if it is okay to put html dom references in js oop. Although there are many JS OOP tutorials online, I haven't seen anything similar to what I am referring to. The code below is what I am referring to.
var form = {
fname : document.getElementById("fname").value;
};
say, for example the document.getElementById("fname").value is a textbox with a value of "jacob". would form.fname = "jacob"?
is this okay to do? is this a common practice to do?
you can do it if the object was created after the load event so you can make sure that the element "fname" is initialized ...
for example...
$(document).ready(function(){
var form = {
fname : document.getElementById("fname").value;
};
});
if you dont want to use jQuery here is another example ...
window.addEvent('load',function(){
//your object ...
});
I am not sure what you're trying to accomplish here. If you only need to retrieve the value that is currently in the input field, one time, ever, then this ought to be fine. If you're expecting the value of form.fname to continually update when the input value changes, you're not going to see that happen. You'd either need some handler tied to the change event of the input, or you'd need to do something more like this:
var form = {
fname: function () {
return document.getElementById('fname').value;
}
};
// Retrieving
form.fname()
Note that you have to invoke the fname function now, you can't simply refer to it as form.fname.
If you really don't want to ever have to retype things ever, do something like this:
var fields = ['fname', 'lname', 'city', 'state'];
var form = {};
for (var i = 0, j = fields.length; i < j; ++i) {
form[fields[i]] = function () {
return document.getElementById(fields[i]).value;
}
}
You'll have to be a little bit more careful with that if you add things like dropdown lists to your form, because their .value isn't as helpful, but you don't retype names if one changes.
And, if we really want to be fancy about it, you don't even have to type names when you get the values:
for (var i = 0, j = fields.length; i < j; ++i) {
console.log(form[fields[i]]())
}
Related
I have a game I created that will add questions missed to my array missedArr, in my JSFiddle example, I have 2 buttons (both set to be wrong answers). After clicking these, it seems to have stored both clicks correctly, however I want give a readout at the end of the game to show my user what parts they did well on vs ones they did poorly on.
To do this, I created a function called determineScorecard which should serve to create a dict of my missedArr, however, when it goes to trigger I get undefined.
The dSc function should be sorting across the data-category set on the html buttons, then I want to console.log only the ones that were missed in category-2
function determineScorecard (){
//build dictionary for missed questions
var sortedMissed = {};
for( var i = 0, max = missedArr.length; i < max ; i++ ){
if( sortedMissed[missedArr[i].category] == undefined ){
sortedMissed[missedArr[i].category] = [];
}
sortedMissed[missedArr[i].category].push(missedArr[i]);
}
console.log(sortedMissed["2"]);
}
I can't seem to get this to split up correctly.
I think this is what you're trying to do:
var incorrect = [];
$('.answer').click(function(){
var data = $(this).data(),
correct = data.correct;
if(!data.correct){
incorrect.push(data);
determineScorecard();
}
});
function determineScorecard(){
var missed = {};
for(var i = 0, max = incorrect.length; i < max ; i++){
var question = incorrect[i];
if(!missed[question.category]){
missed[question.category] = [];
}
missed[question.category].push(question);
}
console.log(missed);
}
DEMO
However, I don't see how this can produce what you're expecting. The scorecard logic makes zero sense to me (with the code that's been provided). Can you post a complete example with the questions so we can see the entire flow?
Maybe you want something like this?
var missedArr = [];
$('.answer').click(function(){
var da=$(this).data();
if (da.correct) return false;
missedArr.push(da);
determineScorecard();
});
function determineScorecard (){
var sortedMissed = {};
$.each(missedArr,(i,da)=>{
if( sortedMissed[da.category] === undefined ){
sortedMissed[da.category] = [];
}
sortedMissed[da.category].push(da);
})
console.log(JSON.stringify(sortedMissed));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button class="btn btn-danger answer" data-category="2" data-question="2" data-value="300" data-correct="false">Google</button>
<button class="btn btn-danger answer" data-category="3" data-question="2" data-value="300" data-correct="false">Full-circle reporting</button>
In my solution I have not stored the whole buttonDOM elements but only their data()-objects into the sortedMissed array since these contain all the information about the question and button pressed. But if you don't like it, feel free to change that back again ...
Referencing your JSFiddle: The missedArr array contains DOM elements. To get the category, value, etc of that element you'll need to access the dataset property of the element.
missedArr[i].category // doesn't exist
missedArr[i].dataset.category // should exist
Updated for jQuery, which uses the .data() method:
missedArr[i].data('category') // should exist
When wrapping 'this' in the jQuery function like $(this), the element becomes a jQuery object, so to access the dataset use the .data() method rather than trying to access the properties directly like you would with vanilla JS:
// lines 22 - 24 of your JSFiddle
if( sortedMissed[missedArr[i].category] == undefined ){
sortedMissed[missedArr[i].category] = [];
}
I need to submit a form in a google script but get this error:
TypeError: Cannot call method "withItemResponse" of undefined
According to the link below, this is how it should be set up https://developers.google.com/apps-script/reference/forms/form#createResponse()
Code:
//Submit form
var formID = row[24];
var form = FormApp.openById(formID);
Logger.log(form.getId()); //returns correct ID
form.createResponse() ;
form.FormResponse.withItemResponse('Core Teachers', logSummary);
//form has only two questions, a short text and a paragraph text
form.FormResponse.submit();
form.createResponse() returns a FormResponse, which you need to assign to a variable.
also, withItemResponse() expects an object of type ItemResponse. I am not familiar with google forms, but maybe this gets you in the right direction:
var formID = row[24];
var form = FormApp.openById(formID);
var formResponse = form.createResponse();
// get items of form and loop through
var items = form.getItems();
for (index = 0; index < a.length; ++index) {
var item = items[index]
// Cast the generic item to the text-item class. You will likely have to adjust this part. You can find the item classes in the documentation. https://developers.google.com/apps-script/reference/forms/item-type.
if (item.getType() == 'TEXT') {
var textItem = item.asTextItem();
var itemresponse = textItem.createResponse('Core Teachers');
formResponse.withItemResponse(itemresponse);
}
}
formResponse.submit();
Generally, when the documentation of a method lists as parameter type something else than primitive types like String or Boolean you need to create or aquire an object of that type, like I did with createResponse. You need to familiarize yourself with these and other principles because the GoogleAppsScript documentation assumes knowledge of them.
I have an array in js containing multiple clickable items. When I click any of them, I want to change the contents of other divs to show the corresponding name and description. I now use something like this:
window.addEventListener("load",function(){
var displayName = document.getElementById("display-title");
var displayDesc = document.getElementById("display-desc");
var projectNames = ["Name1", "Name2"];
var projectDescs = ["Example project 1", "Example project 2"];
var projectButtons = [document.getElementById("project-One"), document.getElementById("project-Two")];
for(var i = 0; i < projectButtons.length; i++){
projectButtons[i].addEventListener("click", function(){
displayName.innerHTML = projectNames[i];
displayDesc.innerHTML = projectDescs[i];
});
}
});
However when I click any of the buttons I always get the second name and description showing. How would I go about making it change to the selected button? In the final thing, I'm changing more than just the name and description, and I will be adding many more buttons in the array, so making different functions for each button isn't really an option, and I'm limited to using Javascript, so JQuery or PHP isn't an option. I'm probably missing something obvious, but I have no idea what...
EDIT:
The following seems to work, which is what was answered already, although I'm not sure if I've implemented it correctly:
for(var i = 0; i < projectButtons.length; i++) {
(function(i) {
setTimeout(function() {
projectButtons[i].addEventListener("click", function(){
displayName.innerHTML = projectNames[i];
displayDesc.innerHTML = projectDescs[i];
});
});
})(i);
}
This is the infamous closure variable in loop
http://www.teknically-speaking.com/2013/01/closures-in-loops-javascript-gotchas.html
I need to work with variables dynamically, and get them dynamically too. The first thing I need to know is:
How to save a variable reference(NOT its value) in a collection?
Example:
var divA = "<div>my div A</div>";
var divB = "<div>my div B</div>";
var divC = "<div>my div C</div>";
Then, save in a collection:
var mySet = new Set();
function returnDivA(){
return divA;
}
function returnDivB(){
return divB;
}
function returnDivC(){
return divC;
}
mySet.add(returnDivA());//I would like save the varible ref in a collection.
mySet.add(returnDivB());
mySet.add(returnDivC());
I want the Set collection to save the variables(NOT its values), it means:
var mySet = new Set(divA, divB, divC);
Then, with that, my intent is to do something like that:
var totalOfDivs;
for(var i = 0; i < mySet.size; i++){
totalOfDivs += mySet[i];
}
$("#anotherDIV_to_show_all_divs").html(totalOfDivs);//Then, here, I want to show all divs in the screen.
I would like suggestions, please!
It solved my problem to put variable dynamically in html using this in a for loop:
$("#anotherDIV_to_show_all_divs").append(mySet[i]);
About saving javascript variable reference in a Collection, I understand that I can't do that, because of the answer of the adeneo in comment:
"There is no "reference", all variables are pass-by-value in javascript..."
Read the documentation about set.
enter link description here
I guess you have to loop your set like this.
var totalOfDivs= "";
for (let item of mySet.values()) {
totalOfDivs+= item;
//console.log(item);
}
$("#anotherDIV_to_show_all_divs").html(totalOfDivs);
I have indexed a bunch of inputs in my html form.
I want to loop through the inputs and create an array. From that array I want to collect the total (sum) of the fields and finally append another HTML input to display that total.
I know how to do this in PHP but I am struggling with JavaScript and I need it done client side.
I have tried to construct as much of this as possible. Here is a jsFiddle:
Here is my html:
<div style="padding:5px;clear:both;"><input type="text" name="total_inkind" id="total_inkind" placeholder="$" onchange="calcInKind()"></div>
and Javascript:
function calcInKind() {
var runningTotal = 0;
var i = 0;
for (var i = 0; document.getElementById('inkind').value; i++){
if(document.getElementById('inkind').value != ''){
$gwyl_gr = document.getElementById('inkind').value;
$runningTotal = parseFloat($runningTotal) + parseFloat($gwyl_gr);
}else{
$gwyl_gr = 0;
}
i = i++;
}
document.getElementById('total_inkind').value = $runningTotal;
}
For something as simple as a sum of all the form elements, you don't really need an array unless you want to manipulate every value in more ways than one. You can however loop over every input you had in the form, taking its value and adding it to the total.
Looking at your code however, I have to remark that Javascript does not require variables to be preceded by a $ unlike PHP. You however have the opportunity to use them, which JQuery users often do, to denote that their variable is in fact a JQuery variable.
I forked your JSFiddle and rewrote some things to get it working as the question states: JSFiddle
function sumTheInkinds() {
var runningTotal = 0;
var ourlist = document.getElementsByClassName("inkind");
for (var i = 0; i < ourlist.length; i++) {
if (ourlist[i].value != '') {
try {
runningTotal = runningTotal + parseFloat(ourlist[i].value);
} catch (err) {
alert ("Value was not a float!");
}
}
}
document.getElementById('total_inkind').value = runningTotal;
};
document.getElementById("runcalc").onclick = sumTheInkinds;
My implementation however relies on a button press which may not be intended, which can easily be changed back to onchange by applying this:
var inks = document.getElementsByTagName("inkind");
for (var i=0;i<inks.length;i++) {
inks.onchange = sumTheInkinds;
}