I am writing a very simple programming language in Javascript. It has a lexer of only one word. When the word is called, the lexer is supposed to put the contents of an input box into an alert box. Instead, nothing happens. There is no error in the console, nothing. I am writing the lexer in a seperate file to the interpreter. Here is my code.
Lexer:
function ScratchLexer(text) {
var words = text.split(/\s+/);
var next = 0;
this.nextWord = function () {
if (next >= words.length) return null;
return words[next++];
};
}
function Scratch() {
var dictionary = {};
this.addWords = function (new_dict) {
for (var word in new_dict)
dictionary[word.toUpperCase()] = new_dict[word];
};
this.run = function (text) {
var lexer = new ScratchLexer(text);
var word;
while (word = lexer.nextWord()) {
word = word.toUpperCase();
num_val = parseFloat(word);
if (dictionary[word]) {
dictionary[word](this);
} else if (!isNaN(num_val)) {
this.stack.push(num_val);
} else {
throw "Unknown word";
}
}
};
}
var PrintingWords = {
"ALERT": function (terp) {
var tos = terp.document.getElementById("Text").value.pop(); alert(tos);
}
}
Interpreter:
<html>
<head>
<script type="text/javascript" src="scratch-lang.js"></script>
<script type="text/javascript">
var terp = new Scratch();
terp.addWords(PrintingWords);
terp.addWords(MathWords);
var alertwords = document.getElementById("TextAlert");
</script>
<style type="text/css">
body { Margin: 2em 5em; Line-height: 2em; Font-family: serif; }
body { Background-color: #ffffff; Color: #000000; }
#TextAlert { Width: 32em; }
#Text { Width: 32em; }
</style>
</head>
<body>
<br />
<input id="TextAlert" value = ""/><input id = 'run' type = 'button' value =
'Run' />
<br />
<input id="Text" value = ""/>
</body>
</html>
Is your <input id="TextAlert" value = ""/><input id = 'run' type = 'button' value ='Run' /> button hooked up to the lexer code in any way? I can't see how your lexical analysis is being initiated. You probably need to hook the run function up to the interface properly.
Some code like this will help you get started.
function handleRunClick(e) {
var value = document.getElementById("TextAlert").value;
terp.run(value);
}
<input id="TextAlert" value =""/><input id="run" type="button" onClick="handleRunClick" />
Related
I’m doing an exercise for high school. The exercise is to create an input and the input needs to be displayed 100 times ( 1) input 2) input 3) input, etc..) and you are not allowed to do it manually; you need to create a loop.
This is what I have so far. I tried googling it for an hour, but I didn't find anything.
<!DOCTYPE HTML>
<html>
<head>
<title>JS example</title>
<style>
body{font-size: 130%; background-color: teal; color: yellow}
input, button {font-size: 90%;}
#output {font-weight: bold; color: blue}
</style>
<script>
function getText(id){
var text = document.getElementById(id).value;
return text;
}
function showReply(id, reply){
document.getElementById(id).innerHTML = reply;
}
function reply(){
var textFromUser = getText("myTextField");
var str = something;
showReply("output", reply);
}
var something = [
[var text = "";]
[var i;]
[for (i = 0; i < 5; i++) {]
[reply += i + ")" + textFromUser;}]
]
</script>
</head>
<body>
<h1>What does a function say?</h1>
<p>Write some text in the text field and press the button.</p>
<input type="text" id="myTextField">
<button onclick="reply()">click?</button>
<p> Reply: <span id="output"></span> </p>
</body>
</html>
How can I do it?
You can create an element and append to your output container using a for loop. Try this:
function getText(id){
var text = document.getElementById(id).value;
return text;
}
function showReply(id, reply){
let container = document.getElementById(id);
let p = document.createElement('p');
p.textContent = reply;
container.appendChild(p);
}
function reply(){
var textFromUser = getText("myTextField");
for(let i = 0; i < 100; i++){
showReply("output", textFromUser);
}
}
<h1>What does a function say?</h1>
<p>Write some text in the text field and press the button.</p>
<input type="text" id="myTextField">
<button onclick="reply()">click?</button>
<p> Reply: <div id="output"></div> </p>
Variable i is used as a counter. If you want to change how many times it loops, just change the i<=num.
for (var i=1; i<=100; i++){
show_reply();
}
I suggest you to check this post on W3Schools.
I've made two files, one for HTML and the other for JavaScript.
Here is the JavaScript code:
function getText(id) {
let text = document.getElementById(id).value;
return text;
}
function showReply(id, reply) {
document.getElementById(id).innerHTML = reply;
}
function reply() {
let textFromUser = getText("myTextField");
let i;
let span1 = document.getElementById("output")
let usert = ""
for (i = 0; i < 100; i++) {
usert += "<br>" + textFromUser
}
span1.innerHTML = usert
}
Here is the HTML:
<!DOCTYPE HTML>
<html>
<head>
<title>JS example</title>
<style>
body{font-size: 130%; background-color: teal; color: yellow}
input, button {font-size: 90%;}
#output {font-weight: bold; color: blue}
</style>
<script src="main.js"></script>
</head>
<body>
<h1>What does a function say?</h1>
<p>Write some text in the text field and press the button.</p>
<input type="text" id="myTextField">
<button onclick="reply()">click?</button>
<p> Reply: <span id="output">dd</span> </p>
</body>
</html>
There are many different potential solutions for this type of question. Choose the flavor you like and put your own spin on it.
function showReply(id, reply){
document.getElementById(id).innerHTML = reply.join('<br>');
}
function reply(){
var textFromUser = getText('myTextField');
var outputs = [];
for (let i = 0; i < 100; i++){
outputs.push(`#${ i } ${ textFromUser }`)
}
showReply('output', outputs);
}
let words = [];
var longestCt = 0;
var longestWord = "";
var myList = [];
var myList = ['Loops','are','used','while','Learning JavaScript'];
function addWords() {
let template = words.map(word => `<li>${word}</li>`).join('\n');
document.querySelector('ul').innerHTML = template;
}
addWords();
let btnAdd = document.querySelector('button');
let input = document.querySelector('input');
btnAdd.addEventListener('click', () => {
words.push(input.value);
input.value = '';
addWords();
});
let findLong = document.querySelector('button');
findLong.addEventListener('click', () => {
let longestCt = 0;
let longestWord = "";
words.forEach(function (value) {
if (value.length > longestCt) {
longestWord = value;
longestCt = value.length;
} else {
longestWord = longestWord;
}
});
//}
});
document.getElementById("demo2").innerHTML = longestWord;
div {
widows: 20%;
margin: auto;
}
input, button {
padding: 5px;
display: inline-block;
}
li {
font-size: 20px;
font-weight: bold;
margin-left: -40px;
list-style: none;
}
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="test_Arr_Input.css">
<title>Test Longest Array.html</title>
</head>
<body>
<!--Thank you to YouTube KodeBase with my modifications adding a second button which isn't working-->
<div>
<input type="text">
<button>Add a Word</button>
<ul></ul>
<br>
<button>Find the Longest</button>
<p id="demo"></p>
</div>
<script type="text/javascript" src="test_Arr_Input.js"></script>
</body>
</html>
Full disclosure; Beginner. With that said; thank you in advance.
I have written a simple JavaScript to return the longest string in an array.
Here it is as simply a JavaScript function, that I ran from the console, without interacting with the html:
var myList = ['Loops','are','used','while','Learning JavaScript'];
var longestCt = 0;
var longestWord = "";
myList.forEach(function (value) {
if (value.length > longestCt) {
longestWord = value; longestCt = value.length;
} else {
longestWord = longestWord;
}
});
console.log(longestWord);
I then endeavored to create an HTML page to enter objects into the array and to create a list.
(Thanks to KodeBase from Youtube for the direction). The JavaScript for this is posted at the end after the CSS. Here is the HTML:
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="test_Arr_Input.css">
<title>Test Longest Array.html</title>
</head>
<body>
<!--Thank you to YouTube KodeBase with my modifications adding a second button which isn't working-->
<div>
<input type="text">
<button>Add a Word</button>
<ul></ul>
<br>
<button>Find the Longest</button>
<p id="demo"></p>
</div>
<button onclick="intoMyList()">Submit to the array</button>
<p id="demo"></p>
<button onclick="findTheLongest()">Find the Longest Word</button>
<p id="demo2"></p>
<script type="text/javascript" src="test_Arr_Input.js"></script>
</body>
</html>
Here is the CSS:
div {
widows: 20%;
margin: auto;
}
input, button {
padding: 5px;
display: inline-block;
}
li {
font-size: 20px;
font-weight: bold;
margin-left: -40px;
list-style: none;
}
And here is the final JavaScript:
let words = [];
function addWords() {
let template = words.map(word => `<li>${word}</li>`).join('\n');
document.querySelector('ul').innerHTML = template;
}
addWords();
let btnAdd = document.querySelector('button');
let input = document.querySelector('input');
btnAdd.addEventListener('click', () => {
words.push(input.value);
input.value = '';
addWords();
});
let findLong = document.querySelector('button');
findLong.addEventListener('click', () => {
//function findTheLongest() {
let longestCt = 0;
let longestWord = "";
myList.forEach(function (value) {
if (value.length > longestCt) {
longestWord = value;
longestCt = value.length;
} else {
longestWord = longestWord;
}
});
//}
});
document.getElementById("demo2").innerHTML = longestWord;
First I changed a few variable names for more clarity.
But the issue is, although I am able to get the words to enter the array by clicking the first button, the second button does not seem to call the ForEach function to trigger the return of the longest word. I am wondering if I need to somehow differentiate between button 1 and 2 in the HTML. Or if I just need to go back to the drawing board to rethink my understanding of the way I am putting the JS together.
In short, you need to give each of your buttons a unique ID and then you can use this Id to target the appropriate button in your code.
<button id="add-word">Add a Word</button>
and
let btnAdd = document.querySelector('#add-word');
As mentioned by Jamiec you should give each button its own unique id and use getElementById to target it specifically with that or you can use onclick="function()" in the html to call a function from that element directly
The current point of failure also seems to be line 27 reads myList.forEach when it should be words.ForEach. I've changed a few lines and got a working example here for you: https://jsfiddle.net/z7dsabLc/6/
Learning JS, trying to get this little survey to work, but I get a "function not defined" error at HTML element onclick. Can't figure out why, it seems like the function is defined and I can't find any syntax errors. I also get an error saying that "soda is not defined," but it seems like that variable is defined as an object in the array.
<html>
<body>
<h3>What cats are in the room?</h3>
Sophie: <input type="checkbox" id="sophieCheck">
<br></br>
Soda: <input type="checkbox" id="sodaCheck">
<br></br>
Mr.: <input type="checkbox" id="mrCheck">
<br></br>
<button onclick="catsInTheRoom()">Try it</button>
<br></br>
<p id="cats"></p>
<script>
function catsInTheRoom() {
var myCats = [ soda, mr, sophie ];
if (getElementById("sodaCheck").checked) {
myCats[0] = 1;
} else {
myCats[0] = 0;
}
if (getElementById("sophieCheck").checked) {
myCats[2] = 10;
} else {
myCats[2] = 0;
}
if (getElementById("mrCheck").checked) {
myCats[1] = 20;
} else {
myCats[1] = 0;
}
getElementById("cats").innerHTML = myCats[0] + myCats[1] + myCats[2];
}
</script>
</body>
</html>
I created the array so I can use the numerical values for a switch statement to produce different text based on which checkboxes are checked.
This simpler version worked:
Sophie: <input type="checkbox" id="sohpieCheck">
<br></br>
Soda: <input type="checkbox" id="sodaCheck">
<br></br>
Mr.: <input type="checkbox" id="mrCheck">
<br></br>
<button onclick="myFunction()">Try it</button>
<p id="cats"></p>
<script>
function myFunction() {
var soda = document.getElementById("sodaCheck").checked;
if (soda) {
catBehavior = "Cats are being rascals.";
} else {
catBehavior = "Cats are behaving nicely.";
}
document.getElementById("cats").innerHTML = catBehavior;
}
</script>
Why does the second example work, but not the first one?
script error: soda, mr, sophie are used as variables but are never defined before .. throws error and stops function execution.
var myCats = [ 0, 0, 0 ]; // will initialize myCats to 0,0,0
or you can defined variables first:
var soda = 0, mr = 0, sophie = 0;
bunt since you never use them after initial myCats definition, initializing to 0s should enough
Your code has some errors. Please, check the fixes:
<br> tags are self closed.
soda, mr and sophie must be strings.
getElementById belongs to the document object (or any other DOM node).
<h3>What cats are in the room?</h3>
Sophie: <input type="checkbox" id="sophieCheck">
<br>
Soda: <input type="checkbox" id="sodaCheck">
<br>
Mr.: <input type="checkbox" id="mrCheck">
<br>
<button onclick="catsInTheRoom()">Try it</button>
<br>
<p id="cats"></p>
<script>
function catsInTheRoom() {
var myCats = [ 'soda', 'mr', 'sophie' ];
if (document.getElementById("sodaCheck").checked) {
myCats[0] = 1;
} else {
myCats[0] = 0;
}
if (document.getElementById("sophieCheck").checked) {
myCats[2] = 10;
} else {
myCats[2] = 0;
}
if (document.getElementById("mrCheck").checked) {
myCats[1] = 20;
} else {
myCats[1] = 0;
}
document.getElementById("cats").innerHTML = myCats[0] + myCats[1] + myCats[2];
}
</script>
the line 'var myCats = [ soda, mr, sophie ];' is the cause of the error. You are using strings as variables. If you must use those strings, then create an object with those properties and initialize the values as follows;
var myCats ={soda=0, mr=0, sophie=0};
if (getElementById("sodaCheck").checked) {
myCats.soda = 1;
} else {
myCats.soda = 0;
}
if (getElementById("sophieCheck").checked) {
myCats.sophie= 10;
} else {
myCats.sophie = 0;
}
if (getElementById("mrCheck").checked) {
myCats.mr = 20;
} else {
myCats.mr = 0;
}
getElementById("cats").innerHTML = myCats.soda + myCats.mr + myCats.sophie;
}
function newCheckbox(){
var aLabel = document.form1.getElementsByTagName('label');
var last = aLabel[aLabel.length-1];
var label = document.createElement('label');
label.appendChild(Box(aLabel.length));
label.appendChild(document.createTextNode(' '+document.getElementById('text').value));
last.parentNode.insertBefore(label, last);
document.getElementById('text').value = '';
}
function Box(num){
var elm = null;
try {
elm=document.createElement('<input type="checkbox" id="chk'+num+'">');
}
catch(e) {
elm = document.createElement('input');
elm.setAttribute('type', 'checkbox');
elm.id='chk'+num;
}
return elm;
}
function delBoxes(){
var texts = document.form1.getElementsByTagName('label');
for(var i = 0; i<texts.length-1; i++){
var chbox=Box[i];
txt = texts[i];
if(chbox.checked){
chbox.parentNode.removeChild(chbox);
txt.parentNode.removeChild(txt);
}
}
}
form{
color:blue;
font-weight:bold;
margin:100 0 0 50;
font-weight:bold;
margin-left:120;
padding:100;
}
label{
display:block;
}
input{
color:blue;
background-color:pink;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form action="#" name="form1">
<div>
<label>Checkbox text:<input type="text" id="text"></label>
<input type="button" onclick="newCheckbox();"value="add">
<input type="button" value="Delete" onclick = "delBoxes();"/>
</div>
</form>
</body>
</html>
I want to have a dynamic page that allows a user to add checkboxes to the page. Checkbox content is the input in the textbox.
When the user pushes the “add”-button checkboxes are created and shown. The user must have the ability to remove checkboxes by marking them. The code can add a new checkbox to the form but the deleting function does not work.
It seems that chbox is not created and the if-statement does nothing in the function delBoxes.
Any suggestions?
Replace the whole script you have with this :
function newCheckbox() {
var aLabel = document.form1.getElementsByTagName('label');
var last = aLabel[aLabel.length-1];
var label = document.createElement('label');
label.appendChild(Box(aLabel.length));
label.appendChild(document.createTextNode(' '+document.getElementById('text').value));
last.parentNode.insertBefore(label, last);
document.getElementById('text').value = '';
}
function Box(num) {
var elm = null;
try {
elm=document.createElement('<input type="checkbox" class="chk">');
}
catch(e) {
elm = document.createElement('input');
elm.setAttribute('type', 'checkbox');
elm.className='chk';
}
return elm;
}
function delBoxes(){
var texts = document.form1.getElementsByTagName('label');
var chbox = document.form1.getElementsByClassName('chk');
for(var i = 0; i<texts.length-1; i++){
if(chbox[i].checked){
chbox[i].parentNode.removeChild(chbox[i]);
texts[i].parentNode.removeChild(texts[i]);
}
}
}
Assume I have a page with an input box. The user types something into the input box and hits a button. The button triggers a function that picks up the value typed into the text box and outputs it onto the page beneath the text box for whatever reason.
Now this has been disturbingly difficult to find a definitive answer on or I wouldn't be asking but how would you go about outputting this string:
<script>alert("hello")</script> <h1> Hello World </h1>
So that neither the script is executed nor the HTML element is displayed?
What I'm really asking here is if there is a standard method of avoiding both HTML and Script injection in Javascript. Everyone seems to have a different way of doing it (I'm using jQuery so I know I can simply output the string to the text element rather than the html element for instance, that's not the point though).
You can encode the < and > to their HTML equivelant.
html = html.replace(/</g, "<").replace(/>/g, ">");
How to display HTML tags as plain text
myDiv.textContent = arbitraryHtmlString
as #Dan pointed out, do not use innerHTML, even in nodes you don't append to the document because deffered callbacks and scripts are always executed. You can check this https://gomakethings.com/preventing-cross-site-scripting-attacks-when-using-innerhtml-in-vanilla-javascript/ for more info.
A one-liner:
var encodedMsg = $('<div />').text(message).html();
See it work:
https://jsfiddle.net/TimothyKanski/wnt8o12j/
I use this function htmlentities($string):
$msg = "<script>alert("hello")</script> <h1> Hello World </h1>"
$msg = htmlentities($msg);
echo $msg;
From here
var string="<script>...</script>";
string=encodeURIComponent(string); // %3Cscript%3E...%3C/script%3
My solution using typescript + decorators + regex
const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
function filter(target) {
return class extends target {
constructor(...args) {
super(...args);
}
setState(opts) {
const state = {
username: this.filter(opts.username),
password: this.filter(opts.password),
};
super.setState(state);
}
filter(value) {
const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");
}
};
}
let Form = class Form {
constructor() {
this.state = {
username: "",
password: "",
};
}
setState(opts) {
this.state = {
...this.state,
...opts,
};
}
getState() {
return this.state;
}
};
Form = __decorate([
filter,
__metadata("design:paramtypes", [])
], Form);
function getElement(key) {
return document.getElementById(key);
}
const button = getElement("btn");
const username = getElement("username");
const password = getElement("password");
const usernameOutput = getElement("username-output");
const passwordOutput = getElement("password-output");
function handleClick() {
const form = new Form();
form.setState({ username: username.value, password: password.value });
usernameOutput.innerHTML = `Username: ${form.getState().username}`;
passwordOutput.innerHTML = `Password: ${form.getState().password}`;
}
button.onclick = handleClick;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
:root {
--bg: #1d1907;
--foreground: #e3e0cd;
--primary: #cfb53b;
--black: #333;
--white: #fafafa;
}
#keyframes borderColor {
from {
border-bottom: 1px solid var(--foreground);
}
to {
border-bottom: 1px solid var(--primary);
}
}
* {
outline: none;
border: none;
}
body {
padding: 0.5rem;
font-family: "Fira Code";
background-color: var(--bg);
color: var(--foreground);
}
input {
border-bottom: 1px solid var(--foreground);
background-color: var(--black);
color: var(--foreground);
padding: 0.5rem;
}
input:focus {
animation-name: borderColor;
animation-duration: 3s;
animation-fill-mode: forwards;
}
button {
padding: 0.5rem;
border-radius: 3px;
border: 1px solid var(--primary);
background-color: var(--primary);
color: var(--white);
}
button:hover,
button:active {
background-color: var(--white);
color: var(--primary);
}
.form {
margin-bottom: 2rem;
}
</style>
<title>Decorator</title>
</head>
<body>
<h1>Prevent Injection</h1>
<div class="form">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" placeholder="Type your username" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" placeholder="Type your password" />
</div>
<div class="form-group">
<button id="btn">Enviar</button>
</div>
</div>
<div class="form-result">
<p id="username-output">Username:</p>
<p id="password-output">Password:</p>
</div>
<script src="/dist/pratica1.js"></script>
</body>
</html>
Typescript Code bellow:
type State = {
username: string;
password: string;
};
function filter<T extends new (...args: any[]) => any>(target: T): T {
return class extends target {
constructor(...args: any[]) {
super(...args);
}
setState(opts: State) {
const state = {
username: this.filter(opts.username),
password: this.filter(opts.password),
};
super.setState(state);
}
filter(value: string) {
const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");
}
};
}
#filter
class Form {
private state: State;
constructor() {
this.state = {
username: "",
password: "",
};
}
setState(opts: State) {
this.state = {
...this.state,
...opts,
};
}
getState() {
return this.state;
}
}
function getElement(key: string): HTMLElement | null {
return document.getElementById(key);
}
const button = getElement("btn") as HTMLButtonElement;
const username = getElement("username") as HTMLInputElement;
const password = getElement("password") as HTMLInputElement;
const usernameOutput = getElement("username-output") as HTMLParagraphElement;
const passwordOutput = getElement("password-output") as HTMLParagraphElement;
function handleClick() {
const form = new Form();
form.setState({ username: username.value, password: password.value });
usernameOutput.innerHTML = `Username: ${form.getState().username}`;
passwordOutput.innerHTML = `Password: ${form.getState().password}`;
}
button.onclick = handleClick;
Try this method to convert a 'string that could potentially contain html code' to 'text format':
$msg = "<div></div>";
$safe_msg = htmlspecialchars($msg, ENT_QUOTES);
echo $safe_msg;
Hope this helps!
Use this,
function restrict(elem){
var tf = _(elem);
var rx = new RegExp;
if(elem == "email"){
rx = /[ '"]/gi;
}else if(elem == "search" || elem == "comment"){
rx = /[^a-z 0-9.,?]/gi;
}else{
rx = /[^a-z0-9]/gi;
}
tf.value = tf.value.replace(rx , "" );
}
On the backend, for java , Try using StringUtils class or a custom script.
public static String HTMLEncode(String aTagFragment) {
final StringBuffer result = new StringBuffer();
final StringCharacterIterator iterator = new
StringCharacterIterator(aTagFragment);
char character = iterator.current();
while (character != StringCharacterIterator.DONE )
{
if (character == '<')
result.append("<");
else if (character == '>')
result.append(">");
else if (character == '\"')
result.append(""");
else if (character == '\'')
result.append("'");
else if (character == '\\')
result.append("\");
else if (character == '&')
result.append("&");
else {
//the char is not a special one
//add it to the result as is
result.append(character);
}
character = iterator.next();
}
return result.toString();
}