JavaScript Todo列表 - 当我点击“编辑”时按钮,它选择了错误的文字输入,但仍然编辑了正确的项

时间:2017-06-22 20:26:27

标签: javascript html



const todoList = {
  todos: [],

  addTodo: function(todoText) {
    this.todos.push({
      todoText: todoText,
      completed: false
    });
    view.displayTodos();
  },

  changeTodo: function(position, newTodoText) {
    this.todos[position].todoText = newTodoText;
    view.displayTodos();
  },

  deleteTodo: function(position) {
    this.todos.splice(position, 1);
    view.displayTodos();
  },

  toggleCompleted: function(position) {
    let todo = this.todos[position];
    todo.completed = !todo.completed;
  },

  toggleAll: function() {
    const allTodos = this.todos.length;
    let completedTodos = 0;

    for (let i = 0; i < allTodos; i++) {
      if (this.todos[i].completed === true) {
        completedTodos++;
      }
    }

    if (completedTodos === allTodos) {
      for (let i = 0; i < allTodos; i++) {
        this.todos[i].completed = false;
      }
    } else {
      for (let i = 0; i < allTodos; i++) {
        this.todos[i].completed = true;
      }
    }

    view.displayTodos();
  }
};

const handlers = {
  toggleAll: function() {
    todoList.toggleAll();
  },

  addTodo: function(e) {
    if (e.keyCode === 13) {
      e.preventDefault(); // Ensure it is only this code that rusn
      let todoTextInput = document.getElementById('todoTextInput');
      todoList.addTodo(todoTextInput.value);
      todoTextInput.value = '';
    }
  },

  deleteTodo: function(position) {
    todoList.deleteTodo(position);
  }
};

const view = {

  displayTodos: function() {
    let todosUl = document.getElementById('todoList');
    todosUl.innerHTML = '';

    for (let i = 0; i < todoList.todos.length; i++) {
      let todoLi = document.createElement('li');
      let todoLiText = document.createElement('input');
      todoLiText.type = "text";
      todoLiText.disabled = true;
      todoLiText.id = 'textInput';
      let todoTextWithCompletion = todoList.todos[i].todoText;;
      let check = document.createElement('input');
      check.type = "checkbox";
      check.id = "checkbox";
      check.className = "checkbox";
      check.checked = '';

      todoLi.id = i;
      todoLiText.value = todoTextWithCompletion;
      todoLi.appendChild(check);
      todoLi.appendChild(todoLiText);
      todoLi.appendChild(this.createDeleteButton());
      todoLi.appendChild(this.createEditButton());
      todosUl.appendChild(todoLi);

      if (document.getElementById('checkbox').checked === true) {
        todoList.toggleCompleted(i);
      };
      if (todoList.todos[i].completed === true) {
        todoLiText.style.textDecoration = "line-through";
      };

    }
  },

  createDeleteButton: function() {
    let deleteButton = document.createElement('a');
    deleteButton.href = "#";
    deleteButton.textContent = "Delete";
    deleteButton.className = 'x';
    return deleteButton;
  },

  createEditButton: function() {
    let editButton = document.createElement('a');
    editButton.href = "#";
    editButton.textContent = "edit";
    editButton.className = 'edit';
    return editButton;
  },

  setUpEventListeners: function() {
    let todosUl = document.getElementById('todoList');

    todosUl.addEventListener('click', (event) => {
      let elementClicked = event.target;

      if (elementClicked.className === 'x') {
        handlers.deleteTodo(parseInt(elementClicked.parentNode.id));
      };
    });

    // Edit List Item
    todosUl.addEventListener('click', (event) => {
      let elementClicked = event.target;
      let position = elementClicked.parentNode.id;

      if (elementClicked.className === 'edit') {
        let input = document.getElementById('textInput');

        input.disabled = false;
        input.className += " activeTextInput ";

        input.focus();
        input.select();

        input.addEventListener('keyup', (event) => {
          let elementClicked = event.target;

          if (event.keyCode === 13) {
            let textInput = input.value;
            input.disabled = true;
            input.classList.remove("activeTextInput");
            todoList.changeTodo(position, textInput);
          };
        });
      };
    });

    // Line through on check
    todosUl.addEventListener('click', (event) => {
      let elementClicked = event.target;
      let position = elementClicked.parentNode.id;
      let check = document.getElementById('checkbox');

      if (elementClicked.className === 'checkbox') {
        todoList.toggleCompleted(position);
        check.checked = true;
      };
    });

    //Delete All
    let clearAll = document.getElementById('clearAll');

    clearAll.addEventListener('click', (event) => {
      todoList.todos.splice(0, todoList.todos.length);
      view.displayTodos();
    });

    // TODO Delete Selected

  }
};

view.setUpEventListeners();
&#13;
html,
body {
  margin: 0;
  height: 100%;
}

body {
  background-color: #eeeeee !important;
}

h1 {
  color: #282845 !important;
}

p {
  opacity: .3;
}

.container {
  min-height: 70%;
  display: flex;
  justify-content: center;
  flex-direction: column;
  width: 50% !important;
}

#todoTextInput {
  background-color: white;
  opacity: .7;
  box-shadow: 1px 1px 10px rgba(5, 5, 5, 0.2);
  height: 50px;
  padding: 10px;
  border: none;
  font-style: italic;
}

ul {
  display: flex;
  flex-direction: column;
  padding: 0;
  margin: 0;
}

li {
  list-style-type: none !important;
  border-bottom: 1px solid rgba(5, 5, 5, 0.1);
  padding: 10px;
  background-color: white;
  box-shadow: 1px 1px 10px rgba(5, 5, 5, 0.2);
  min-width: inherit;
}

li a {
  float: right;
  padding-right: 10px;
  opacity: .3 !important;
  transition: .2s;
}

li a:hover {
  opacity: 1 !important;
}

input {
  border: none;
  border-bottom: 1px solid rgba(5, 5, 5, 0..01);
  background-color: inherit;
}

li input[type="text"] {
  padding: none;
  border: none;
  width: 80%;
  margin-left: 10px;
  transition: .5s;
}

.activeTextInput {
  box-shadow: 1px 1px 10px rgba(5, 5, 5, 0.1);
  padding: 10px !important;
}

input[type="text"] {
  background-color: inherit;
  border: none;
  border-bottom: 1px solid rgba(5, 5, 5, 0.01);
  padding: 0;
}

input:focus {
  outline: none;
}

input:checked+input[type="text"] {
  text-decoration: line-through;
  opacity: .5;
}

.btn {
  background-color: white !important;
  border-radius: 0 !important;
  padding: 0;
  box-shadow: 1px 1px 10px rgba(5, 5, 5, 0.2);
  margin-top: -2px !important;
  font-style: italic;
  opacity: 0.5;
}

#clearAll {
  margin-top: -21px !important;
}

.hidden {
  display: none !important;
  background-color: red !important;
}
&#13;
<link href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css" rel="stylesheet" />

<body>
  <div class="container">
    <h1 class="text-center">List+</h1>

    <div class="row list-head">
      <div class="col-md-12">
        <input type="text" placeholder="Enter a List Item" style="width: 100%" id="todoTextInput" onkeyup="handlers.addTodo(event)">
      </div>
    </div>

    <div class="row list-container">
      <div class="col-md-12">
        <ul id="todoList">

        </ul>
      </div>

    </div>
    <div class="row">
      <div class="col-md-12">
        <button class="btn" style="width: 100%" id="clearAll">Clear All</button>
        <button class="btn" style="width: 100%">Clear Selected</button>
      </div>
    </div>
    <div class="row">
      <div class="col-md-12">
        <p class="text-center"><i>Created by Connor Beam</i></p>
      </div>
    </div>
  </div>

  <script src="js/main.js"></script>
</body>
&#13;
&#13;
&#13;

我正在使用vanilla JavaScript构建待办事项列表。我试着去编辑&#39;选项正常运行。当我点击&#39;编辑&#39;按钮,应启用相应的文本输入,并自动选择,然后用户应该可以按“输入”键。提交更改。

然而,无论哪个&#39;编辑&#39;单击按钮,始终选择第一个文本输入,同时在提交时仍更改正确的项目。

这是指向最新版本的工作链接:http://vanillajstodo.surge.sh/

我认为问题在于所有&#t;游戏文本&#39;正在创建具有相同ID的输入;但是,我不确定如何解决这个问题。

如果需要更多信息,请告诉我。

由于

1 个答案:

答案 0 :(得分:1)

看看这个解决方案:

https://codepen.io/anon/pen/YQQovp?editors=1010

let input = document.getElementById(position).childNodes[1];

您的错误是您不应该在同一页面上拥有多个具有相同ID的元素。相反,你应该在那种情况下使用相同的类。