I am clueless of how to do this, I am trying to edit the second line of a text file imported in html. This is my code so far:
let AddedItems = '';
function GenerateCode() {
const Out = document.getElementById("Output").value
const Quantity = document.getElementById("OutQuantity").value
const Time = document.getElementById("Time").value
if(Quantity < 1) return alert('You need to set a quantity greater than 0');
if(Time < 0) return alert('You need to set a time of aleast 0');
if(Out === '') return alert('You need to set a output item');
document.getElementById("CodeOut").innerHTML = ',{"itemId": "' + Out + '", "quantity": ' + Quantity + ', "craftTime": ' + Time + ', "ingredientList": [' + AddedItems + ']}';
}
function ResetItems() {
AddedItems = '';
GenerateCode();
}
function AddItem() {
const ItemQ = document.getElementById("IimeQ").value;
const Input = document.getElementById("Input").value;
if(ItemQ < 1) return alert('You need to set a quantity greater than 0');
if(Input === '') return alert('You need to set a input');
if(AddedItems === '') {
AddedItems = '{ "quantity": ' + ItemQ + ', "itemId": "' + Input + '"}';
} else {
AddedItems = AddedItems.concat(', { "quantity": ' + ItemQ + ', "itemId": "' + Input + '"}');
}
GenerateCode();
}
it is just calling functions when a button is clicked, but I need another function to get a text file and change the second to last line to "document.getElementById("CodeOut").innerHTML"
Use the FileReader API and pass the data from the file input. You can then split by line breaks and read it in as an array (if the file isn't massive, otherwise you should use some sort of a buffer)
document.getElementById('inputfile').addEventListener('change', function() {
const fr=new FileReader();
fr.onload=function(){
document.getElementById('output')
.textContent=fr.result;
}
let text = fr.readAsText(this.files[0]);
/*Split by a regex that looks at windows (\n)
and unix (\r) line breaks, then get the second line.*/
text.split(/[\r\n]+/g)[1];
})
Related
I have been stuck on this problem for a while now, Basically i want to populate the below select with option group and option check boxes. The text file imports to JS just fine, i'm getting the problem trying to populate the drop down. Here is my HTML:
function LoadTxtFile(p) {
var AllTxtdata = '';
var targetFile = p.target.files[0];
if (targetFile) {
// Create file reader
var FileRead = new FileReader();
FileRead.onload = function (e) {
if (FileRead.readyState === 2) {
AllTxtdata = FileRead;
// Split the results into individual lines
var lines = FileRead.result.split('\n').map(function (line) {
return line.trim();
});
var select = $("#MySelect");
var optionCounter = 0;
var currentGroup = "";
lines.forEach(function (line) {
// If line ends it " -" create option group
if (line.endsWith(" -")) {
currentGroup = line.substring(0, line.length - 2);
optionCounter = 0;
select.append("<optgroup id'" + currentGroup + "' label='" + currentGroup + "'>");
// Else if the line is empty close the option group
} else if (line === "") {
select.append("</optgroup>");
// Else add each of the values to the option group
} else {
select.append("<option type='checkbox' id='" + (currentGroup + optionCounter) + "' name'"
+ (currentGroup + optionCounter) + "' value='"
+ line + "'>" + line + "</option>");
}
});
}
}
FileRead.readAsText(targetFile);
}
}
document.getElementById('file').addEventListener('change', LoadTxtFile, false);
<html>
<body>
<select name="MySelect" id="MySelect"/>
</body>
</html>
I believe you are using append incorrectly as you are dealing with partial nodes with the optgroup. I would build the html snippet then append it in one go. This would also bring a performance benefit as multiple DOM manipulations can get expensive.
I'd do something like the following.
function LoadTxtFile(p) {
var AllTxtdata = '';
var htmlString = '';
//Optional Templates. I find them more readable
var optGroupTemplate = "<optgroup id='{{currentGroup}}' label='{{currentGroup}}'>";
var optionTemplate = "<option type='checkbox' id='{{currentGroupCounter}}' name='{{currentGroupCounter}}' value='{{line}}'>{{line}}</option>";
var targetFile = p.target.files[0];
if (targetFile) {
// Create file reader
var FileRead = new FileReader();
FileRead.onload = function (e) {
if (FileRead.readyState === 2) {
AllTxtdata = FileRead;
// Split the results into individual lines
var lines = FileRead.result.split('\n').map(function (line) {
return line.trim();
});
var select = $("#MySelect");
var optionCounter = 0;
var currentGroup = "";
lines.forEach(function (line) {
// If line ends it " -" create option group
if (line.endsWith(" -")) {
currentGroup = line.substring(0, line.length - 2);
optionCounter = 0;
htmlString += optGroupTemplate.replace("{{currentGroup}}", currentGroup);
// Else if the line is empty close the option group
} else if (line === "") {
htmlString +="</optgroup>";
// Else add each of the values to the option group
} else {
//I'm assuming you want to increment optionCounter
htmlString += optionTemplate.replace("{{currentGroupCounter}}", currentGroup + optionCounter).replace("{{line}}", line);
}
});
select.append(htmlString);
}
}
FileRead.readAsText(targetFile);
}
}
document.getElementById('file').addEventListener('change', LoadTxtFile, false);
NOTE the above is untested and may need some debugging.
I don't understand why the temp variable is only returning false. I have tried == just to see if using strict comparison was the issue, but it didn't change. Just to double check, I'm making sure the variables are of the same type by printing their type in console.
Another odd thing that is happening is when I use this line, console.log('temp = ' + temp); to see what is inside of temp, nothing but a blank space will print. But if I use console.log(temp);, it will print what is stored in temp. The console.log('temp = ' + temp); seems to have fixed itself, so nevermind with that issue, but it's still not returning true.
var upFormData = formData.toUpperCase();
console.log('Form Data: ' + upFormData);
degrees[str] = [];
degrees[str][0] = data[0];
for(var i = 1; i < data.length; i++)
{
var temp = data[i][5].toUpperCase();
console.log(temp);
//console.log('temp = ' + temp);
console.log('upFormData = ' + upFormData + ' ' + typeof upFormData + ' ' + typeof temp);
if(upFormData === temp)
{
console.log('MATCH');
}
else
{
console.log('NOT A MATCH');
//console.log(temp);
//console.log('upFormData = ' + upFormData + ' ' + typeof upFormData + ' ' + typeof temp);
}
Results of this script:
Can someone help explain what I'm not doing? And please let me know if you need more information.
EDIT:
Looks like you are want to check if the value entered in form (formData) is in data array.
Use some
var upFormData = formData.trim().toUpperCase();
var hasFormData = data.some( s => s[5].trim().toUpperCase() === upFormData ); //hasFormData will return true if any value matches
If you want to filter out data values which matches forData value, use filter
var matchedData = data.filter( s => s[5].trim().toUpperCase() === upFormData );
I have a recusive function that is supposed to loop through a json object and output the expression. However, my recusion seems to be off because it's outputting field1 != '' AND field3 == '' when it should be outputting field1 != '' AND field2 == '' AND field3 == ''
I've tried a couple different things and the only way I can get it to work is by creating a global variable outstring instead of passing it to the function. Where am I off? When I step through it, i see a correct result but once the stack reverses, it start resetting outstring and then stack it back up again but leaves out the middle (field2).
JSFiddle
function buildString(json, outstring) {
var andor = json.condition;
for (var rule in json.rules) {
if (json.rules[rule].hasOwnProperty("condition")) {
buildString(json.rules[rule], outstring);
} else {
var field = json.rules[rule].id;
var operator = json.rules[rule].operator;
var value = json.rules[rule].value == null ? '' : json.rules[rule].value;
outstring += field + ' ' + operator + ' ' + value;
if (rule < json.rules.length - 1) {
outstring += ' ' + andor + ' ';
}
}
}
return outstring;
}
var jsonObj = {"condition":"AND","rules":[{"id":"field1","operator":"!= ''","value":null},{"condition":"AND","rules":[{"id":"field2","operator":"== ''","value":null}]},{"id":"field3","operator":"== ''","value":null}]};
$('#mydiv').text(buildString(jsonObj, ""));
The function has a return of a string.
When you call the function recursively from within itself, you aren't doing anything with the returned string from that instance, just calling the function which has nowhere to return to
Change:
if (json.rules[rule].hasOwnProperty("condition")) {
buildString(json.rules[rule], outstring);
}
To
if (json.rules[rule].hasOwnProperty("condition")) {
// include the returned value in concatenated string
outstring += buildString(json.rules[rule], outstring);
}
DEMO
Why so complicated?
function buildString(obj) {
return "condition" in obj?
obj.rules.map(buildString).join(" " + obj.condition + " "):
obj.id + " " + obj.operator + " " + string(obj.value);
}
//this problem occurs quite often, write a utility-function.
function string(v){ return v == null? "": String(v) }
Okay, that title will sound a bit crazy. I have an object, which I build from a bunch of inputs (from the user). I set them according to their value received, but sometimes they are not set at all, which makes them null. What I really want to do, it make an item generator for WoW. The items can have multiple attributes, which all look the same to the user. Here is my example:
+3 Agility
+5 Stamina
+10 Dodge
In theory, that should just grab my object's property name and key value, then output it in the same fashion. However, how do I setup that if-statement?
Here is what my current if-statement MADNESS looks like:
if(property == "agility") {
text = "+" + text + " Agility";
}
if(property == "stamina") {
text = "+" + text + " Stamina";
}
if(property == "dodge") {
text = "+" + text + " Dodge";
}
You get that point right? In WoW there are A TON of attributes, so it would suck that I would have to create an if-statement for each, because there are simply too many. It's basically repeating itself, but still using the property name all the way. Here is what my JSFiddle looks like: http://jsfiddle.net/pm2328hx/ so you can play with it yourself. Thanks!
EDIT: Oh by the way, what I want to do is something like this:
if(property == "agility" || property == "stamina" || ....) {
text = "+" + text + " " + THE_ABOVE_VARIABLE_WHICH_IS_TRUE;
}
Which is hacky as well. I definitely don't want that.
if(['agility','stamina','dodge'].indexOf(property) !== -1){
text = "+" + text + " " + property;
}
If you need the first letter capitalized :
if(['agility','stamina','dodge'].indexOf(property) !== -1){
text = "+" + text + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
UPDATE per comment:
If you already have an array of all the attributes somewhere, use that instead
var myatts = [
'agility',
'stamina',
'dodge'
];
if(myatts.indexOf(property) !== -1){
text = "+" + text + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
UPDATE per next comment:
If you already have an object with the attributes as keys, you can use Object.keys(), but be sure to also employ hasOwnProperty
var item = {};
item.attribute = {
agility:100,
stamina:200,
dodge:300
};
var property = "agility";
var text = "";
if(Object.keys(item.attribute).indexOf(property) !== -1){
if(item.attribute.hasOwnProperty(property)){
text = "+" + text + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
}
Fiddle: http://jsfiddle.net/trex005/rk9j10bx/
UPDATE to answer intended question instead of asked question
How do I expand the following object into following string? Note: the attributes are dynamic.
Object:
var item = {};
item.attribute = {
agility:100,
stamina:200,
dodge:300
};
String:
+ 100 Agility + 200 Stamina + 300 Dodge
Answer:
var text = "";
for(var property in item.attribute){
if(item.attribute.hasOwnProperty(property)){
if(text.length > 0) text += " ";
text += "+ " + item.attribute[property] + " " + property.charAt(0).toUpperCase() + property.substr(1);
}
}
It's unclear how you're getting these values an storing them internally - but assuming you store them in a hash table:
properties = { stamina: 10,
agility: 45,
...
}
Then you could display it something like this:
var text = '';
for (var key in properties) {
// use hasOwnProperty to filter out keys from the Object.prototype
if (h.hasOwnProperty(k)) {
text = text + ' ' h[k] + ' ' + k + '<br/>';
}
}
After chat, code came out as follows:
var item = {};
item.name = "Thunderfury";
item.rarity = "legendary";
item.itemLevel = 80;
item.equip = "Binds when picked up";
item.unique = "Unique";
item.itemType = "Sword";
item.speed = 1.90;
item.slot = "One-handed";
item.damage = "36 - 68";
item.dps = 27.59;
item.attributes = {
agility:100,
stamina:200,
dodge:300
};
item.durability = 130;
item.chanceOnHit = "Blasts your enemy with lightning, dealing 209 Nature damage and then jumping to additional nearby enemies. Each jump reduces that victim's Nature resistance by 17. Affects 5 targets. Your primary target is also consumed by a cyclone, slowing its attack speed by 20% for 12 sec.";
item.levelRequirement = 60;
function build() {
box = $('<div id="box">'); //builds in memory
for (var key in item) {
if (item.hasOwnProperty(key)) {
if (key === 'attributes') {
for (var k in item.attributes) {
if (item.attributes.hasOwnProperty(k)) {
box.append('<span class="' + k + '">+' + item.attributes[k] + ' ' + k + '</span>');
}
}
} else {
box.append('<span id="' + key + '" class="' + item[key] + '">' + item[key] + '</span>');
}
}
}
$("#box").replaceWith(box);
}
build();
http://jsfiddle.net/gp0qfwfr/5/
I am writing an extension for a text-editor (Brackets) that can generate HTML and append libraries automatically in the HTML.
I have an Object called 'choice'.
This modal requests the users input:
choice grabs the user's input by defining methods on choice
partial JS here:
var choice = new Object();
choice.language = function () {
//Buid HTML top 'head'
var htmlTop = "<!DOCTYPE html>" + "<html>" + "<head lang='";
//Grab Selected Language Type
var languageChoice = document.getElementById("languages").value;
//Determine what Selected Language type is and complete HTML 'head'
if (languageChoice === "english") {
languageChoice = "en";
return htmlTop + languageChoice + "'>";
} else if (languageChoice === "german") {
languageChoice = "de";
return htmlTop + languageChoice + "'>";
} else if (languageChoice === "spanish") {
languageChoice = "es";
return htmlTop + languageChoice + "'>";
} else if (languageChoice === "french") {
languageChoice = "fr";
return htmlTop + languageChoice + "'>";
} else if (languageChoice === "italian") {
languageChoice = "it";
return htmlTop + languageChoice + "'>";
} else if (languageChoice === "chinese") {
languageChoice = "zh-cn";
return htmlTop + languageChoice + "'>";
}
}; //end choice.language
choice.charset = function () {
//Build meta and the rest of the 'head tag'
var htmlCharset_Beginning = "<meta charset='";
var htmlCharset_End = "'>" + "<title> -Insert Title- </title>" + "<!-- Insert CSS links below -->" + "</head>" + "<body>";
var charsetChoice = document.getElementById("charset").value;
if (charsetChoice === "utf8") {
charsetChoice = "UTF-8";
return htmlCharset_Beginning + charsetChoice + htmlCharset_End;
} else {
charsetChoice = "UTF-16";
return htmlCharset_Beginning + charsetChoice + htmlCharset_End;
}
}; // end choice.charset
choice.doctype = function () {
var doctypeChoice = document.getElementById("doctype").value;
return doctypeChoice;
}; // end doctype
choice.libraries = function () {
var checkedBoxes = getCheckedBoxes("lib_checkboxes");
checkedBoxes.forEach(function(item){
var scripts =+ $(item).data('script');
});//End forEach
var bottomHTML = scripts + "</body>" + "</html>";
return bottomHTML;
}; //End choice.libraries
var chosenTemplate = function(){
var template = choice.language() + choice.charset() + choice.libraries();
// insert html into file, this will overwrite whatever content happens to be there already
EditorManager.getCurrentFullEditor()._codeMirror.setValue(template);
// automatically close the modal window
$('#templates_modalBtn').click();
};
//Get checkedBoxes function
// Pass the checkbox name to the function
function getCheckedBoxes(chkboxName) {
var checkboxes = document.getElementsByName(chkboxName);
var checkboxesChecked = [];
// loop over them all
for (var i = 0; i < checkboxes.length; i++) {
// And stick the checked ones onto an array...
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i]);
}
}
// Return the array if it is non-empty, or null
return checkboxesChecked.length > 0 ? checkboxesChecked : null;
}
} // End action();
//JEFF STOP CODING HERE
// Register the commands and insert in the File menu
CommandManager.register(Strings.MENU_COMMAND, 'templates', action);
var menu = Menus.getMenu(Menus.AppMenuBar.EDIT_MENU);
menu.addMenuDivider();
menu.addMenuItem('templates');
}); //end define;
QUESTION:
Can I save multiple methods (each method returns a string) as a variable?
Example here:
var chosenTemplate = function(){
var template = choice.language() + choice.charset() + choice.libraries();
// insert html into file, this will overwrite whatever content happens to be there already
EditorManager.getCurrentFullEditor()._codeMirror.setValue(template);
// automatically close the modal window
$('#templates_modalBtn').click();
};
My code is loading with no errors, but its not executing at all so I am trying to debug and figure out what is going wrong...
Before you realize the function 'chosenTemplate', you should check whether the document stream of the page has already downloaded. If it not, you may not be able to get the value of the widget (empty).