Когда «Как спросить» слишком тонко

  

Это первый код JavaScript, который я когда-либо писал, alert("hello, world!"); в стороне.


Этот сайт закрывает довольно много вопросов, потому что люди не читают справочник правил или обратите внимание на панель Как спросить , которая отображается при вводе названия вопроса - почти 60% закрытых вопросов связаны с нарушенным кодом , поэтому я предложил выпустить предупреждение о красном знаке, когда пользователь собирается задать вопиющий вопрос вне темы с сломанным кодом.

Не зная, будет ли Stack Exchange продвигаться с чем-то подобным, Я предложил нам реализовать один из них , черт возьми. Еще слишком рано для июля , так что это не запись ... ну это было бы, но я просто не мог дождаться, чтобы что-то попробовать, так что вот оно.


Я «украл» некоторые HTML и CSS на странице Ask Question , немного поместил его в поле «Стек-фрагмент» и приступил к реализации кода JavaScript, чтобы он работал.

Давай, попробуй! Сценарий запускается, когда вы нажимаете ENTER в поле заголовка.

  

ПРИМЕЧАНИЕ . В коде используется String.includes, который может быть недоступен в вашем браузере. Подробнее см. принятый ответ .

 function validateKey(e) {
  "use strict";
  if (e.keyCode == 13) {
    var field = document.getElementById("title");
    if (!validateTitle(field)) {
      showWarning();
    }
    else {
      clearWarning();
    }
  } 
}


function validateTitle(titleField) {
  "use strict";
  var title = titleField.value;
  return !title.includes("bug") 
      && !title.includes("issue") 
      && !title.includes("t work") // catches won't work, isn't working, etc.
      && !title.includes("s wrong") // catches what's wrong, what is wrong
      && !title.includes("fix")
      && !title.includes("why");
}


function showWarning() {
  "use strict";
  var msg = getWarningDiv();
  document.getElementsByTagName("table")[0].appendChild(msg);
}

function clearWarning() {
  "use strict";
  var popup = document.getElementsByClassName("message-dismissable")[0];
  if (popup == undefined) {
    return;
  }
  
  popup.parentNode.removeChild(popup);
}

function getWarningDiv() {
  "use strict";
  
  var popup = document.createElement("div");  
  popup.className = "message message-error message-dismissable";
  popup.setAttribute("style", "max-width: 270px; min-width: 270px; position: absolute; top: 32px; left: 378px; display: block;");
  popup.addEventListener("click", function(event) { clearWarning(); });
  
  var tooltip = document.createElement("div");
  tooltip.className = "message-inner message-tip message-tip-left-top";
  
  popup.appendChild(tooltip);
  
  var tipText = document.createElement("div");
  tipText.title = "close this message (or hit Esc)";
  tipText.className = "message-close";
  tipText.textContent  = "×";
  
  tooltip.appendChild(tipText);
  
  var msg = document.createElement("div");
  msg.className = "message-text";
  msg.setAttribute("style", "padding-right: 35px;");
  msg.textContent = "Wait! If your code does not work as intended, this question is off-topic!";
  
  popup.appendChild(msg);
  return popup;
}
 body {
  font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
  font-size: 13px;
  line-height: 1.3em;
  color: #222;
  background: #fff;
  min-width: 1030px;
}

.ask-title-table {
  width: 668px;
  height: 44px;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
  border-color: grey;
}

.ask-title-cell-key {
  width: 40px;
}

#title {
  width: 498px;
}

.form-item label {
  display: block;
  font-weight: bold;
  padding-bottom: 3px;
}

input[type=text], input[type=url], input[type=email], input[type=tel], textarea {
  font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
  background: #fff;
  color: #444;
  border: 1px solid #ccc;
  font-size: 14px;
  padding: 8px 10px;
}

.message.message-error.message-dismissable {
  cursor: pointer;
}

.message.message-error {
  z-index: 1;
  display: none;
  color: #fff;
  background-color: #c04848;
  text-align: left;
}

.message.message-error .message-text {
  padding: 15px;
}

.message.message-error .message-close {
  padding: 2px 6px 3px 6px;
  font-family: Arial,sans-serif;
  font-size: 16px;
  font-weight: normal;
  color: #fcb2b1 !important;
  line-height: 1;
  float: right;
  border: 1px solid rgba(255,255,255,0.2);
  margin-top: 8px;
  margin-right: 8px;
}

.message.message-error .message-tip-left-top:before {
  top: 0;
  left: -9px;
  border-top: 9px solid #c04848;
  border-left: 9px solid transparent;
}

.message.message-error .message-tip:before {
  content: "";
  position: absolute;
}
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
  <head>
      <title>Ask a Question - Code Review Stack Exchange</title>
  </head>
  <body>
    <form>
    <div id="question-form">
      <div class="form-item ask-title">
        <table class="ask-title-table">
          <tbody>
            <tr>
              <td class="ask-title-cell-key">
                <label for="title">Title</label>
              </td>
              <td class="ask-title-cell-value">
                <input id="title" name="title" type="text" maxlength="300" tabindex="100" placeholder="State the task that your code accomplishes. Make your title distinctive." class="ask-title-field" data-min-length="15" data-max-length="150" autocomplete="off" onkeypress="return validateKey(event)"/>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <!-- warning should be inserted here -->
    </div>
    </form>
  </body>
</html>

Опять же, CSS и HTML не совсем мои - это всего лишь оправдание для JavaScript, который я бы хотел улучшить. Кроме того, я не заметил каких-либо вопиющих ложных срабатываний?

30 голосов | спросил Mathieu Guindon 12 J0000006Europe/Moscow 2015, 09:34:37

4 ответа


28

String.includes() является частью экспериментального предложения ECMAScript 6. Поэтому вы не можете полагаться на то, что он доступен в браузерах. В браузерах, которые не поддерживают String.includes(), ваш скрипт ничего не делает - он просто оставляет ошибку в консоли JavaScript, если вам интересно посмотреть там. Это одна из опасностей программирования JavaScript: страница просто ломается полностью из-за одной ошибки, даже если она работает в вашем собственном браузере.

Консервативный подход, title.indexOf(…) >= 0, определенно рекомендуется.

Кроме этого, ваш код выглядит неплохо. Однако, поскольку вы включили jQuery в свой фрагмент Stack, я озадачен тем, почему вы его не использовали. Большая часть этого кода будет упрощена.

Подробнее jQuery, пожалуйста!

ответил 200_success 12 J0000006Europe/Moscow 2015, 11:12:01
23

Метод validateTitle принимает titleField, а затем извлекает titleField.value как title. Поскольку основная ответственность за эту функцию заключается в проверке строки, было бы лучше сделать именно это, без дополнительных знаний о том, что он должен извлечь эту строку, вызвав .value в полученное поле. Короче говоря, просто передайте ему значение поля напрямую.


Это, конечно, о клавише ввода:

  if (e.keyCode == 13) {

Но это более очевидно и легче читать:

  var ENTER_KEY = 13;
  // ...

  if (e.keyCode == ENTER_KEY) {

Вместо повторяющегося !title.includes с образцами строк, закодированными в коде:

  // ...
  && !title.includes("issue") 
  && !title.includes("t work") // catches won't work, isn't working, etc.
  // ...

Я предлагаю помещать подозрительные строки в массив около вершины кода и заменять повторяющийся !title.includes на цикл:

var INVALID_STRINGS = [
    'bug',
    'issue',
    't work',   // catches won't work, isn't working, 
    's wrong',  // catches what's wrong, what is wrong
    'fix',
    'why'
];

// ...

  for (var i = 0; i < INVALID_STRINGS.length; ++i) {
      if (title.includes(INVALID_STRINGS[i])) {
          return false;
      }
   }
   return true;

Мне нравится делать различие между двумя типами методов проверки:

  • validateSomething:
    • Проверьте, действительно ли «что-то», а если нет, создайте исключение.
    • В качестве альтернативы проверьте, действительно ли «что-то», и делайте разные вещи в зависимости от успеха /неудачи.
  • isValidSomething:
    • Проверьте, что «что-то» действительно, и верните true или false соответственно.

В этом духе я бы переименовал validateTitle в isValidTitle


Смотрите исполняемый фрагмент с приведенными выше изменениями.

 var ENTER_KEY = 13;
var INVALID_STRINGS = [
    'bug',
    'issue',
    't work',   // catches won't work, isn't working, 
    's wrong',  // catches what's wrong, what is wrong
    'fix',
    'why'
];

function validateKey(e) {
  "use strict";
  if (e.keyCode == ENTER_KEY) {
    var field = document.getElementById("title");
    if (!isValidTitle(field.value)) {
      showWarning();
    } else {
      clearWarning();
    }
  } 
}

function isValidTitle(title) {
  "use strict";
  for (var i = 0; i < INVALID_STRINGS.length; ++i) {
      if (title.includes(INVALID_STRINGS[i])) {
          return false;
      }
   }
   return true;
}

function showWarning() {
  "use strict";
  var msg = getWarningDiv();
  document.getElementsByTagName("table")[0].appendChild(msg);
}

function clearWarning() {
  "use strict";
  var popup = document.getElementsByClassName("message-dismissable")[0];
  if (popup == undefined) {
    return;
  }
  
  popup.parentNode.removeChild(popup);
}

function getWarningDiv() {
  "use strict";
  
  var popup = document.createElement("div");  
  popup.className = "message message-error message-dismissable";
  popup.setAttribute("style", "max-width: 270px; min-width: 270px; position: absolute; top: 32px; left: 378px; display: block;");
  popup.addEventListener("click", function(event) { clearWarning(); });
  
  var tooltip = document.createElement("div");
  tooltip.className = "message-inner message-tip message-tip-left-top";
  
  popup.appendChild(tooltip);
  
  var tipText = document.createElement("div");
  tipText.title = "close this message (or hit Esc)";
  tipText.className = "message-close";
  tipText.textContent  = "×";
  
  tooltip.appendChild(tipText);
  
  var msg = document.createElement("div");
  msg.className = "message-text";
  msg.setAttribute("style", "padding-right: 35px;");
  msg.textContent = "Wait! If your code does not work as intended, this question is off-topic!";
  
  popup.appendChild(msg);
  return popup;
}
 body {
  font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
  font-size: 13px;
  line-height: 1.3em;
  color: #222;
  background: #fff;
  min-width: 1030px;
}

.ask-title-table {
  width: 668px;
  height: 44px;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
  border-color: grey;
}

.ask-title-cell-key {
  width: 40px;
}

#title {
  width: 498px;
}

.form-item label {
  display: block;
  font-weight: bold;
  padding-bottom: 3px;
}

input[type=text], input[type=url], input[type=email], input[type=tel], textarea {
  font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
  background: #fff;
  color: #444;
  border: 1px solid #ccc;
  font-size: 14px;
  padding: 8px 10px;
}

.message.message-error.message-dismissable {
  cursor: pointer;
}

.message.message-error {
  z-index: 1;
  display: none;
  color: #fff;
  background-color: #c04848;
  text-align: left;
}

.message.message-error .message-text {
  padding: 15px;
}

.message.message-error .message-close {
  padding: 2px 6px 3px 6px;
  font-family: Arial,sans-serif;
  font-size: 16px;
  font-weight: normal;
  color: #fcb2b1 !important;
  line-height: 1;
  float: right;
  border: 1px solid rgba(255,255,255,0.2);
  margin-top: 8px;
  margin-right: 8px;
}

.message.message-error .message-tip-left-top:before {
  top: 0;
  left: -9px;
  border-top: 9px solid #c04848;
  border-left: 9px solid transparent;
}

.message.message-error .message-tip:before {
  content: "";
  position: absolute;
}
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
  <head>
      <title>Ask a Question - Code Review Stack Exchange</title>
  </head>
  <body>
    <form>
    <div id="question-form">
      <div class="form-item ask-title">
        <table class="ask-title-table">
          <tbody>
            <tr>
              <td class="ask-title-cell-key">
                <label for="title">Title</label>
              </td>
              <td class="ask-title-cell-value">
                <input id="title" name="title" type="text" maxlength="300" tabindex="100" placeholder="state the task that your code accomplishes. Make your title distinctive." class="ask-title-field" data-min-length="15" data-max-length="150" autocomplete="off" onkeypress="return validateKey(event)"/>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <!-- warning should be inserted here -->
    </div>
    </form>
  </body>
</html>
ответил janos 12 J0000006Europe/Moscow 2015, 10:20:03
14

Я удивлен, увидев, что никто не упомянул об этом, но вы забыли одну вещь:

  

В МОЕМ КОДЕ ПРОБЛЕМА

является принятым названием, а

  

в моем коде есть ошибка

нет.

Вы действительно должны сделать его нечувствительным к регистру.


Подход String-contains - это простой подход, чтобы принять эту проблему, но также может привести к ложным срабатываниям:

  • "Отслеживание проблем в Github с помощью скрипта Python"
  • «Остановите прослушивание меня! (Игра об ошибках)»

В этом случае, однако, это не мешает тому, что ИМО имеет ложные срабатывания, и я должен сказать, что ваш простой фильтр неплох.

ответил Simon Forsberg 12 J0000006Europe/Moscow 2015, 20:59:41
12

Несколько мелочей:

"use strict";

Увидев, как вы хотите, чтобы все ваши функции использовали строгий режим, просто поместите его в верхнюю часть файла. (Обратите внимание, что перед ним разрешены только комментарии и пробел.)

    if (!validateTitle(field)) {
      showWarning();
    }
    else {
      clearWarning();
    }
  if (popup == undefined) {
    return;
  }

  popup.parentNode.removeChild(popup);

Сравнение может быть заменено на более простой и короткий код:

    if (validateTitle(field)) {
      clearWarning();
    }
    else {
      showWarning();
    }
  if (popup) {
    popup.parentNode.removeChild(popup);
  }
ответил curiousdannii 12 J0000006Europe/Moscow 2015, 14:24:58

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132