2

I'm making a simple data url maker and I'm wondering why the code for my clear button isn't working, when other sections with the exact same code are working.

function go() {
  var string = document.getElementById("input").value;
  var encodedString = btoa(string);
  document.getElementById("output").value = "data:text/html;base64," + encodedString;
}

function copy() {
  var copyText = document.getElementById("output");
  copyText.select();
  copyText.setSelectionRange(0, 99999)
  document.execCommand("copy");
}

function clear() {
  document.getElementById("output").value = "";
  document.getElementById("input").value = "";
}
var input = document.getElementById("input");
input.addEventListener("keyup", function(event) {
  if (event.keyCode === 13) {
    event.preventDefault();
    document.getElementById("go").click();
  }
});
button {
  font-family: 'Baloo 2', cursive;
  background-color: lightgrey;
}

input {
  font-family: 'Baloo 2', cursive;
}
<link href="https://fonts.googleapis.com/css?family=Baloo+2&display=swap" rel="stylesheet">
<input id="input" type="text" size="160" placeholder="HTML here" value="">
<button onclick="clear()">&#x1f7aa;</button>
<button id="go" onclick="go()">Convert</button>
<br><br>
<input type="text" placeholder="Output here" id="output" size="160">
<button onclick="copy()">Copy text</button>

Near the bottom, the function called 'clear' isn't working. When I hit the button which calls that function, nothing happens.

However, I'm using the exact same code in the function 'go', which is working.

Pointy
  • 405,095
  • 59
  • 585
  • 614
TorNato
  • 305
  • 2
  • 12

2 Answers2

3

When you use an inline handler, the handler is wrapped inside two with statements: one for the element the handler is on, and one for the document. Your code is doing something like:

with (document) {
  with (button) {
    clear();
  }
}

But clear exists on the document:

console.log(document.clear);

So, when you reference an identifier named clear, it never gets out of the withs, so the function that you called clear never runs.

Use a different variable name, like clearInputAndOutput:

function go() {
  var string = document.getElementById("input").value;
  var encodedString = btoa(string);
  document.getElementById("output").value = "data:text/html;base64," + encodedString;
}

function copy() {
  var copyText = document.getElementById("output");
  copyText.select();
  copyText.setSelectionRange(0, 99999)
  document.execCommand("copy");
}

function clearInputAndOutput() {
  document.getElementById("output").value = "";
  document.getElementById("input").value = "";
}
var input = document.getElementById("input");
input.addEventListener("keyup", function(event) {
  if (event.keyCode === 13) {
    event.preventDefault();
    document.getElementById("go").click();
  }
});
button {
  font-family: 'Baloo 2', cursive;
  background-color: lightgrey;
}

input {
  font-family: 'Baloo 2', cursive;
}
<link href="https://fonts.googleapis.com/css?family=Baloo+2&display=swap" rel="stylesheet">
<input id="input" type="text" size="160" placeholder="HTML here" value="">
<button onclick="clearInputAndOutput()">&#x1f7aa;</button>
<button id="go" onclick="go()">Convert</button>
<br><br>
<input type="text" placeholder="Output here" id="output" size="160">
<button onclick="copy()">Copy text</button>

But it would be far better to attach the event handler properly using Javascript. Inline handlers have too many scoping and escaping problems, and are best avoided. Use addEventListener instead, and you won't have to worry about name collisions or global variable problems:

const [clearBtn, goBtn, copyBtn] = document.querySelectorAll('button');
clearBtn.addEventListener('click', () => {
  document.getElementById("output").value = "";
  document.getElementById("input").value = "";
});
goBtn.addEventListener('click', () => {
  var string = document.getElementById("input").value;
  var encodedString = btoa(string);
  document.getElementById("output").value = "data:text/html;base64," + encodedString;
});
copyBtn.addEventListener('click', () => {
  var copyText = document.getElementById("output");
  copyText.select();
  copyText.setSelectionRange(0, 99999)
  document.execCommand("copy");
});

var input = document.getElementById("input");
input.addEventListener("keyup", function(event) {
  if (event.keyCode === 13) {
    event.preventDefault();
    document.getElementById("go").click();
  }
});
button {
  font-family: 'Baloo 2', cursive;
  background-color: lightgrey;
}

input {
  font-family: 'Baloo 2', cursive;
}
<link href="https://fonts.googleapis.com/css?family=Baloo+2&display=swap" rel="stylesheet">
<input id="input" type="text" size="160" placeholder="HTML here" value="">
<button>&#x1f7aa;</button>
<button id="go">Convert</button>
<br><br>
<input type="text" placeholder="Output here" id="output" size="160">
<button>Copy text</button>
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Thank you for the answer! I was really confused. I have one more question though: When I run my code on this page, or on another hosting page everything works. However, when I put the code onto a base64 encoded data: url, the buttons suddenly stop working. Why might this be? – TorNato Mar 22 '20 at 01:59
  • See the snippet in your question - it doesn't look to work here (because `document.clear` exists). What hosting page does it work on, do you have a link so I can see for myself? Seems pretty odd, I'd expect it to always fail (or always succeed), given the same browser. – CertainPerformance Mar 22 '20 at 02:16
  • Yeah, @CertainPerformance. I put the code into a site called w3schools.com, where it worked, but when I encoded it into base64 and made it into a data: url, none of the JS worked which is weird. It doesn't matter that much, because I'm now hosting it on Github, but [here](https://www.w3schools.com/code/tryit.asp?filename=GD3HN8TZHMOO)'s a link if you're curious. (If you want to see the data url version, just copy the code on the right into the box in the top left.) – TorNato Mar 23 '20 at 05:27
2

As a solution, you can change the function name "clear" to something else. It may be mistaken with default functions of JavaScript with the same name, e.g. document.clear

user3842413
  • 176
  • 1
  • 9