Использование CSS Grid для создания простого калькулятора на ванильном JavaScript

#javascript #html #css

#javascript #HTML #css

Вопрос:

Я работал над простым калькулятором на ванильном JavaScript и тем временем воспользовался возможностью попробовать свои силы в использовании CSS Grid (пока я использовал его очень мало раз, и мне все еще нужно многое улучшить). У меня не было проблем с JavaScript, но у меня были проблемы с использованием CSS Grid.

 const calculator = () => {
  const doc = document,
    screen = doc.getElementById(`calculator__screen`),
    keys = doc.getElementById(`calculator__keys`);
  let operationStatus = false,
    number1,
    typeOperation;

  screen.textContent = `0`;

  if (!keys) return;
  keys.addEventListener(`click`, (e) => {
    const t = e.target,
      d = t.dataset;

    if (d.number) {
      writeScreen(d.number);
    }

    if (d.math) {
      getOperation(t, d.math);
    }

    if (d.operation) {
      runOperation(d.operation);
    }
  });
  const writeScreen = (number) => {
    screen.textContent === `0` || operationStatus === true ?
      (screen.textContent = number) :
      number === `.` amp;amp; !screen.textContent.includes(`.`) ?
      (screen.textContent  = number) :
      number !== `.` ?
      (screen.textContent  = number) :
      null;
    operationStatus = false;
  };
  const getOperation = (element, operation) => {
    operationStatus = true;
    number1 = Number(screen.textContent);
    typeOperation = operation;
    screen.textContent = element.textContent;
  };
  const runOperation = (operation) => {
    operation === `clear` ?
      (screen.textContent = `0`) :
      getResult(number1, typeOperation);
    operationStatus = true;
  };
  const getResult = (number1, typeOperation) => {
    const number2 = Number(screen.textContent);
    let resu<
    switch (typeOperation) {
      case `add`:
        result = number1   number2;
        break;

      case `minus`:
        result = number1 - number2;
        break;

      case `multiply`:
        result = number1 * number2;
        break;

      case `divide`:
        result = number1 / number2;
        break;
      default:
        break;
    }
    result === Infinity ?
      (screen.textContent = `Error`) :
      (screen.textContent = result);
  };
};

window.addEventListener(`load`, () => {
  calculator();
});  
 /*Variables*/

:root {
  --body-bg: #fbfbfe;
  --black: #000;
  --white: #fff;
}


/*Base*/

*,
*::after,
*::before {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

*::after,
*::before {
  content: "";
}

a {
  text-decoration: none;
}

img {
  display: block;
  max-width: 100%;
}

li,
ol,
ul {
  list-style: none;
}


/*Calculator*/

.calculator {
  margin: 0 auto;
  max-width: 25rem;
  width: 90%;
}

.calculator__keys {
  display: grid;
  grid-gap: 0.25rem;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(5, 1fr);
   :first-child {
    height: 0;
    padding-bottom: 100%;
  }
}

.calculator button {
  border: none;
  font-size: 1rem;
}

[data-math="add"],
[data-operation="equals"] {
  grid-row: span 2;
}

[data-number="0"] {
  grid-column: span 2;
}

[data-operation="clear"] {
  grid-column: 1;
  grid-row: 1;
}

.calculator__screen {
  background: rgba(0, 0, 0, 0.8);
  border-radius: 0.25rem;
  color: var(--white);
  margin-bottom: 0.25rem;
  padding: 1rem;
  text-align: right;
}  
 <div class="calculator">
  <div class="calculator__screen" id="calculator__screen">

  </div>
  <div class="calculator__keys" id="calculator__keys">
    <button data-operation="clear">

    </button>
    <button data-operation="clear">
      C
    </button>
    <button data-math="divide">
      /
    </button>
    <button data-math="multiply">
      *
    </button>
    <button data-math="minus">
      -
    </button>
    <button data-number="7">
      7
    </button>
    <button data-number="8">
      8
    </button>
    <button data-number="9">
      9
    </button>
    <button data-math="add">
       
    </button>
    <button data-number="4">
      4
    </button>
    <button data-number="5">
      5
    </button>
    <button data-number="6">
      6
    </button>
    <button data-number="1">
      1
    </button>
    <button data-number="2">
      2
    </button>
    <button data-number="3">
      3
    </button>
    <button data-operation="equals">
      =
    </button>
    <button data-number="0">
      0
    </button>
    <button data-number=".">
      .
    </button>
  </div>
</div>  

Ссылка на Codepen: https://codepen.io/AlessandroReina/pen/wvWaJyw

Если вы посмотрите на него, вы увидите белую ячейку рядом с клавишей clear (C); Я действительно не понимаю, что генерирует эту пустую ячейку. Кроме того, я намеревался разместить клавиши «-«, » » и «=» в правой части моего калькулятора, но я не знаю почему, вместо этого они расположены с левой стороны.

Не мог бы кто-нибудь из вас взглянуть на мой проект и сказать мне, где я ошибаюсь?

Заранее спасибо всем, кто мне поможет.

С наилучшими пожеланиями

Алессандро

Комментарии:

1. Пожалуйста, добавьте свой код прямо здесь, в вашем вопросе, а не на внешнем сайте кода. Нажмите «редактировать» под вашим сообщением, затем нажмите <> кнопку.

2. Почему у вас есть 2 кнопки с data-operation="clear" ? Кроме того, какой в этом смысл? *::after, *::before { content: ""; }

3. Привет, connexo, прежде всего, спасибо за ваш ответ, я ввел *::after, *::before { content: «»; } среди моих основных стилей, потому что, поскольку каждому псевдоэлементу after или before требуется свойство content, даже если оно пустое, если бы мне пришлось вставить какой-нибудь псевдоэлемент в мой проектЯ бы избегал писать content: «»; каждый раз

4. Это действительно плохая идея, потому что это означает, что теперь они будут у любых элементов. Элементы Psueod никогда не должны создаваться на элементах, где они вам не нужны.

Ответ №1:

Если вы проверяете код, ::before ::after псевдоэлемент and считается дочерним элементом Grid. Вы определили глобальные стили для псевдоэлемента с пустым содержимым, которое портит структуру.

 *::after,
*::before {
  content: "";
}
  

Поскольку @connexo упоминает, что вам нужно удалить вышеупомянутые или, но если они вам нужны по какой-либо причине: вы можете переопределить глобальный стиль, установив отдельные стили для псевдоэлементов:

 .calculator__screen::after,
.calculator__screen::before {
  display: none;
}

.calculator__keys::after,
.calculator__keys::before {
  display: none;
}
  

 const calculator = () => {
  const doc = document,
    screen = doc.getElementById(`calculator__screen`),
    keys = doc.getElementById(`calculator__keys`);
  let operationStatus = false,
    number1,
    typeOperation;

  screen.textContent = `0`;

  if (!keys) return;
  keys.addEventListener(`click`, (e) => {
    const t = e.target,
      d = t.dataset;

    if (d.number) {
      writeScreen(d.number);
    }

    if (d.math) {
      getOperation(t, d.math);
    }

    if (d.operation) {
      runOperation(d.operation);
    }
  });
  const writeScreen = (number) => {
    screen.textContent === `0` || operationStatus === true ?
      (screen.textContent = number) :
      number === `.` amp;amp; !screen.textContent.includes(`.`) ?
      (screen.textContent  = number) :
      number !== `.` ?
      (screen.textContent  = number) :
      null;
    operationStatus = false;
  };
  const getOperation = (element, operation) => {
    operationStatus = true;
    number1 = Number(screen.textContent);
    typeOperation = operation;
    screen.textContent = element.textContent;
  };
  const runOperation = (operation) => {
    operation === `clear` ?
      (screen.textContent = `0`) :
      getResult(number1, typeOperation);
    operationStatus = true;
  };
  const getResult = (number1, typeOperation) => {
    const number2 = Number(screen.textContent);
    let resu<
    switch (typeOperation) {
      case `add`:
        result = number1   number2;
        break;

      case `minus`:
        result = number1 - number2;
        break;

      case `multiply`:
        result = number1 * number2;
        break;

      case `divide`:
        result = number1 / number2;
        break;
      default:
        break;
    }
    result === Infinity ?
      (screen.textContent = `Error`) :
      (screen.textContent = result);
  };
};

window.addEventListener(`load`, () => {
  calculator();
});  
 /*Variables*/

:root {
  --body-bg: #fbfbfe;
  --black: #000;
  --white: #fff;
}


/*Base*/

*,
*::after,
*::before {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

*::after,
*::before {
  content: "";
}

a {
  text-decoration: none;
}

img {
  display: block;
  max-width: 100%;
}

li,
ol,
ul {
  list-style: none;
}


/*Calculator*/

.calculator {
  margin: 0 auto;
  max-width: 25rem;
  width: 90%;
}

.calculator__screen::after,
.calculator__screen::before {
  display: none;
}

.calculator__keys {
  display: grid;
  grid-gap: 0.25rem;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(5, 1fr);
}

.calculator__keys::after,
.calculator__keys::before {
  display: none;
}

.calculator__keys :first-child {
  height: 0;
  padding-bottom: 100%;
}

.calculator button {
  border: none;
  font-size: 1rem;
}

[data-math="add"],
[data-operation="equals"] {
  grid-row: span 2;
}

[data-number="0"] {
  grid-column: span 2;
}

[data-operation="clear"] {
  grid-column: 1;
  grid-row: 1;
}

.calculator__screen {
  background: rgba(0, 0, 0, 0.8);
  border-radius: 0.25rem;
  color: var(--white);
  margin-bottom: 0.25rem;
  padding: 1rem;
  text-align: right;
}  
 <div class="calculator">
  <div class="calculator__screen" id="calculator__screen">

  </div>
  <div class="calculator__keys" id="calculator__keys">
    <button data-operation="clear">

    </button>
    <button data-operation="clear">
      C
    </button>
    <button data-math="divide">
      /
    </button>
    <button data-math="multiply">
      *
    </button>
    <button data-math="minus">
      -
    </button>
    <button data-number="7">
      7
    </button>
    <button data-number="8">
      8
    </button>
    <button data-number="9">
      9
    </button>
    <button data-math="add">
       
    </button>
    <button data-number="4">
      4
    </button>
    <button data-number="5">
      5
    </button>
    <button data-number="6">
      6
    </button>
    <button data-number="1">
      1
    </button>
    <button data-number="2">
      2
    </button>
    <button data-number="3">
      3
    </button>
    <button data-operation="equals">
      =
    </button>
    <button data-number="0">
      0
    </button>
    <button data-number=".">
      .
    </button>
  </div>
</div>  

Комментарии:

1. Привет, m4n0, прежде всего, спасибо за ваш ответ, я просто применил ваше предложение, и проблема решена, так что большое вам спасибо.

2. @AlessandroReina Рад, что я смог помочь! 🙂

3. Это неправильный подход, особенно потому, что OP использует эти стили псевдоэлементов по совершенно неправильным причинам. Псевдоэлементы должны создаваться только там, где это необходимо, и никогда в глобальном масштабе.

4. @connexo Ты можешь хотя бы сначала прочитать ответ? Да, его подход неверен. Я указал на это. Но что, если он действительно хочет их глобально? Поэтому я предложил ему это. В противном случае ему нужно его удалить. Вот так просто.