Discord role divider generator

by Davri

HTML

<html>

  <body>
    <h1>Discord role divider generator</h1>
    <div id='input-area'>
      <input id='input-box' contenteditable='plaintext-only' placeholder='Role name'>
      <div id='generatebutton' class='button' onclick='generateText()'>Generate</div>
    </div>
    <div id='output-area'>
      <input id='output-box' onclick='output.select()' value=''>
      <div id='width-options'>
        <p>Width:</p>
        <div id='counter'>
          <div id='minus-button' class='button' onclick='updateCounter(rolewidth-1); generateText()'>-</div>
          <input id='counter-value' type='number' min=0 onchange='updateCounter(parseInt(this.value))'>
          <div id='plus-button' class='button' onclick='updateCounter(rolewidth+1); generateText()'>+</div>
        </div>
      </div>
    </div>
    <div id='tip'>Tip: set the role color to #292B2F for better results</div>
    <div id='hidden'></div>
  </body>

</html>

CSS

@font-face {
  font-family: Whitney;
  font-weight: 500;
  src: url("https://api.allorigins.win/raw?url=https://discord.com/assets/cf4a8a10bbdf9b775fad41e0b9921c84.woff2") format("woff2");
}

body {
  font-family: 'Whitney', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
  background-color: #18191C;
  color: white;
  text-align: center;
}

h1 {
  font-weight: 500;
}

p {
  line-height: 36px;
  margin: 0;
}

body > div:not(#tip) {
  margin: 25px;
}

input,
.button {
  padding: 10px;
  margin: 1px;
  border-radius: 3px;
  font-size: 16px;
}

input {
  display: inline;
  font-family: inherit;
  color: inherit;
  background-color: #292B2F;
}

.button {
  display: inline-block;
  cursor: pointer;
  user-select: none;
}

.button:hover {
  transition: background 0.17s ease;
}

div#generatebutton {
  background-color: #3BA55D;
}

div#generatebutton:hover {
  background-color: #2D7D46;
}

input#input-box,
input#output-box {
  width: 300px;
  border: 1px solid rgba(0, 0, 0, 0.3);
}

input#output-box {
  min-width: 350px;
  text-align: center;
}

div#width-options {
  padding: 15px;
}

div#width-options > p {
  display: inline;
}

div#counter {
  display: inline-flex;
  height: 32px;
  padding: 4px;
}

div#counter > div {
  flex-shrink: 0;
  background-color: #292B2F;
  padding: 4px;
  width: 16px;
}

div#counter > div:hover {
  background-color: #34363C;
}

div#minus-button {
  border-radius: 3px 0 0 3px;
}

div#plus-button {
  border-radius: 0 3px 3px 0;
}

div#counter > input {
  width: 32px;
  -moz-appearance: textfield;
  border: none;
  border-radius: 0;
}

div#counter > input::-webkit-outer-spin-button,
div#counter > input::-webkit-inner-spin-button {
  display: none;
}

div#hidden {
  visibility: hidden;
  position: absolute;
  overflow: auto;
  font-size: 12px;
  font-weight: 500;
}

div#tip {
  position: fixed;
  bottom: 5px;
  right: 5px;
  color: #4A4D55;
}

JavaScript

var rolewidth = 200;

var hiddendiv = document.getElementById('hidden');
var userinput = document.getElementById('input-box');
var output = document.getElementById('output-box');
var counter = document.getElementById('counter-value');
counter.value = rolewidth;

const zwsp = "\u200b"; // zero width space
const unicode = [[12, "\u2001"], [6, "\u2000"], [3, "\u2005"], [0.9, "\u200a"]];
// em quad, en quad, three per em space, hair space
// - first value in each array is width in pixels, second is escaped character

userinput.addEventListener("keydown", function(event) {
  if (event.keyCode === 13) {
    document.getElementById("generatebutton").click();
  }
});

function whitespace(length) {
  var output = "";
  unicode.forEach(([charlength, char]) => {
    while (length >= charlength) {
      output += char;
      length -= charlength;
    }
  })
  return output;
}

function updateCounter(value) {
  if (value > 0) {
    rolewidth = value;
    counter.value = value;
  }
}

function generateText() {
  hiddendiv.innerText = userinput.value;
  var textwidth = hiddendiv.clientWidth;
  if (textwidth > rolewidth - 14) {
    output.value = "The text is too long!";
    return;
  }
  // left side is slightly shorter because of the role color blob
  var left = rolewidth / 2 - textwidth / 2 - 9;
  var right = rolewidth / 2 - textwidth / 2 + 8;
  output.value = (zwsp + whitespace(left) + userinput.value + whitespace(right) + "\u200a".repeat(Math.ceil(right % 1)) + zwsp);
  output.focus();
  output.select();
}
// I have no idea what I'm doing, I have never used js before