0

我正在开发一个应用程序的前端来跟踪比赛。在一个页面中,用户需要通过将玩家从左侧列表中拖动到右侧最终结果表中来更新锦标赛结果,我将发送到 PHP 后端进行处理(我不是在开发后端,只需要通过 POST 发送正确的数据)。我的要求是:

  1. 有一个球员名单
  2. 有一个结果表,每行都有固定的位置(第一行,第二行)。
  3. 每个位置将有 4 个相关输入,全部命名为position-1-NAME,位于同一行但不同的列中
  4. 用户应该能够将玩家拖到每个位置
  5. 一名球员只能在一个位置,每个位置只能有一名球员
  6. 当玩家被放置在桌子上时,他应该从列表中删除

我尝试了几种方法,但最接近的一种方法是使用Dragula JS插件。

然后,我创建了带有 的玩家列表,ul使其id成为 Dragula 中的容器:

 <ul id="players-container">
   <li>
     Player 1
   </li>
 </ul>

然后,我有一个table内部form标签,并且字段的名称都是根据位置命名的,例如position-1-name-of-the-input

<form method="POST" action="file_to_process_form.php">
  <thead>
   <th>Position</th>
   <th>Player</th>
   ...
  </thead>
  <tbody>
     <tr>
       <td>
         1st Position
       </td>           
       <td class="target">
         <input type="text" name="position-1-player-name" value="" hidden>
       </td>
       <td>
         ...other inputs 
       </td>
     </tr>
  </tbody>

然后,在 JavaScript 中,我做了一个 hack,text()li被拖动的对象中抓取 并将其放在 的value属性中inputtable这样我就可以将第一个位置的玩家名称发送到后端。编码:

dragula([document.querySelector('#players-container'), document.querySelector('.target')], {
  isContainer: function(el){
    return el.classList.contains('target');
  },
  revertOnSpill: true
}).on('drop', function(el, target, source, sibling){
  elValue = $(el).text();
  $(target).find('input').attr('value', elValue);
});

到目前为止,这正在处理一些错误:

  1. 我可以在同一个中放置两个播放器td,它们将在 UI 中显示两者都被拖动li,但表单将只有最后放置的播放器的值。

  2. 如果我将玩家一个接一个地拖到所有位置,所有输入都将具有他的名字的值,直到我将另一个玩家拖到该位置为止。

所以,我想完成几件事:

  1. 每个里面只允许一名玩家td class="target"。我试图td通过删除.target类来禁用它,但是在被丢弃后我无法再次移动播放器。

  2. 当我将播放器拖出时,删除输入的值。

我知道这有点小技巧,但我对 JS/jQuery 没有太多经验,这是迄今为止唯一可以远程工作的解决方案。

我的问题:

  1. 如何防止td使用 Dragula 或 JS / jQuery 代码将多个玩家表单拖到同一个?

  2. [已解决-见编辑]当我将播放器拖出时value如何删除?inputtd

  3. 你知道一个更好的方法来实现这些要求来推荐吗?

编辑

我通过添加以下代码设法解决了问题 2:

dragulaObject.on('drag', function(el, source) {
   $(source).find('input').attr('value', '');
});
4

1 回答 1

0

因此,在我发布问题后,我设法破解了错误/问题 1 和 2 的一些解决方案:

为了防止多个玩家在同一个位置上,我在 Dragula 对象初始化的选项中添加了以下代码:

accepts: function(el, target, source, sibling) {
    if($(target).attr('class') == 'target' && $(target).find('li').length <= 1) {
      return true;
    } else {
      return false;
    }
  }

第一个条件是允许玩家在被放置在一个位置后被拖回列表,因为列表包含多个 1 li,如果没有第一个条件,返回列表拖动将无效。

仍然存在一些动画错误(被拖动的玩家与另一个玩家短暂显示在位置内,但拖放时未完成拖动)。

为了解决错误/问题 2,我添加了以下代码(与原始答案中编辑的相同):

dragulaObject.on('drag', function(el, source) {
   $(source).find('input').attr('value', '');
});

因此,Dragula 对象的完整代码是:

  dragula([document.querySelector('#players-container'), document.querySelector('.target')], {
      isContainer: function(el){
        return el.classList.contains('target');
      },
      revertOnSpill: true,
      accepts: function(el, target, source, sibling) {
        if($(source).attr('class') == 'target' || $(target).find('li').length <= 1) {
          return true;
        } else {
          return false;
        }
      }
  }).on('drop', function(el, target, source, sibling){
    elValue = $(el).text();
    $(target).find('input').attr('value', elValue);
  }).on('drag', function(el, source) {
    $(source).find('input').attr('value', '');
  });

不是最漂亮的代码,但它确实解决了问题。希望它可以帮助其他尝试做类似事情的人。

于 2016-03-07T20:24:38.237 回答