I'm trying to make my script only log the strings once. So when a new string is created it will only log the new strings... This script logs all of the strings at once. I would like to find a way to make it only log the .innerText of freshly created children in that element with the id "team_log_actual".
Children can be added at any point of time.
Here is my script:
setInterval(function() {
var logelement = $('#team_log_actual');
var foo = document.getElementById('team_log_actual');
for (let i = 0; i < foo.children.length; i++) {
//console.log(foo.children[i].innerText);
var PRINTactions = foo.children[i].innerText;
var PRINTactionsEle = foo.children[i];
var fields = PRINTactions.split(/ /);
var Username = fields[2]; //grabs the second field from the splitted string. which is the username..
var text1 = fields[3];
var text2 = fields[4];
var text3 = fields[5];
var text4 = fields[6];
var text5 = fields[7];
var text6 = fields[8];
var text7 = fields[9];
var text8 = fields[10];
var text9 = fields[11];
var text10 = fields[12];
//Defined multiple just in case. Each field will contain a string. If one is there, but it's highly unlikely to go past 5-6.
var combinetext = fields[3] + " " + fields[4] + " " + fields[5] + " " + fields[6] + " " + fields[7];
if (combinetext.includes("used item") == true) {
console.log(Username + " : " + combinetext) // log the Username and the combinedtext. Only if the combinetext includes the string "in ejector".
}
}
}, 10000); // Run every 10 seconds.
Solved using MutationObserver. Recommended by user: CodeWalker
// Solved code.
var Logconsole = document.getElementById('team_log_actual');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
for (var i = 0; i < mutation.addedNodes.length; i++) {
//This var gets the innertext of the new element.
var TextFromNewElement = mutation.addedNodes[i].innerText;
console.log(TextFromNewElement);
}
});
});
observer.observe(Logconsole, {
childList: true
});
//Test code. ----- Create a fake element every 5 seconds.
var testelement = document.createElement('div');
testelement.id = 'team_log_actual';
testelement.innerHTML = '<p> <b>[<span style="color: #0FF">USER:</span>] <bdi style="color: #0FF;">User2</bdi></b> harvest a plant.</p>'
setInterval(function(){
//every 5 seconds, add the test element.
Logconsole.appendChild(testelement)
}, 5000);
<div id="team_log_actual" class="log">
<p> <b>[<span style="color: #0FF">USER:</span>] <bdi style="color: #0FF;">User1</bdi></b> planted a seed.</p>
</div>
Related
I am trying to create a form which will generate different levels of forms based on the user input.
An example of this is
"How many levels are there?" -User input 3-
Three separate levels will be generated each with the same questions. In this there will be a question asking "How many objects are there?" the same will happen here in that multiple options will be generated.
Rough sketch of how the form would be displayed
The problem I've been having with this is allocating ids and then being able to fetch them after so that they can be referenced for use and MySQL later down the line.
function generateForm(){
var number = document.getElementById('number_of_levels').value;
var div = document.getElementById('levels');
// div.innerHTML += " " +number;
var heading = document.createElement("P");
heading.innerHTML = "Level " + number;
document.getElementById('levels').appendChild(heading);
var objects = document.createElement("P");
objects.innerHTML = "How many objects is the badge comprised of?";
document.getElementById('levels').appendChild(objects);
var num_objects_input = document.createElement("input");
num_objects_input.type = "number";
num_objects_input.id = "number_objects" +number;
document.getElementById('levels').appendChild(num_objects_input);
//num_objects.onchange = function(){addObject(num_objects.id)};
//div for the following levels
var ind_levels_div = document.createElement("div");
ind_levels_div.id = "level_" +number;
document.getElementById('levels').appendChild(ind_levels_div);
num_objects_input.onchange = function(){additionalObject()};
}
function additionalObject(){
var number = document.getElementById("number_objects" +number).value;
var objects_number = document.createElement("P");
objects_number.innerHTML = "Object " + number;
document.getElementById("level_" +number).appendChild(objects_number);
}
The result I'm getting is the form won't generate any Object form elements but will make the Levels.
For building the form this code works fine. If you want to retrieve data then you should add a name attribute what data you want to retrieve.
function generateForm() {
var number = 0;
number = document.getElementById('number_of_levels').value;
var div = document.getElementById('levels');
// div.innerHTML += " " +number;
if (number > 0) {
document.getElementById('levels_btn').setAttribute('disabled', 'disabled');
}
for (let index = 0; index < number; index++) {
var heading = document.createElement("h4");
heading.innerHTML = "Level " + (index + 1);
document.getElementById('levels').appendChild(heading);
var objects = document.createElement("p");
objects.innerHTML = "How many objects is the badge comprised of?";
document.getElementById('levels').appendChild(objects);
var num_objects_input = document.createElement("input");
num_objects_input.type = "number";
num_objects_input.id = "number_objects" + (index + 1);
document.getElementById('levels').appendChild(num_objects_input);
var submit = document.createElement("button");
submit.type = "button";
submit.innerHTML = 'objects';
submit.id = "submit" + (index + 1);
submit.onclick = additionalObject;
document.getElementById('levels').appendChild(submit);
var objectdiv = document.createElement("div");
objectdiv.id = "objects_level" + (index + 1);
objectdiv.className = 'objects_level';
document.getElementById('levels').appendChild(objectdiv);
}
}
function additionalObject() {
//console.log(Number(this.id.replace("submit", "")));
var pos = Number(this.id.replace("submit", ""));
var number = document.getElementById('number_objects' + pos).value;
for (let index = 0; index < number; index++) {
var objects_number = document.createElement("p");
objects_number.innerHTML = "Object " + (index + 1);
document.getElementById("objects_level" + pos).appendChild(objects_number);
}
}
.levels {
padding-left: 20px;
}
.objects_level {
padding-left: 40px;
}
<h3>Level</h3>
<form action="/" method="get">
<input type='number' name='number_of_levels' id='number_of_levels' />
<button type='button' id='levels_btn' onclick='generateForm()' />Levels</button>
<div id='levels' class='levels'></div>
<br><br>
<button type="submit">Submit Form</button>
</form>
You can read the article https://www.w3schools.com/tags/att_form_action.asp for getting the idea of how from action works according to retrieve the data
I wish to run this standalone code twice a day, but cannot solve the exception on the addLabel, which is "impossible to find the method", any suggestion? I tried to change the for cycle as well as to assign a var to the threads[i] but nothing changed.
function salvaNote(){
var d = new Date();
d.setMonth(d.getMonth()-6);
var n = d.getFullYear() + "/" + addZero(d.getMonth()+1) + "/" + addZero(d.getDate());
var folderName = 'tavoloTecnico';
labelName = GmailApp.createLabel('tavoloTecnico');
var query = 'in:anywhere from:mariano.casillo#mit.gov.it OR from:donato.castigliego#mit.gov.it has:attachment subject:previsioni filename:xls '+ 'after:'+n;
var threads = GmailApp.search(query);
var quanteMail = threads.length;
for ( var i = 0 ; i < quanteMail; i++) {
threads[i].addLabel(labelName);
var mesgs = threads[i].getMessages();
for(var j in mesgs){
var attachments = mesgs[j].getAttachments();
for(var k in attachments){
var attachment = attachments[k];
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
DriveApp.getFoldersByName(folderName).next().addFile(file);
}
}
}
}
The function I'm struggling with is part of a script that creates folders and copies a certain spreadsheet into each folder 15 times and names them.
I have a loop to create the files and inside of it I have an if..then..else statement to use a certain name for the file if j>10 and another name (else) if it's not. It always names the file one name and doesn't seem to recognize the if/else statement to change the name if j is over 10.
Basically what I want is to name the file
var namedFileCopy = fileCopy.setName(newFileName);
if j is less than 10 and...
var _namedFileCopy = fileCopy.setName("_" + newFileName);
if j isn't less than 10.
I'm wondering if I need to add a break in there somewhere, but I'm not really familiar with how to use breaks.
This is the function that is giving me a problem, and you'll find all my code in the snippet following it.
function putFilesIntoFolders(arrayOfFolderNames,theFolderNames,cell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getSheetByName('Sheet1');
var folderType = theSheet.getRange(2,1);
var cell = folderType.getValue();
var file = DriveApp.getFileById("ID");
var dest_folder = "";
var baseFileName = "",
newfile,
newFileName = "",
i=0,
j=0;
for (i=0;i<arrayOfFolderNames.length;i+=1) {
var source_folder = DriveApp.getFolderById("ID");
dest_folder = DriveApp.getFolderById(folderIds[i]);
Logger.log('dest_folder' + dest_folder);
baseFileName = arrayOfFolderNames[i];
for (j=1; j<16; j+=1) {
var newFileName = baseFileName + " " + cell + " " + j.toString();
var fileCopy = file.makeCopy();
var namedFileCopy = fileCopy.setName(newFileName);
var _namedFileCopy = fileCopy.setName("_" + newFileName);
if (j<10) {
dest_folder.addFile(namedFileCopy);
source_folder.removeFile(fileCopy);
} else {
dest_folder.addFile(_namedFileCopy);
source_folder.removeFile(fileCopy);
};
};
};
};
var folderIds = [];
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('Data System Tool')
.addItem('Create Data System Folders', 'copyAndRenameTemplate')
.addToUi();
}
function copyAndRenameTemplate() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getSheetByName('Sheet1');
var rangeOfFileNames = ss.getRange("B4:B");
var twoD_Array = rangeOfFileNames.getValues();
var arrayOfFileNames = twoD_Array.join().split(",");
var folderType = theSheet.getRange(2,1);
var cell = folderType.getValue();
Logger.log(folderType);
Logger.log(cell);
// throw new Error('This is not an error. This is just to abort javascript');
var fldrNamesRng = theSheet.getRange(4,1,theSheet.getLastRow()-3,1);
Logger.log('fldrNamesRng: ' + fldrNamesRng);
var folderNames = fldrNamesRng.getValues();
Logger.log('folderNames: ' + folderNames);
var oneD_FolderNames = folderNames.join().split(",");
Logger.log('oneD_FolderNames: ' + oneD_FolderNames);
makeTheFolders(oneD_FolderNames);
putFilesIntoFolders(oneD_FolderNames);
};
function makeTheFolders(theFolderNames,cell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getSheetByName('Sheet1');
var folderType = theSheet.getRange(2,1);
var cell = folderType.getValue();
var i=0,
folderObj;
for (i=0;i<theFolderNames.length;i+=1) {
folderObj = DriveApp.createFolder(theFolderNames[i] + " " + cell);
folderIds.push(folderObj.getId())
};
};
function putFilesIntoFolders(arrayOfFolderNames,theFolderNames,cell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getSheetByName('Sheet1');
var folderType = theSheet.getRange(2,1);
var cell = folderType.getValue();
var file = DriveApp.getFileById("ID");
var dest_folder = "";
var baseFileName = "",
newfile,
newFileName = "",
i=0,
j=0;
for (i=0;i<arrayOfFolderNames.length;i+=1) {
var source_folder = DriveApp.getFolderById("ID");
dest_folder = DriveApp.getFolderById(folderIds[i]);
Logger.log('dest_folder' + dest_folder);
baseFileName = arrayOfFolderNames[i];
for (j=1; j<16; j+=1) {
var newFileName = baseFileName + " " + cell + " " + j.toString();
var fileCopy = file.makeCopy();
var namedFileCopy = fileCopy.setName(newFileName);
var _namedFileCopy = fileCopy.setName("_" + newFileName);
if (j<10) {
dest_folder.addFile(namedFileCopy);
source_folder.removeFile(fileCopy);
} else {
dest_folder.addFile(_namedFileCopy);
source_folder.removeFile(fileCopy);
};
};
};
};
There's no issue about your loops, no need to break; out of them.
Your problem occurs in these lines of code:
var fileCopy = file.makeCopy();
var namedFileCopy = fileCopy.setName(newFileName);
var _namedFileCopy = fileCopy.setName("_" + newFileName);
The makeCopy() method will create a new file object, representing a new file in your Google Drive.
After that, you call the setName() method on the fileCopy object, which changes the name of the associated file. That's fine, except that you've assigned the return value of the method call to a new variable, namedFileCopy. You've now got two variables that reference the same object, because this method simply returns the original object for chaining. (Chaining is when we call multiple methods on on object in the same statement; it's only possible if each method returns the original object reference for the next method.)
Next, you call setName() on fileCopy again, assigning the return value to _namedFileCopy; that's the third reference to the exact same object. Oh, and that file - the file that all three object references point to - is now named with an underscore.
After this, your if..then..else is doomed to name the resulting file with an underscore. Actually... the file is already named with an underscore, from the third operation above.
Separate concerns some more; you've got to make a decision about a file name, so do that in isolation. Once you've completed that concern, you are ready to manipulate the file, which is a separate concern.
The resulting loop should look something like this:
for (i=0; i<arrayOfFolderNames.length; i++) {
var source_folder = DriveApp.getFolderById("ID");
dest_folder = DriveApp.getFolderById(folderIds[i]);
Logger.log('dest_folder' + dest_folder);
baseFileName = arrayOfFolderNames[i];
for (j=1; j<16; j++) {
// Determine the name for the new file
var newFileName = baseFileName + " " + cell + " " + j.toString();
// Prepend file name with underscore if j >= 10
if (j >= 10) newFileName = "_" + newFileName;
// Copy "file" and apply our newFileName, then move to new destination.
var fileCopy = file.makeCopy()
.setName(newFileName);
dest_folder.addFile(fileCopy);
source_folder.removeFile(fileCopy);
}
}
(I suspect this is what being said in Alvaz' answer.)
fileCopy.setName() changes the filename property of the file object. You should move your calls to fileCopy.setName() inside of your conditional branches.
I'm creating something which shows a list of cats and then increments a counter when the image is clicked. I've got everything working so when the image is clicked it increments the integer when I log it to the console. The only problem is that on the page the counter doesn't increment, it stays static at zero.
Here is my code. I've tried to create an update function which takes everything with the class tag and then loops through it replacing the HTML with the same thing so it redraws the text.
However it doesn't work. Any help would be appreciated!
var HTMLcatName = '<h1>%data%</h1>';
var HTMLcatImage = '<img id="cat" src="%data%">';
var HTMLcatCounter = '<p class="counter">Number of clicks: %data%</p>';
var noCats = 'No cats selected m8';
var cats = {
"name": ["Monte", "Jib"],
"image": ["images/monte.jpg", "images/jib.jpg"],
"clicks": [0, 0],
display: function () {
for (i = 0; i < cats.image.length; i++) {
formattedCatNames = HTMLcatName.replace("%data%", cats.name[i]);
var catNames = formattedCatNames;
formattedCatImages = HTMLcatImage.replace("%data%", cats.image[i]);
var catImages = formattedCatImages;
formattedCatCounter = HTMLcatCounter.replace("%data%", cats.clicks[i]);
var catCounter = formattedCatCounter
var elem = document.createElement('div');
elem.innerHTML = catNames + catImages + catCounter;
elem.querySelector('img').addEventListener('click', (function(catCountUp) {
return function() {
cats.clicks[catCountUp]++;
update();
};
})(i));
document.body.appendChild(elem);
}
},
}
cats.display();
var getCounterClass = document.getElementsByClassName("counter");
var update = function() {
for (j = 0; j < getCounterClass.length; j++) {
getCounterClass[j].innerHTML = '<p class="counter">Number of clicks: ' + cats.clicks[j] + '</p>';
}
}
I cannot see the click event, but this can be the error:
getTags.innerHTML = '<p class="counter">Number of clicks: ' + cats.clicks[j] + '</p>';
replace with
getTags[j].innerHTML = 'Number of clicks: ' + cats.clicks[j];
you are missing the counter in the for loop for targeting the right element
I have a loop with changing parameters wich I'd like to use in a oninput function of the sliders I'm creating within that loop, but I can't get it to work. Here's a simplified version of my script:
for (var con in dict) {
var div = document.getElementById("content");
var conDiv = document.createElement("div");
conDiv.innerHTML = "<b>" + con + ":</b><br>";
var effectID = dict[con].effect_id;
for (var param in dict[con].params) {
var inp,span = document.createElement("span");
span.innerHTML = " " + param + " ";
conDiv.appendChild(span);
inp = document.createElement("input");
inp.type = "range";
inp.min = vars[effectID][param].min;
inp.max = vars[effectID][param].max;
inp.value = dict[con].params[param];
inp.oninput = function(con,param,val) {
setParam(con,param,val);
}(con,param,this.value);
conDiv.appendChild(inp);
}
div.appendChild(conDiv);
}
What's wrong with my code?
edit: My goal: I have a set of audio effects that I want to change. Every container (con) controls an effect node via multiple parameters. All those parameters have different min- and max-values and an actual value they have right now. Via the sliders I want to be able to call a function that changes the parameters of an container. Therefore, every slider should control one effect parameter.
That's because the callback is called after the loop finish, so your variables have changed.
A usual trick is to use an immediately called function whose scope can store your variable values :
for (var con in dict) {
(function(con) { // <= creates a scope and a new con variable
var div = document.getElementById("content");
var conDiv = document.createElement("div");
conDiv.innerHTML = "<b>" + con + ":</b><br>";
var effectID = dict[con].effect_id;
for (var param in dict[con].params) {
(function(param){
var inp,span = document.createElement("span");
span.innerHTML = " " + param + " ";
conDiv.appendChild(span);
inp = document.createElement("input");
inp.type = "range";
inp.min = vars[effectID][param].min;
inp.max = vars[effectID][param].max;
inp.value = dict[con].params[param];
inp.oninput = function() {
setParam(con,param,inp.value);
};
conDiv.appendChild(inp);
})(param);
}
div.appendChild(conDiv);
})(con);
}