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();
}
Related
I have a form where I check the password strength of a user. It works correctly and shows the text according to the validation. But when a user makes a mistake and uses backspace to re-enter his password, the text from data-text isn't show anymore because the content property from the CSS is being removed (I guess because of the backspace). I couldn't find a solution to prevent it from being removed.
// Password field
self.addEventListener("keyup", () => {
let val = self.value;
testPasswordStrength(val);
});
// check password strength
const testPasswordStrength = (value) => {
const strengthText = document.getElementsByClassName('js-password-strength')[0];
const strongRegex = new RegExp(
'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[=/\()%ยง!##$%^&*])(?=.{8,})'
),
mediumRegex = new RegExp(
'^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})'
);
if (value) {
if (strongRegex.test(value)) {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textStrong);
return "strong";
} else if (mediumRegex.test(value)) {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textGood);
return "medium";
} else {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textDefault);
return "weak";
}
} else {
strengthText.classList.add("d-none");
}
};
content: attr(data-validation-text);
<div class="js-password-strength" data-validation-text data-text-default="Password must be 8+ characters" data-text-good="Good password" data-text-strong="Great password">
</div>
Is this work for you
// Password field
const passwordField = document.getElementsByClassName('js-password-strength')[0];
passwordField.addEventListener("keyup", () => {
let val = passwordField.textContent;
testPasswordStrength(val);
});
// check password strength
const testPasswordStrength = (value) => {
;
const strongRegex = new RegExp(
'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[=/\()%ยง!##$%^&*])(?=.{8,})'
),
mediumRegex = new RegExp(
'^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})'
);
if (value) {
if (strongRegex.test(value)) {
passwordField.setAttribute('data-validation-text', passwordField.dataset.textStrong);
return "strong";
} else if (mediumRegex.test(value)) {
passwordField.setAttribute('data-validation-text', passwordField.dataset.textGood);
return "medium";
} else {
passwordField.setAttribute('data-validation-text', passwordField.dataset.textDefault);
return "weak";
}
} else {
passwordField.classList.add("d-none");
}
};
.js-password-strength{
border:1px solid #000;
}
.js-password-strength:after{
content: attr(data-validation-text);
font-size:12px;
color:#666;
}
<html>
<head>
</head>
<body>
<div class="js-password-strength"
data-validation-text
data-text-default="Password must be 8+ characters"
data-text-good="Good password"
data-text-strong="Great password" contenteditable=true>
</div>
</body>
<html>
#AndrewL64 I found the issue strengthText.classList.add("d-none"); It makes it display none. So it removes the content property. So if the value is set. It should have display: block
if (value) {
strengthText.classList.remove("d-none");
strengthText.classList.add("d-block");
if (strongRegex.test(value)) {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textStrong);
return "strong";
} else if (mediumRegex.test(value)) {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textGood);
return "medium";
} else {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textDefault);
return "weak";
}
} else {
strengthText.classList.remove("d-block");
strengthText.classList.add("d-none");
}
I'm making a basic calculator and so far it "works". Users can only enter in a single digit from their keyboard. If they want to use double digits they're going to have to use the arrows in the text box. How can I make it so that users can enter in double digit numbers? If the user tries to type in double digit numbers the second number only get stored (so typing in 25 will only store 5)
// Base Variables
let result = 0;
let numb1 = 0;
let numb2 = 0;
let firstNumberEntered = false;
//This will be rewritten
let calculationDescription = `${numb1} + ${numb2}`;
document.querySelector('#input-number').addEventListener('keypress', numbersInput);
function numbersInput(e) {
if (!firstNumberEntered && e.key === 'Enter') {
numb1 = document.getElementById("input-number").value;
firstNumberEntered = true;
document.getElementById("input-number").innerHTML = "";
} else if (firstNumberEntered && e.key === 'Enter') {
numb2 = document.getElementById("input-number").value;
firstNumberEntered = false;
console.log(`${numb1} and ${numb2}`);
}
document.getElementById("input-number").value = "";
}
document.querySelector("#btn-add").addEventListener('click', sumNumbs);
document.querySelector("#btn-subtract").addEventListener('click', subtractNumbs);
document.querySelector("#btn-multiply").addEventListener('click', multiplyNumbs);
document.querySelector("#btn-divide").addEventListener('click', divideNumbs);
function sumNumbs() {
let numb1Final = parseInt(numb1);
let numb2Final = parseInt(numb2);
result = numb1Final + numb2Final;
calculationDescription = `${numb1} + ${numb2}`;
outputResult(result, calculationDescription);
}
function subtractNumbs() {
let numb1Final = parseInt(numb1);
let numb2Final = parseInt(numb2);
result = numb1Final - numb2Final;
calculationDescription = `${numb1} - ${numb2}`;
outputResult(result, calculationDescription);
}
function multiplyNumbs() {
let numb1Final = parseInt(numb1);
let numb2Final = parseInt(numb2);
result = numb1Final * numb2Final;
calculationDescription = `${numb1} x ${numb2}`;
outputResult(result, calculationDescription);
}
function divideNumbs() {
let numb1Final = parseInt(numb1);
let numb2Final = parseInt(numb2);
result = numb1Final / numb2Final;
calculationDescription = `${numb1} / ${numb2}`;
outputResult(result, calculationDescription);
}
<section id="calculator">
<input type="number" id="input-number" />
<div id="calc-actions">
<button type="button" id="btn-add">+</button>
<button type="button" id="btn-subtract">-</button>
<button type="button" id="btn-multiply">*</button>
<button type="button" id="btn-divide">/</button>
</div>
</section>
All this does is grab the elements on the HTML page and put them into variables and send info back to be displayed
const userInput = document.getElementById('input-number');
const addBtn = document.getElementById('btn-add');
const subtractBtn = document.getElementById('btn-subtract');
const multiplyBtn = document.getElementById('btn-multiply');
const divideBtn = document.getElementById('btn-divide');
const currentResultOutput = document.getElementById('current-result');
const currentCalculationOutput = document.getElementById('current-calculation');
function outputResult(result, text) {
currentResultOutput.textContent = result;
currentCalculationOutput.textContent = text;
}
Not sure if providing my CSS is necessary, but let me know and I'll make a change.
I just started learning JavaScript recently. I watched a few videos on a Udemy tutorial on doing this project, but I stopped watching and tried to figure the rest out myself.
What I did try doing was adding maxlength="6" to my HTML input element, but that didn't work.
function numbersInput(e) {
if(!firstNumberEntered && e.key === 'Enter') {
numb1 = document.getElementById("input-number").value;
firstNumberEntered = true;
document.getElementById("input-number").innerHTML = "";
document.getElementById("input-number").value = "";
}
else if(firstNumberEntered && e.key === 'Enter') {
numb2 = document.getElementById("input-number").value;
firstNumberEntered = false;
console.log(`${numb1} and ${numb2}`);
document.getElementById("input-number").value = "";
}
}
Add document.getElementById("input-number").value = "";
to the end of both if statements and remove from the end of the function
Here's my own basic calculator using HTML, CSS, and javascript only.
To be able to input one or more digit numbers, use arrays to function as storage of those numbers chosen and for your chosen arithmetic operation as well.
please see my source code for a clearer grasp of my idea.
//index.html
<!DOCTYPE html>
<html>
<head>
<title>My HTML/CSS/JS Calculator</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div class="outer-container">
<div class="items" id="items"></div>
<div class="calc-screen">
<div id="screen"></div>
</div>
<div class="keys-container">
<button type="button" class="keys" id="opm" onclick="opm()">*</button>
<button type="button" class="keys" id="opd" onclick="opd()">/</button>
<button type="button" class="keys" id="opa" onclick="opa()">+</button>
<button type="button" class="keys" id="ops" onclick="ops()">-</button>
<button type="button" class="keys" id="num9" onclick="num9()">9</button>
<button type="button" class="keys" id="num8" onclick="num8()">8</button>
<button type="button" class="keys" id="num7" onclick="num7()">7</button>
<button type="button" class="keys" id="num6" onclick="num6()">6</button>
<button type="button" class="keys" id="num5" onclick="num5()">5</button>
<button type="button" class="keys" id="num4" onclick="num4()">4</button>
<button type="button" class="keys" id="num3" onclick="num3()">3</button>
<button type="button" class="keys" id="num2" onclick="num2()">2</button>
<button type="button" class="keys" id="num1" onclick="num1()">1</button>
<button type="button" class="keys" id="num0" onclick="num0()">0</button>
<button type="button" class="keys" id="del" onclick="del()">Del</button>
<button type="button" class="keys" id="clr" onclick="clr()">Clr</button>
<button type="submit" class="keys" id="equals" onclick='equals()'>=</button>
</div>
</div>
<script type="text/javascript" src="js/js.js"></script>
</body>
</html>
//js.js
var item1, op, item2, arr1, arr2, text, x, prod, qout, sum, diff, a, b, c;
item1, item2, op = '';
arr1 = [];
arr2 = [];
function num9() {
if (op=='') {
arr1.push(document.getElementById("num9").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num9").innerHTML);
arr2Function();
}
}
function num8() {
if (op=='') {
arr1.push(document.getElementById("num8").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num8").innerHTML);
arr2Function();
}
}
function num7() {
if (op=='') {
arr1.push(document.getElementById("num7").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num7").innerHTML);
arr2Function();
}
}
function num6() {
if (op=='') {
arr1.push(document.getElementById("num6").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num6").innerHTML);
arr2Function();
}
}
function num5() {
if (op=='') {
arr1.push(document.getElementById("num5").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num5").innerHTML);
arr2Function();
}
}
function num4() {
if (op=='') {
arr1.push(document.getElementById("num4").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num4").innerHTML);
arr2Function();
}
}
function num3() {
if (op=='') {
arr1.push(document.getElementById("num3").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num3").innerHTML);
arr2Function();
}
}
function num2() {
if (op=='') {
arr1.push(document.getElementById("num2").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num2").innerHTML);
arr2Function();
}
}
function num1() {
if (op=='') {
arr1.push(document.getElementById("num1").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num1").innerHTML);
arr2Function();
}
}
function num0() {
if (op=='') {
arr1.push(document.getElementById("num0").innerHTML);
arr1Function();
}
else {
arr2.push(document.getElementById("num0").innerHTML);
arr2Function();
}
}
function opm() {
if (arr1=='') {
document.getElementById("screen").innerHTML = "Please press a number first!";
}
else if (op!='' && arr2!='') {
console.log("press equal sign");
}
else {
document.getElementById("screen").innerHTML = document.getElementById("opm").innerHTML;
op = '*';
console.log(op);
}
}
function opd() {
if (arr1=='') {
document.getElementById("screen").innerHTML = "Please press a number first!";
}
else if (op!='' && arr2!='') {
console.log("press equal sign");
}
else {
document.getElementById("screen").innerHTML = document.getElementById("opd").innerHTML;
op = '/';
console.log(op);
}
}
function opa() {
if (arr1=='') {
document.getElementById("screen").innerHTML = "Please press a number first!";
}
else if (op!='' && arr2!='') {
console.log("press equal sign");
}
else {
document.getElementById("screen").innerHTML = document.getElementById("opa").innerHTML;
op = '+';
console.log(op);
}
}
function ops() {
if (arr1=='') {
document.getElementById("screen").innerHTML = "Please press a number first!";
}
else if (op!='' && arr2!='') {
console.log("press equal sign");
}
else {
document.getElementById("screen").innerHTML = document.getElementById("ops").innerHTML;
op = '-';
console.log(op);
}
}
function equals() {
a = parseInt(item1); b = parseInt(item2);
if (op == '*') {
prod = a * b;
document.getElementById("items").innerHTML = a+' '+op+' '+b+' =';
c = prod;
document.getElementById("screen").innerHTML = c;
console.log('product: '+c);
result(c);
}
else if (op == '/') {
qout = a / b;
document.getElementById("items").innerHTML = a+' '+op+' '+b+' =';
c = qout;
document.getElementById("screen").innerHTML = c;
console.log('qoutient: '+c);
result(c);
}
else if (op == '+') {
sum = a + b;
document.getElementById("items").innerHTML = a+' '+op+' '+b+' =';
c = sum;
document.getElementById("screen").innerHTML = c;
console.log('sum: '+c);
result(c);
}
else if (op == '-') {
diff = a - b;
document.getElementById("items").innerHTML = a+' '+op+' '+b+ ' =';
c = diff;
document.getElementById("screen").innerHTML = c;
console.log('difference: '+c);
result(c);
}
else {
document.getElementById("screen").innerHTML = "Please press a number first!";
}
}
function result() {
console.log('function result: '+c);
arr1=[]; arr2=[]; item1, item2, op = '';
item1 = c;
console.log('function result new item1: '+item1);
arr1.push(item1);
arr1Function();
}
function del() {
if (arr1!='' && op=='' && arr2=='') {
arr1.pop();
console.log(arr1);
arr1Function();
}
else if (arr1!='' && op!='' && arr2=='') {
op = '';
document.getElementById("screen").innerHTML = op;
}
else if (arr1!='' && op!='' && arr2!='') {
arr2.pop();
console.log(arr2);
arr2Function();
}
}
function clr() {
arr1=[]; arr2=[]; item1,item2,op='';
console.log(arr1+', '+op+', '+arr2+', '+item1+', '+item2);
document.getElementById("screen").innerHTML = '';
document.getElementById("items").innerHTML = '';
}
function arr1Function() {
document.getElementById("screen").innerHTML = arr1;
text = ""; arr1.forEach(myFunction); text += "";
function myFunction(value) {
text += value;
x = parseInt(text);
document.getElementById("screen").innerHTML = x;
item1 = x;
console.log("Arr 1 Parse: "+x);
console.log("Arr 1: "+arr1);
console.log("Item 1: "+item1);
}
}
function arr2Function() {
document.getElementById("screen").innerHTML = arr2;
text = ""; arr2.forEach(myFunction); text += "";
function myFunction(value) {
text += value;
x = parseInt(text);
document.getElementById("screen").innerHTML = x;
item2 = x;
console.log("Arr 2 Parse: "+x);
console.log("Arr 2: "+arr2);
console.log("Item 2: "+item2);
}
}
//css
body {
background-color: orange;
}
.outer-container {
position: static;
background-color: black;
margin: auto;
border: solid black 2px;
width: 350px;
padding: 20px;
box-sizing: border-box;
border-radius: 20px;
}
.items {
background-color: silver;
border: solid white 1px;
display: inline-block;
color: black;
max-width: 100%;
font-size: 16px;
height: 20px;
box-sizing: border-box;
}
.calc-screen {
padding: 10px;
border: solid white 1px;
max-width: 100%;
width: 100%;
height: 50px;
background-color: silver;
color: white;
font-size: 25px;
box-sizing: border-box;
overflow-x: auto;
}
.keys-container {
margin-top: 20px;
width: 100%;
border: solid white 1px;
max-width: 100%;
display: inline-block;
}
#equals {
width: 100%;
}
.keys {
float: left;
border: solid black 1px;
box-sizing: border-box;
width: 25%;
height: 40px;
box-sizing: border-box;
text-align: center;
margin: auto;
font-size: 25px;
padding: 5px;
}
.keys:hover {
background-color: blue;
color: white;
}
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" />
First of all, sorry if my question is too silly, I'm still new with Polymer 2.
I'm facing a little issue. I've created a custom component, where I load some dynamic data via xhr.
Everything seems to work correctly, but I've noticed that when I leave and come back to this view, the component has not changed, even if it raises all the xhr to get new data.
I'm wondering if the issue is that the data is updated, but the DOM is still the same.
Is it possible to force the system to "reload" the component each time I visit the page?
Thanks in advance.
It's a custom "tree view component".
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-if.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-repeat.html">
<link rel="import" href="../../bower_components/paper-collapse-item/paper-collapse-item.html">
<link rel="import" href="../../bower_components/vaadin-icons/vaadin-icons.html">
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../bower_components/iron-location/iron-location.html">
<link rel="import" href="../../portal_components/portal-measurement-units/portal-measurement-units.html">
<dom-module id="portal-tree-view">
<template>
<style include="iron-flex iron-flex-alignment">
<style>
:host {
display: block;
}
.icon
{
margin-right: 24px;
--iron-icon-height: 34px;
--iron-icon-width: 34px;
color: var(--disabled-text-color);
}
.icon-small
{
margin-right: 24px;
--iron-icon-height: 20px;
--iron-icon-width: 20px;
color: var(--disabled-text-color);
}
.icon-big
{
margin-right: 24px;
--iron-icon-height: 40px;
--iron-icon-width: 40px;
color: var(--disabled-text-color);
}
.alert {
color: orange;
}
.emergency {
color: red;
}
</style>
<template is="dom-if" if=[[!loading]]>
<template is="dom-repeat" items={{tree}}>
<template is="dom-if" if="[[item.deploy]]">
<paper-collapse-item icon="icons:label" header="[[item.name]]" id="collapseitem" >
<portal-tree-view assets=[[item.children]] tasks=[[tasks]] results=[[results]] network=[[network]]></portal-tree-view>
</paper-collapse-item>
</template>
<template is="dom-if" if="[[item.mp]]">
<span style= "font-size: var(--paper-font-subhead_-_font-size); margin-left: 15px;">
<iron-icon class="icon" icon="label-outline"></iron-icon>
<iron-icon class="icon-big" style="color: black; float: right; margin-top: 40px" icon="vaadin:info-circle-o" on-click="goDetail"></iron-icon>
[[item.name]] <br/>
<span style="margin-left: 96px">
<iron-icon class="icon-small" style="color: [[item.lastacq_status]]" icon="vaadin:spark-line"></iron-icon>
<span style="color: [[checkLastAcqStatus(item)]]">[[getLastAcq(item)]]</span>
</span><br/>
<span style="margin-left: 86px">
Speed: <span style="color: [[checkSpeedStatus(item)]]">[[checkSpeed(item)]] </span>
</span><br/>
<span style="margin-left: 86px">
Acceleration: <span style="color: [[checkAccStatus(item)]]">[[checkAcc(item)]]</span>
</span><br/>
<span style="margin-left: 86px">
Temperature: <span style="color: [[checkTempStatus(item)]]">[[checkTemp(item)]]</item>
</span><br/>
</span><br/>
</template>
<template is="dom-if" if="[[item.transmitter]]">
<span style= "font-size: var(--paper-font-subhead_-_font-size); margin-left: 15px;">
<iron-icon class="icon" icon="label-outline"></iron-icon>
[[item.name]]<br/>
</span>
<span style="margin-left: 96px">
<iron-icon class="icon-small" style="color: [[item.latcom_status]]" icon="settings-input-antenna"></iron-icon>
<span style="color: [[checkLastComStatus(item)]]">[[getLastCom(item)]]</span>
</span><br/>
</template>
<template is="dom-if" if="[[item.endpoint]]">
<span style= "font-size: var(--paper-font-subhead_-_font-size); margin-left: 15px;">
<iron-icon class="icon" icon="label-outline"></iron-icon>
[[item.name]]<br/>
</span>
</template>
</template>
</template>
<template is="dom-if" if=[[loading]]>
<div class="center-center layout horizontal">
<img src="portal_components/portal-tree-view/loading.gif" />
</div>
</template>
<portal-lite-global-variables id="GLOBALS"></portal-lite-global-variables>
<portal-measurement-units id="UNITS"></portal-measurement-units>
<iron-location id="location"></iron-location>
</template>
<script>
/**
* `portal-tree-view`
*
*
* #customElement
* #polymer
* #demo demo/index.html
*/
class portalTreeView extends Polymer.Element {
static get is() { return 'portal-tree-view'; }
static get properties() {
return {
assets: {
type: Array,
notify: true,
},
tasks: {
type: Object,
notify: true,
},
results: {
type: Object,
notify: true,
},
network: {
type: Array,
notify: true
},
tree: {
type: Array,
notify: true
},
trigger: {
type: Boolean,
observer: '_trigger'
}
};
}
static get observers() {
return [
'fullAssets(tasks, results)'
]
}
_trigger()
{
if (this.trigger)
{
this.ready();
console.log("trigger")
this.fullAssets();
}
}
toFixed(value, precision) {
return Number(value).toFixed(precision);
}
goDetail(event)
{
var item = event.model.item;
this.$.location.path="portal-lite-asset-details/"+item._id;
}
checkLastComStatus(item)
{
if (this.network[item.mac] !== undefined)
{
var current = this.$.GLOBALS.getUTCTimeStamp(new Date());
if (current < this.$.GLOBALS.getUTCTimeStamp(new Date(this.network[item.mac].last_com)) + 54000)
return 'orange';
else if (current > this.$.GLOBALS.getUTCTimeStamp(new Date(this.network[item.mac].last_com)) + 54000)
return 'red';
}
}
getLastAcq(item)
{
if (this.results[item._id] !== undefined)
return new Date(this.results[item._id].acqend).toLocaleDateString() + " " + new Date(this.results[item._id].acqend).toLocaleTimeString();
}
getLastCom(item)
{
if (this.network[item.mac] !== undefined)
return new Date(this.network[item.mac].last_com).toLocaleDateString() + " " + new Date(this.network[item.mac].last_com).toLocaleTimeString();
}
checkLastAcqStatus(item)
{
if (this.tasks[item._id] !== undefined)
return this.$.GLOBALS.checkTask(this.tasks[item._id], this.results[item._id]);
}
checkSpeed(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.vib !== undefined &&
this.results[item._id].globals.vib.v !== undefined)
{
var aux = this.$.UNITS.speed(this.results[item._id].globals.vib.v[0]);
return aux.value.toFixed(2) + " " + aux.desc;
}
}
}
checkSpeedStatus(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.vib !== undefined &&
this.results[item._id].globals.vib.v !== undefined)
{
if (this.results[item._id].globals.vib.v[1] == 1) return "orange";
else if (this.results[item._id].globals.vib.v[1] == 2) return "red";
}
}
}
checkAccStatus(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.vib !== undefined &&
this.results[item._id].globals.vib.a !== undefined)
{
if (this.results[item._id].globals.vib.a[1] == 1) return "orange";
else if (this.results[item._id].globals.vib.a[1] == 2) return "red";
}
}
}
checkTempStatus(item)
{
if (this.results[item._id] !== undefined)
if (this.results[item._id].globals.temp !== undefined &&
this.results[item._id].globals.temp !== null)
{
if (this.results[item._id].globals.temp[1] == 1) return "orange";
else if (this.results[item._id].globals.temp[1] == 2) return "red";
}
}
checkAcc(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.vib !== undefined &&
this.results[item._id].globals.vib.a !== undefined)
{
var aux = this.$.UNITS.g(this.results[item._id].globals.vib.a[0]);
return aux.value.toFixed(2) + " " + aux.desc;
}
}
}
checkTemp(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.temp !== undefined &&
this.results[item._id].globals.temp !== null)
{
var aux = this.$.UNITS.temp(this.results[item._id].globals.temp[0]);
return aux.value.toFixed(1) + " " + aux.desc;
}
}
}
fullAssets()
{
if (this.assets !== undefined && this.network !== undefined)
{
this.loading = false;
this.assets.sort(function(d1,d2)
{
if (d1.children.length > 0) return -1;
return 1;
});
for (var i = 0; i < this.assets.length; i++)
{
this.assets[i].endpoint = false;
this.assets[i].mp = false;
this.assets[i].transmitter = false;
if (this.assets[i].children.length === 0)
this.assets[i].endpoint = true;
if (this.assets[i].t == 33554435)
{
this.assets[i].endpoint = false;
this.assets[i].transmitter = true;
this.assets[i].mac = this.assets[i].optionals.mac.toUpperCase();
}
if (this.assets[i].t == 16777218)
{
this.assets[i].endpoint = false;
this.assets[i].mp = true
}
this.assets[i].deploy = !this.assets[i].mp && !this.assets[i].endpoint && !this.assets[i].transmitter;
}
this.notifyPath('tree', this.assets);
}
}
constructor()
{
super();
this.loading = true;
this.queue_results = 0;
}
ready()
{
super.ready();
}
}
window.customElements.define(portalTreeView.is, portalTreeView);
</script>
</dom-module>
On this.$.UNITS I have a set of functions to make a conversion of values (Metric, Imperial, etc...).
The function checkSpeed(item) is executed each time I show the view.
Via console.log I can check that the value returned is always correct, but when leaving, I change the unity (from metric to imperial, for instance), and when I'm back again the view in the component remains in the old unities (even if the console.log in the function returns the correct value).
Hope it's useful.
Thanks in advance.
[EDIT]
Finally found out the solution here: https://easyusedev.wordpress.com/2015/11/06/dynamically-loading-polymer-elements-on-the-fly/
In order to be sure that the component is refresed each time I call the view, create the component manually when everything's ready to load the component:
var tree = document.createElement('portal-tree-view');
And, when leaving, I remove it:
var element = this.$.container.querySelector("portal-tree-view");
element.parentNode.removeChild(element)
En cualquier caso, muchas gracias por tu tiempo Álvaro.
Best regards.
I see you are doing this.notifyPath('tree', this.assets); in fullAssets(), but I think the syntax is not correct.
From the docs:
When calling notifyPath, you need to use the exact path that changed.
For example, calling this.notifyPath('profile') doesn't pick up a
change to profile.name because the profile object itself hasn't
changed.
So try to do this:
this.notifyPath('tree.property_you_want_to_be_changed');
Or maybe would be better to you to use MutableData mixin. This mixin allows the array to be updated and the UI be notified simpley doing
this.notifyPath('tree');
I'm completely new nopCommerce. One of my client is getting error during check out with VISA card. He is getting the following screen. I'm not sure where do I start to troubleshoot. Can you please help me? Some how I'm not able to post exact HTML document. But please consider below code as properly formatted HTML.
<script type="text/javascript">
(function (f, b) {
if (!b.__SV) {
var a, e, i, g;
window.mixpanel = b;
b._i = [];
b.init = function (a, e, d) {
function f(b, h) {
var a = h.split(".");
2 == a.length && (b = b[a[0]], h = a[1]);
b[h] = function () {
b.push([h].concat(Array.prototype.slice.call(arguments, 0)))
}
}
var c = b;
"undefined" !== typeof d ? c = b[d] = [] : d = "mixpanel";
c.people = c.people || [];
c.toString = function (b) {
var a = "mixpanel";
"mixpanel" !== d && (a += "." + d);
b || (a += " (stub)");
return a
};
c.people.toString = function () {
return c.toString(1) + ".people (stub)"
};
i = "disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");
for (g = 0; g < i.length; g++) f(c, i[g]);
b._i.push([a, e, d])
};
b.__SV = 1.2;
a = f.createElement("script");
a.type = "text/javascript";
a.async = !0;
a.src = "//cdn.mxpnl.com/libs/mixpanel-2.2.min.js";
e = f.getElementsByTagName("script")[0];
e.parentNode.insertBefore(a, e)
}
})(document, window.mixpanel || []);
var mode = 'prd'.toLowerCase();
var token = '';
if (mode == 'demo') {
token = 'xxxxxxxxxxxxxxxxxxxxxx';
} else if (mode == 'prd' || mode == 'prda' || mode == 'prdk') {
token = 'xxxxxxxxxxxxxxxxxxxxxx';
} else if (mode == 'test') {
token = 'xxxxxxxxxxxxxxxxxxx';
} else {
token = 'xxxxxxxxxxxxxxxxxxxxxxxxx';
}
if (token != '') {
mixpanel.init(token, {
persistence: 'localStorage'
});
}
</script><!-- end Mixpanel -->
<script type="text/javascript">
if (self !== top && typeof mixpanel !== "undefined") {
mixpanel.track("inFrame", {
"merchant_id": "XXXX(actual number here)",
"tid": "XXXX(actual number here)"
});
}
</script>
<style type="text/css">
BODY, TD, INPUT, SELECT, TEXTAREA, BUTTON, .normal {
font-family: arial,helvetica,sans-serif;
font-size: 10pt;
font-weight: normal;
}
.small {
font-size: 10pt;
}
.medium {
font-size: 14pt;
}
.large {
font-size: 18pt;
}
</style>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- process-transaction-response -->
<html>
<head>
<meta http-equiv="refresh" content="1;url=http://www.myvirtualmerchant.com?
ssl_approval_code=++++++&
ssl_cvv2_response=&
ssl_exp_date=XXXX(actual number here)&
ssl_account_balance=0.00&
ssl_get_token=&
ssl_token=&
ssl_departure_date=&
ssl_token_response=&
ssl_result_message=DECLINED&
ssl_invoice_number=XXXX(actual number here)&
ssl_description=Name1+Name2&
ssl_amount=184.48&
ssl_txn_id=GUID&
ssl_result=1&
ssl_card_number=XXXX(actual number here)&
ssl_completion_date=&
ssl_txn_time=10%2F28%2F2016+04%3A03%3A18+PM&
ssl_avs_response=G">
<style type="text/css">
BODY, TD, INPUT, SELECT, TEXTAREA, BUTTON, .normal {
font-family: arial,helvetica,sans-serif;
font-size: 10pt;
font-weight: normal;
}
.small {
font-size: 10pt;
}
.medium {
font-size: 14pt;
}
.large {
font-size: 18pt;
}
</style>
</head>
<form name="frmMenu" action="#" method="POST">
<input type="hidden" name="dispatchMethod" />
<input type="hidden" name="permissionDesc" />
<input type="hidden" name="menuAction" />
<input type="hidden" name="thClientID" value="" />
</form> <!-- start Mixpanel -->
</body>
</html>