Как включить кнопки? (проблема с логикой?)

В настоящее время у меня есть программа с некоторыми командами, которые играют в парах. Нажатие на команду увеличивает выигрыши выбранной команды и увеличивает проигрыши пары, с которой она связана. Команда с двумя поражениями отключается и меняет текст на «Выбыла».

У меня есть кнопка сброса, которая должна очищать все счетчики, и теоретически при очистке счетчиков отключенные кнопки должны снова включиться. Однако это не так: они остаются отключенными, а их текст снова переключается на название команды. Как сохранить кнопки включенными после сброса?

Любой вклад будет принят с благодарностью :)

let groups = [{
    name: "Chaos Coordinators",
    wins: 0,
    losses: 0
  },
  {
    name: "Sofa King Awesome",
    wins: 0,
    losses: 0
  },
  {
    name: "The Nerd Herd",
    wins: 0,
    losses: 0
  },
  {
    name: "The Laughing Stock",
    wins: 0,
    losses: 0
  },
  {
    name: "Brainy Bunch Gone Wild",
    wins: 0,
    losses: 0
  },
  {
    name: "Cereal Killers",
    wins: 0,
    losses: 0
  },
  {
    name: "The Mismatched Socks",
    wins: 0,
    losses: 0
  },
  {
    name: "The Awkward Turtles",
    wins: 0,
    losses: 0
  }
];


// Create pairs from the groups
function makeMatches(array) {
  return array.map((_, i) => (i % 2 === 0) ? [array[i], array[i + 1]] : []).filter(v => v.length === 2);
}

let matches = makeMatches(groups);

// Create a map of team names to their index
const groupIndexMap = {};
groups.forEach((group, index) => {
  groupIndexMap[group.name] = index;
});

// Function to handle button clicks
function handleButtonClick(groupName) {
  const matchIndex = groupIndexMap[groupName];
  const match = matches.find(match => match.some(group => group.name === groupName));


  if (!match) return;

  match.forEach((group, button) => {
    if (group.name === groupName) {
      group.wins += 1;
    } else if (group.losses < 2) {
      group.losses += 1;
    }
  });

  updateButtonTexts();
  console.info(groups);
}

// Function to update button texts
function updateButtonTexts() {
  groups.forEach((group, index) => {
    const button = document.getElementById(`button${index + 1}`);
    if (button) {
      button.textContent = `${group.name} - Wins: ${group.wins} - Losses: ${group.losses}`;
    }
    if (group.losses == 2) {
      button.textContent = 'Eliminated';
      button.disabled = true;
    }
  });
}

// Function to reset all counters
function resetCounters() {
  groups.forEach(group => {
    group.wins = 0;
    group.losses = 0;
  });
  updateButtonTexts();
}


// Initialize button click handlers
function initializeButtons() {
  groups.forEach((group) => {
    const button = document.querySelector(`[data-team-name='${group.name}']`);
    if (button) {
      button.onclick = () => handleButtonClick(group.name);
    }
  });

  // Initialize reset button handler
  document.getElementById('resetButton').onclick = resetCounters;

  // Initial update of button texts
  updateButtonTexts();
}

// Initial render and setup
initializeButtons();
#group-buttons {
  position: relative;
  /* Container should be relative for positioning buttons absolutely */
  width: 100%;
  height: 500px;
  /* Adjust height as needed */
  border: 1px solid #ccc;
}

.group-button {
  position: absolute;
  /* Allows for free positioning */
  cursor: pointer;
  /* Indicates the element is clickable */
  padding: 10px;
  background: #f0f0f0;
  border: 1px solid #ddd;
  border-radius: 5px;
}


/* Example styles for individual buttons */

#button1 {
  top: 50px;
  left: 50px;
}

#button2 {
  top: 50px;
  left: 200px;
}

#button3 {
  top: 150px;
  left: 50px;
}

#button4 {
  top: 150px;
  left: 200px;
}

#button5 {
  top: 250px;
  left: 50px;
}

#button6 {
  top: 250px;
  left: 200px;
}

#button7 {
  top: 350px;
  left: 50px;
}

#button8 {
  top: 350px;
  left: 200px;
}
<button id = "resetButton">Reset All Counters</button>
<div id = "group-buttons">
  <button id = "button1" class = "group-button" data-team-name = "Chaos Coordinators">Chaos Coordinators - Wins: 0 - Losses: 0</button>
  <button id = "button2" class = "group-button" data-team-name = "Sofa King Awesome">Sofa King Awesome - Wins: 0 - Losses: 0</button>
  <button id = "button3" class = "group-button" data-team-name = "The Nerd Herd">The Nerd Herd - Wins: 0 - Losses: 0</button>
  <button id = "button4" class = "group-button" data-team-name = "The Laughing Stock">The Laughing Stock - Wins: 0 - Losses: 0</button>
  <button id = "button5" class = "group-button" data-team-name = "Brainy Bunch Gone Wild">Brainy Bunch Gone Wild - Wins: 0 - Losses: 0</button>
  <button id = "button6" class = "group-button" data-team-name = "Cereal Killers">Cereal Killers - Wins: 0 - Losses: 0</button>
  <button id = "button7" class = "group-button" data-team-name = "The Mismatched Socks">The Mismatched Socks - Wins: 0 - Losses: 0</button>
  <button id = "button8" class = "group-button" data-team-name = "The Awkward Turtles">The Awkward Turtles - Wins: 0 - Losses: 0</button>
</div>

Кажется, в вашем фрагменте все работает нормально.

Pointy 01.08.2024 22:35

Никогда не делайте button.disabled = false повторное включение кнопок при сбросе счетчиков.

Barmar 01.08.2024 22:35

Кстати, if (group.losses == 2) должно быть внутри if (button). В противном случае вы попытаетесь получить доступ к свойствам несуществующей кнопки.

Barmar 01.08.2024 22:38

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

Barmar 01.08.2024 22:41

Я написал заголовок таким образом, потому что думал, что проблема в счетчиках :) (если счетчики не сбрасывались, кнопка оставалась отключенной, это то, что я понял, наблюдая за консолью, потому что, если вы внимательно посмотрите, когда вы получите до двух потерь на кнопке и сброса, тогда две потери не исчезают, что, как я думал, могло удерживать его в отключенном состоянии :)

Jazzwal 01.08.2024 22:50
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
5
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам нужно установить button.disabled = true;, когда потери будут меньше 2. Это снова включит кнопку при сбросе счетчиков.

function updateButtonTexts() {
  groups.forEach((group, index) => {
    const button = document.getElementById(`button${index + 1}`);
    if (button) {
      button.textContent = `${group.name} - Wins: ${group.wins} - Losses: ${group.losses}`;
      if (group.losses == 2) {
        button.textContent = 'Eliminated';
        button.disabled = true;
      } else {
        button.disabled = false;
      }
    }
  });
}

let groups = [{
    name: "Chaos Coordinators",
    wins: 0,
    losses: 0
  },
  {
    name: "Sofa King Awesome",
    wins: 0,
    losses: 0
  },
  {
    name: "The Nerd Herd",
    wins: 0,
    losses: 0
  },
  {
    name: "The Laughing Stock",
    wins: 0,
    losses: 0
  },
  {
    name: "Brainy Bunch Gone Wild",
    wins: 0,
    losses: 0
  },
  {
    name: "Cereal Killers",
    wins: 0,
    losses: 0
  },
  {
    name: "The Mismatched Socks",
    wins: 0,
    losses: 0
  },
  {
    name: "The Awkward Turtles",
    wins: 0,
    losses: 0
  }
];


// Create pairs from the groups
function makeMatches(array) {
  return array.map((_, i) => (i % 2 === 0) ? [array[i], array[i + 1]] : []).filter(v => v.length === 2);
}

let matches = makeMatches(groups);

// Create a map of team names to their index
const groupIndexMap = {};
groups.forEach((group, index) => {
  groupIndexMap[group.name] = index;
});

// Function to handle button clicks
function handleButtonClick(groupName) {
  const matchIndex = groupIndexMap[groupName];
  const match = matches.find(match => match.some(group => group.name === groupName));


  if (!match) return;

  match.forEach((group, button) => {
    if (group.name === groupName) {
      group.wins += 1;
    } else if (group.losses < 2) {
      group.losses += 1;
    }
  });

  updateButtonTexts();
  //console.info(groups);
}

// Function to update button texts
function updateButtonTexts() {
  groups.forEach((group, index) => {
    const button = document.getElementById(`button${index + 1}`);
    if (button) {
      button.textContent = `${group.name} - Wins: ${group.wins} - Losses: ${group.losses}`;
      if (group.losses == 2) {
        button.textContent = 'Eliminated';
        button.disabled = true;
      } else {
        button.disabled = false;
      }
    }
  });
}

// Function to reset all counters
function resetCounters() {
  groups.forEach(group => {
    group.wins = 0;
    group.losses = 0;
  });
  updateButtonTexts();
}


// Initialize button click handlers
function initializeButtons() {
  groups.forEach((group) => {
    const button = document.querySelector(`[data-team-name='${group.name}']`);
    if (button) {
      button.onclick = () => handleButtonClick(group.name);
    }
  });

  // Initialize reset button handler
  document.getElementById('resetButton').onclick = resetCounters;

  // Initial update of button texts
  updateButtonTexts();
}

// Initial render and setup
initializeButtons();
#group-buttons {
  position: relative;
  /* Container should be relative for positioning buttons absolutely */
  width: 100%;
  height: 500px;
  /* Adjust height as needed */
  border: 1px solid #ccc;
}

.group-button {
  position: absolute;
  /* Allows for free positioning */
  cursor: pointer;
  /* Indicates the element is clickable */
  padding: 10px;
  background: #f0f0f0;
  border: 1px solid #ddd;
  border-radius: 5px;
}


/* Example styles for individual buttons */

#button1 {
  top: 50px;
  left: 50px;
}

#button2 {
  top: 50px;
  left: 200px;
}

#button3 {
  top: 150px;
  left: 50px;
}

#button4 {
  top: 150px;
  left: 200px;
}

#button5 {
  top: 250px;
  left: 50px;
}

#button6 {
  top: 250px;
  left: 200px;
}

#button7 {
  top: 350px;
  left: 50px;
}

#button8 {
  top: 350px;
  left: 200px;
}
<button id = "resetButton">Reset All Counters</button>
<div id = "group-buttons">
  <button id = "button1" class = "group-button" data-team-name = "Chaos Coordinators">Chaos Coordinators - Wins: 0 - Losses: 0</button>
  <button id = "button2" class = "group-button" data-team-name = "Sofa King Awesome">Sofa King Awesome - Wins: 0 - Losses: 0</button>
  <button id = "button3" class = "group-button" data-team-name = "The Nerd Herd">The Nerd Herd - Wins: 0 - Losses: 0</button>
  <button id = "button4" class = "group-button" data-team-name = "The Laughing Stock">The Laughing Stock - Wins: 0 - Losses: 0</button>
  <button id = "button5" class = "group-button" data-team-name = "Brainy Bunch Gone Wild">Brainy Bunch Gone Wild - Wins: 0 - Losses: 0</button>
  <button id = "button6" class = "group-button" data-team-name = "Cereal Killers">Cereal Killers - Wins: 0 - Losses: 0</button>
  <button id = "button7" class = "group-button" data-team-name = "The Mismatched Socks">The Mismatched Socks - Wins: 0 - Losses: 0</button>
  <button id = "button8" class = "group-button" data-team-name = "The Awkward Turtles">The Awkward Turtles - Wins: 0 - Losses: 0</button>
</div>

Я попробовал это, но кнопка по-прежнему неактивна после нажатия кнопки сброса :)

Jazzwal 01.08.2024 22:52

Я предполагаю, что это потому, что счетчик не обнулился :)

Jazzwal 01.08.2024 23:02

У меня была опечатка, disable должно быть disabled.

Barmar 01.08.2024 23:05

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

Barmar 01.08.2024 23:05

ох, круто, спасибо

Jazzwal 01.08.2024 23:08

Я предположил это, наблюдая за консолью :)

Jazzwal 01.08.2024 23:11

счетчики не начинают отсчет с нуля до тех пор, пока вы не нажмете кнопку, поэтому я думал, что они не включатся снова, пока не будут нажаты - чего они не могли, потому что они были отключены

Jazzwal 01.08.2024 23:11

Спасибо большое за вашу помощь :)

Jazzwal 01.08.2024 23:11

Используйте свойство HTMLButtonElement.disabled, которому присвоено логическое значение.


Ваш код кажется слишком сложным, и есть некоторые нерешенные проблемы:

  • Вместо создания массива с парами используйте другую стратегию: связанные узлы графа. Каждый (клонированный) Объект команды будет иметь свойство opponent, указывающее на команду противника и наоборот.
  • отключить обе кнопки не только на проигравшей стороне.
  • создайте структурированный клон, чтобы не загрязнять исходные данные - таким образом вам не нужно делать тяжелые сбросы - просто повторно используйте исходные исходные данные.
  • предварительно заполненный HTML не требуется, кнопки создавайте динамически!

Упрощенный пример:

// Data
const groups = [ {name: "Chaos Coordinators", wins: 0, losses: 0}, {name: "Sofa King Awesome", wins: 0, losses: 0}, {name: "The Nerd Herd", wins: 0, losses: 0}, {name: "The Laughing Stock", wins: 0, losses: 0}, {name: "Brainy Bunch Gone Wild", wins: 0, losses: 0}, {name: "Cereal Killers", wins: 0, losses: 0}, {name: "The Mismatched Socks", wins: 0, losses: 0}, {name: "The Awkward Turtles", wins: 0, losses: 0}];

// DOM helpers 
const el = (sel, par = document) => par.querySelector(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);

// App
const max = 2; // Max losses. SET AS DESIRED
const elGroupButtons = el("#group-buttons");

const updateButton = (team) => {
  const text = team.losses === max ? "Eliminated" : `Wins: ${team.wins} - Losses: ${team.losses}`;
  team.button.textContent = `${team.name} - ${text}`;
  team.button.disabled = team.losses === max || team.opponent.losses === max;
  team.button.classList.toggle("is-eliminated", team.losses === max);
};

const updateScore = (team, score = 1) => {
  team.wins += score;
  team.opponent.losses += score;
  updateButton(team);
  updateButton(team.opponent);
};

const makeMatches = (array) => {
  elGroupButtons.innerHTML = ""; // Cleanup
  // Let's clone data and recreate the buttons
  structuredClone(array).forEach((team, i, teams) => {
    team.opponent = teams[i + (i % 2 === 0 ? 1 : -1)];
    team.button = elNew("button", {
      className: "group-button",
      onclick() { updateScore(team); }
    });
    updateButton(team); // Initial button text
    elGroupButtons.append(team.button);
  });
};

// Init and Reset event
const matches = makeMatches(groups);
el("#resetButton").addEventListener("click", () => makeMatches(groups));
/*QuickReset*/ * { margin: 0; box-sizing: border-box; }

#group-buttons {
  position: relative;
  border: 1px solid #888;
  display: flex;
  flex-flow: row wrap;
  padding: 0.5em;
  gap: 0.5em;
  
  & .group-button {
    flex: 0 0 calc(50% - 0.3em);
    padding: 1em;

    &.is-eliminated {
      color: #f008;
    }
  }
}
<button id = "resetButton">RESET</button>
<div id = "group-buttons"></div>

Другие вопросы по теме