问题转到Ajax

时间:2016-12-14 20:45:21

标签: jquery ajax

我正在研究一些jQuery,以检查表中的单元格是否已被编辑。如果有,则修订通过ajax发送回数据库。我正在使用超时延迟为用户提供2500毫秒的击键次数以进行全面校正并在完成时捕获。如果他们点击html表中的其他td,我也会使用模糊绕过超时延迟。一旦ajax完成,我添加一个"已保存的" class td并在if语句中包含ajax,这样只有在"保存"时才会出现ajax。上课没有。这只允许ajax发生一次。

我的问题:如果更改了某个号码并立即点击了其他td并且用户开始输入,则之前的更改永远不会将其设置为ajax,因此它永远不会保存到数据库。 1毫秒计时器使得看起来似乎没有可能发生这种情况,但某些事情必然会以某种方式减慢它。

我的问题:为什么会发生这种情况,我该如何解决?

旁注: toastr代码也停止了工作,我不确定原因。

$('td').on('input blur', function(e) {

    var timeoutDelay=2500;

    if( e.type == "blur"){
        timeoutDelay=1;
    }

    // If NOT already saved...
    if( !$(this).hasClass("saved") ){
        var _this = $(this); // preserve reference to the input field here

        clearTimeout(saveTimeout);
        saveTimeout = setTimeout(function() {
            console.log(_this)
            $.ajax({
                method: "POST",
                url: "updatedatabase.php",
                data: { 
                    content: _this.text(), 
                    date: _this.siblings().first().text(),
                    prod: $('tr:first-child th:nth-child(' + (_this.index() + 1) + ')').text(),
                    old: old
                }
            })
            .done(function( msg ) {
                alert( msg );
                // Add the "saved" class to prevent other saving
                _this.addClass("saved");
            });

            toastr.options = {
                "positionClass": "toast-top-center",
                "onclick": null,
                "timeOut": "2500",
            }

            toastr.info(old,'Database Updated!<br><br>Your Previous Amount Was:');

            _this.prop('contenteditable', false);

        }, timeoutDelay);
    }
});

&#13;
&#13;
$(document).ready(function () {

    var old;
            
    $('td').click(function(){
                
        old=$(this).text();
                
        $(this).prop('contenteditable', true);
                
                
    });
            
    var saveTimeout;
            
    // Remove the "saved" class on keydown
    $('td').on('keydown', function(e) {
        $(this).removeClass("saved");
    });
    
    $('td').on('input blur', function(e) {
                                
        var timeoutDelay=2500;
               
        if( e.type == "blur"){
            timeoutDelay=1;
        }
                
        // If NOT already saved...
        if( !$(this).hasClass("saved") ){
            var _this = $(this); // preserve reference to the input field here
            
            // Add the "saved" class to prevent other saving
            _this.addClass("saved");
            
            clearTimeout(saveTimeout);
            saveTimeout = setTimeout(function() {
                console.log(_this)
                $.ajax({
                    method: "POST",
                    url: "updatedatabase.php",
                    data: { 
                        content: _this.text(), 
                        date: _this.siblings().first().text(),
                        prod: $('tr:first-child th:nth-child(' + (_this.index() + 1) + ')').text(),
                        old: old
                    }
                })
                .done(function( msg ) {
                    alert( msg );
                });

                toastr.options = {
                    "positionClass": "toast-top-center",
                    "onclick": null,
                    "timeOut": "2500",
                }

                toastr.info(old,'Database Updated!<br><br>Your Previous Amount Was:');
                        
                _this.prop('contenteditable', false);
                        
            }, timeoutDelay);
        }
    });
            
            
    $("td").hover(function(){
                                
                
                    
        $(this).addClass('highlight').siblings().first().addClass('highlight');

        $('tr:eq(1) th:eq('+$(this).index()+')').addClass('highlight');
                
                
    },function(){
                
                
                    
        $(this).removeClass("highlight").siblings().first().removeClass('highlight');

        $('tr:eq(1) th:eq('+$(this).index()+')').removeClass('highlight');
                
                
    });
    
}); 
&#13;
table,th, td {
  
    border: 1px solid black;
    border-collapse: collapse;
        
}

.highlight {
    
    background-color:#E0E0E0;
    color: blue;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/1.3.1/css/toastr.css" rel="stylesheet"/> 
        <script src="http://cdnjs.cloudflare.com/ajax/libs/toastr.js/1.3.1/js/toastr.js"></script>
<table>
  <tr>
    <th>Item #</th>
    <th>1234567</th>
    <th>7654321</th>
    <th>5678945</th>
  </tr>
  <tr>
    <th>Product</th>
    <th><u>22 ounce Dark</u></th>
    <th><u>12count 4oz Dark</u></th>
    <th><u>24count 6oz TJ</u></th>
  </tr>
  <tr>
    <th>2016-01-03</th>
    <td>13587</td>
    <td>2203</td>
    <td>4111</td>
  </tr>
  <tr>
    <th>2016-01-04</th>
    <td>14111</td>
    <td>3247</td>
    <td>4332</td>
  </tr>
  <tr>
    <th>2016-01-05</th>
    <td>13212</td>
    <td>3101</td>
    <td>3911</td>
  </tr>
  <tr>
    <th>2016-01-06</th>
    <td>16335</td>
    <td>3299</td>
    <td>4001</td>
  </tr>
  <tr>
    <th>2016-01-07</th>
    <td>15421</td>
    <td>3100</td>
    <td>4078</td>
  </tr>
</table>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

每当调用$('td').on('input blur', function(e) {事件处理程序时,都会清除超时引用saveTimeout,并且永远不会调用先前的超时。解决方案是每个td都有一个超时参考。

这里没有检查草稿

if ( _this.saveTimeout )
    clearTimeout(_this.saveTimeout);
_this.saveTimeout = setTimeout(function { ........  

等等。

<强> CORRECTED:

clearTimeout(_this.data('saveTimeout'));
_this.data('saveTimeout', setTimeout(function() {
     console.log("Saving " + _this.text()) + "...";
     ...
}, timeoutDelay));

答案 1 :(得分:0)

以下是事件的顺序:

  1. 获得input事件的第一个单元格中的用户类型。
  2. 调用的事件处理程序:此单元格的td没有类saved,因此if (!$(this).hasClass("saved"))的分支被占用。
  3. 课程saved已添加到td
  4. 设置新超时并保存在saveTimeout中。我们称之为超时,超时A。
  5. 用户点击第二个单元格:第一个单元格获得blur事件。
  6. 调用的事件处理程序:此单元格的<{1}} 仍然具有类td ,因此不会执行分支,也不会设置新的超时。< / strong>唯一仍然有效的超时是超时A.
  7. 第二个单元格中的用户类型,它会获得saved个事件。
  8. 调用事件处理程序:此第二个单元格的input没有td类,因此分支被占用。
  9. 处理程序在saved中找到超时A并取消它。它设置新的超时以在第二个单元格中保存更改。
  10. 好的,所以我使用了你的代码片段并对其进行了一些修改。您的代码段发出了错误,因为没有加载toastr,并且没有任何东西可以接收AJAX,而且这个代码段遭受同样的问题。但是,它可以用来说明解决方案。我做的是:

    1. 如果偶数为saveTimeout,则即使存在blur类,也会强制设置新超时。

    2. 超时在DOM元素本身上保存。我之前已经在其他环境中完成了这项工作,并且我已经在多个浏览器中进行了测试,并且工作正常。但是,您可能会定位我不使用的浏览器。如果此方法使您可以使用任何允许基于DOM元素检索已保存超时的方法替换它。您可以使用元素ID查看从id到timeout的映射,或者使用what-have-you。使用任何让你感到舒服的东西。

    3. 根据我所做的更改,我可以在日志中看到第一个单元格的保存请求被触发,第二个单元格的不同请求也会触发。

      saved
      $(document).ready(function () {
      
          var old;
                  
          $('td').click(function(){
                      
              old=$(this).text();
                      
              $(this).prop('contenteditable', true);
                      
                      
          });
                          
          // Remove the "saved" class on keydown
          $('td').on('keydown', function(e) {
              console.log("remove");
              $(this).removeClass("saved");
          });
          
          $('td').on('input blur', function(e) {
                                      
              var timeoutDelay=2500;
                     
              if( e.type == "blur"){
                  timeoutDelay=1;
              }
                      
              // If NOT already saved... or if it is a blur
              if( !$(this).hasClass("saved") || e.type === "blur" ){
                  var _this = $(this); // preserve reference to the input field here
                  
                  // Add the "saved" class to prevent other saving
                  _this.addClass("saved");
                  
                  console.log("setting new timeout");
                  if (this.saveTimeout) {
                      clearTimeout(this.saveTimeout);
                      this.saveTimeout = null;
                  }
                  this.saveTimeout = setTimeout(function() {
                      console.log("timeout", _this.text());
                      $.ajax({
                          method: "POST",
                          url: "updatedatabase.php",
                          data: { 
                              content: _this.text(), 
                              date: _this.siblings().first().text(),
                              prod: $('tr:first-child th:nth-child(' + (_this.index() + 1) + ')').text(),
                              old: old
                          }
                      })
                      .done(function( msg ) {
                          alert( msg );
                      });
      
                      toastr.options = {
                          "positionClass": "toast-top-center",
                          "onclick": null,
                          "timeOut": "2500",
                      }
      
                      toastr.info(old,'Database Updated!<br><br>Your Previous Amount Was:');
                              
                      _this.prop('contenteditable', false);
                              
                  }, timeoutDelay);
              }
          });
                  
                  
          $("td").hover(function(){
                                      
                      
                          
              $(this).addClass('highlight').siblings().first().addClass('highlight');
      
              $('tr:eq(1) th:eq('+$(this).index()+')').addClass('highlight');
                      
                      
          },function(){
                      
                      
                          
              $(this).removeClass("highlight").siblings().first().removeClass('highlight');
      
              $('tr:eq(1) th:eq('+$(this).index()+')').removeClass('highlight');
                      
                      
          });
          
      });
      table,th, td {
        
          border: 1px solid black;
          border-collapse: collapse;
              
      }
      
      .highlight {
          
          background-color:#E0E0E0;
          color: blue;
      }