Как я могу автоматически показать результат функции JavaScript в форме HTML, когда я изменяю ввод? - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть переменная javascript с параметрами, но я не знаю, как передать ее в мой код html. Код javascript взят из https://gist.github.com/EvanHahn/2587465:

var caesarShift = function(str, amount) {
    // Wrap the amount
    if (amount < 0)
        return caesarShift(str, amount + 26);

    // Make an output variable
    var output = '';

    // Go through each character
    for (var i = 0; i < str.length; i ++) {
        // Get the character we'll be appending
        var c = str[i];

        // If it's a letter...
        if (c.match(/[a-z]/i)) {
            // Get its code
            var code = str.charCodeAt(i);

            // Uppercase letters
            if ((code >= 65) && (code <= 90))
                c = String.fromCharCode(((code - 65 + amount) % 26) + 65);

            // Lowercase letters
            else if ((code >= 97) && (code <= 122))
                c = String.fromCharCode(((code - 97 + amount) % 26) + 97);
        }

        // Append
        output += c;
    }

    // All done!
    return output;
};

Я хочу передать его моему HTML, очевидно. Я провел некоторые исследования и наткнулся на такие способы, как:

<p id="output"></p>

, а затем

document.getElementById('output').innerHTML = lengthOfName;

, но я не знаю, как все это сложить вместе. Как мне вызвать переменную? Для строки у меня есть поле ввода текстовой области, и, возможно, кликер для второго аргумента, сумма, но я не знаю, как собрать все это вместе в HTML.

В моем предыдущий вопрос, Как сделать функцию javascript атрибутом html? , и мой ответ был HTTP-формой. Но я пытаюсь создать сайт, который имеет много способов расшифровки 1 строки. Так что если пользователю приходится нажимать кнопку «Отправить» каждый раз, особенно в этом случае 25 раз, это не будет таким уж полезным. Есть ли способ заставить его жить без кнопки отправки? Это то, к чему я стремлюсь, https://cryptii.com/pipes/caesar-cipher.

1 Ответ

1 голос
/ 08 апреля 2020

Вам нужно предотвратить событие по умолчанию после нажатия кнопки.

e.preventDefault(); // Do not submit!

Также я полировал логи c в шифре, чтобы учесть отрицательные сдвиги.

Примечание: нет никаких причин для вызова смены, если сумма равна нулю, просто верните входящее сообщение ... если только вы на самом деле не хотите, чтобы он очищал сообщение от буквенных символов.


Обновление: Добавлена ​​динамическая форма c без кнопки.

Обратите внимание на удобную функцию addEventListeners, которую я создал ниже. Это позволяет добавить событие к нескольким элементам для множества различных типов событий. Это в лучшем случае элементарно, но экономит ваше время при добавлении каждого слушателя событий. Лучшим подходом был бы объект. Я, вероятно, добавлю альтернативный пример внизу.

const caesarShift = (str, amount) => {
  const LOWER_A = 'a'.charCodeAt(0) , LOWER_Z = 'z'.charCodeAt(0),
        UPPER_A = 'A'.charCodeAt(0) , UPPER_Z = 'Z'.charCodeAt(0),
        SIZE    = LOWER_Z - LOWER_A ;
  if (amount === 0) return str;
  let output = '';
  for (let i = 0; i < str.length; i++) {
    let c = str[i];
    if (c.match(/[a-z]/i)) {
      let offset = -1, code = str.charCodeAt(i);
      if (code >= LOWER_A && code <= LOWER_Z) {
        offset = LOWER_A;
      } else if (code >= UPPER_A && code <= UPPER_Z) {
        offset = UPPER_A;
      }
      if (offset !== -1) {
        c = String.fromCharCode(offset + ((code - offset) + amount + SIZE) % SIZE);
      }
    }
    output += c;
  }
  return output;
};

const form = document.forms['caesar-1'];
form.querySelector('button').addEventListener('click', (e) => {
  form.result.value = caesarShift(
    form.message.value,
    parseInt(form.amount.value, 10)
  );
  e.preventDefault(); // Do not submit!
});

const form2 = document.forms['caesar-2'];
addEventListeners('input, textarea', 'change keyup', (e) => {
  form2.result.value = caesarShift(
    form2.message.value,
    parseInt(form2.amount.value, 10)
  );
}, form2);

// Initial change events
triggerEvent(form.querySelector('button'), 'click');
triggerEvent(form2.message, 'change'); 

// Custom functions to make life easier...
function addEventListeners(selector, eventNames, eventFn, scope) {
  scope = scope || document;
  const names = eventNames.split(/\s+/g);
  selector.split(/\s*,\s*/).forEach(sel => {
    Array.from(scope.querySelectorAll(sel)).forEach(el => {
      names.forEach(eventName => el.addEventListener(eventName, eventFn));
    });
  });
}
function triggerEvent(el, eventName) {
  let event = document.createEvent('HTMLEvents');
  event.initEvent(eventName, true, false);
  el.dispatchEvent(event);
}
hr { margin: 1em 0; }

.form-field {
  margin-bottom: 0.5em;
}

.form-field label {
  display: inline-block;
  width: 4em;
  font-weight: bold;
}

form button {
  margin-left: 5em;
  margin-bottom: 0.5em;
}

.form-field-stacked {
  display: inline-block;
  vertical-align: top;
  margin-right: 0.5em;
}

.form-field-stacked label {
  display: block;
  margin-bottom: 0.25em;
  width: auto;
}

.form-field-stacked input[type="number"] {
  width: 3em;
}
<h2>Button Form</h2>
<form name="caesar-1">
  <div class="form-field">
    <label>Message</label>
    <input name="message" type="text" value="Hello World"/>
  </div>
  <div class="form-field">
    <label>Amount</label>
    <input name="amount" type="number" value="13" />
  </div>
  <button>Rotate</button>
  <div class="form-field">
    <label>Output</label>
    <input name="result" type="text" disabled="disabled" />
  </div>
</form>
<hr />
<h2>Dynamic Form</h2>
<form name="caesar-2">
  <div class="form-field form-field-stacked">
    <label>Message</label>
    <textarea name="message" rows="4" cols="24">Hello World</textarea>
  </div>
  <div class="form-field form-field-stacked">
    <label>Amount</label>
    <input name="amount" type="number" value="13" />
  </div>
  <div class="form-field form-field-stacked">
    <label>Output</label>
    <textarea name="result" rows="4" cols="24" disabled="disabled"></textarea>
  </div>
</form>

Еще более динамическая c функция прослушивания событий.

const caesarShift=(t,e)=>{if(r="a".charCodeAt(0),a="z".charCodeAt(0),o="A".charCodeAt(0),c="Z".charCodeAt(0),h=a-r,0===e)return t;let C="";for(let d=0;d<t.length;d++){let A=t[d];if(A.match(/[a-z]/i)){let C=-1,f=t.charCodeAt(d);f>=r&&f<=a?C=r:f>=o&&f<=c&&(C=o),-1!==C&&(A=String.fromCharCode(C+(f-C+e+h)%h))}C+=A}return C};

const form = document.forms['caesar'];
const handleUpdate = (e) => {
  form.result.value = caesarShift(
    form.message.value,
    parseInt(form.amount.value, 10)
  );
}

addEventListeners({
  selector : 'input',
  listeners : {
    'change' : handleUpdate,
    'keyup' : handleUpdate
  },
  scope: form
}, {
  selector : 'textarea',
  listeners : {
    'change' : handleUpdate,
    'keyup' : handleUpdate
  },
  scope: form
});

// Initial change events
triggerEvent(form.message, 'change'); 

// Custom functions to make life easier...
function addEventListeners(...configs) {
  configs.forEach(config => {
    let options = config.options || {};
    let els = Array.from((config.scope || document).querySelectorAll(config.selector));
    Object.keys(config.listeners || {}).forEach(eventName => {
      els.forEach(el => {
        el.addEventListener(eventName, config.listeners[eventName], options)
      });
    });
  });
}
function triggerEvent(el, eventName) {
  let event = document.createEvent('HTMLEvents');
  event.initEvent(eventName, true, false);
  el.dispatchEvent(event);
}
.form-field {
  margin-bottom: 0.5em;
}

.form-field label {
  font-weight: bold;
}

.form-field-stacked {
  display: inline-block;
  vertical-align: top;
  margin-right: 0.5em;
}

.form-field-stacked label {
  display: block;
  margin-bottom: 0.25em;
  width: auto;
}

.form-field-stacked input[type="number"] {
  width: 3em;
}
<h2>Dynamic Form</h2>
<form name="caesar">
  <div class="form-field form-field-stacked">
    <label>Message</label>
    <textarea name="message" rows="4" cols="24">Hello World</textarea>
  </div>
  <div class="form-field form-field-stacked">
    <label>Amount</label>
    <input name="amount" type="number" value="13" />
  </div>
  <div class="form-field form-field-stacked">
    <label>Output</label>
    <textarea name="result" rows="4" cols="24" disabled="disabled"></textarea>
  </div>
</form>
...