【问题标题】:How can I make my Javascript always submit properly?如何让我的 Javascript 始终正确提交?
【发布时间】:2015-07-06 10:56:28
【问题描述】:

我有一个 .php 文件,其中包含一些调用画布绘制的 javascript,在提交表单时将上传画布绘制图像并将 SQL 数据提交到数据库。 100% 的时间将上传 SQL 数据。我的问题是javascript不会总是上传。我的浏览器是 iPad 上的移动 Safari。任何帮助将不胜感激。下面是捕获图像的文件。然后将其上传到upload_data.php。我正在使用 codeigniter 框架。

 <!DOCTYPE html>
 <html lang="en">
 <head>
 <meta charset="utf-8" />
 <title>Trailer Draw</title>

 <script src="http://code.createjs.com/easeljs-0.5.0.min.js"></script> 
 <script src="http://code.jquery.com/jquery-1.8.2.js"></script>
 <script type="text/javascript">
  $(document).ready(function () {
     initialize();
  });


  // works out the X, Y position of the click inside the canvas from the X, Y     position on the page
  function getPosition(mouseEvent, sigCanvas) {
     var x, y;
     if (mouseEvent.pageX != undefined && mouseEvent.pageY != undefined) {
        x = mouseEvent.pageX;
        y = mouseEvent.pageY;
     } else {
        x = mouseEvent.clientX + document.body.scrollLeft +  document.documentElement.scrollLeft;
        y = mouseEvent.clientY + document.body.scrollTop +  document.documentElement.scrollTop;
     }

     return { X: x - sigCanvas.offsetLeft, Y: y - sigCanvas.offsetTop };
  }

  function initialize(canvas, context, onload) {
     // get references to the canvas element as well as the 2D drawing context
     var sigCanvas = document.getElementById("canvasSignature");
     var context = sigCanvas.getContext("2d");
     context.strokeStyle = 'red';
     make_base();

  function make_base(){
     base_image = new Image();
     base_image.src = '/inc/img/inspection/trailer.png';
     base_image.onload = function(){
     context.drawImage(base_image, 2, 100);

      }
    }

     // This will be defined for the iPad
     var is_touch_device = 'ontouchstart' in document.documentElement;

     if (is_touch_device) {
        // create a drawer which tracks touch movements
        var drawer = {
           isDrawing: false,
           touchstart: function (coors) {
              context.beginPath();
              context.moveTo(coors.x, coors.y);
              this.isDrawing = true;
           },
           touchmove: function (coors) {
              if (this.isDrawing) {
                 context.lineTo(coors.x, coors.y);
                 context.stroke();
              }
           },
           touchend: function (coors) {
              if (this.isDrawing) {
                 this.touchmove(coors);
                 this.isDrawing = false;
              }
           }
        };

        // create a function to pass touch events and coordinates to drawer
        function draw(event) {

           // get the touch coordinates.  Using the first touch in case of  multi-touch
           var coors = {
              x: event.targetTouches[0].pageX,
              y: event.targetTouches[0].pageY
           };

           // Now we need to get the offset of the canvas location
           var obj = sigCanvas;

           if (obj.offsetParent) {
              // Every time we find a new object, we add its offsetLeft and offsetTop to curleft and curtop.
              do {
                 coors.x -= obj.offsetLeft;
                 coors.y -= obj.offsetTop;
              }
              // The while loop can be "while (obj = obj.offsetParent)" only, which does return null
              // when null is passed back, but that creates a warning in some editors (i.e. VS2010).
              while ((obj = obj.offsetParent) != null);
           }

           // pass the coordinates to the appropriate handler
           drawer[event.type](coors);
        }


        // attach the touchstart, touchmove, touchend event listeners.
        sigCanvas.addEventListener('touchstart', draw, false);
        sigCanvas.addEventListener('touchmove', draw, false);
        sigCanvas.addEventListener('touchend', draw, false);

        // prevent elastic scrolling
        sigCanvas.addEventListener('touchmove', function (event) {
           event.preventDefault();
        }, false); 
     }
     else {

        // start drawing when the mousedown event fires, and attach handlers to
        // draw a line to wherever the mouse moves to
        $("#canvasSignature").mousedown(function (mouseEvent) {
           var position = getPosition(mouseEvent, sigCanvas);

           context.moveTo(position.X, position.Y);
           context.beginPath();

           // attach event handlers
           $(this).mousemove(function (mouseEvent) {
              drawLine(mouseEvent, sigCanvas, context);
           }).mouseup(function (mouseEvent) {
              finishDrawing(mouseEvent, sigCanvas, context);
           }).mouseout(function (mouseEvent) {
              finishDrawing(mouseEvent, sigCanvas, context);
           });
        });

     }
  }


  // draws a line to the x and y coordinates of the mouse event inside
  // the specified element using the specified context
  function drawLine(mouseEvent, sigCanvas, context) {

     var position = getPosition(mouseEvent, sigCanvas);

     context.lineTo(position.X, position.Y);
     context.stroke();
  }

  // draws a line from the last coordiantes in the path to the finishing
  // coordinates and unbind any event handlers which need to be preceded
  // by the mouse down event
  function finishDrawing(mouseEvent, sigCanvas, context) {
     // draw the line to the finishing coordinates
     drawLine(mouseEvent, sigCanvas, context);

     context.closePath();

     // unbind any events which could draw
     $(sigCanvas).unbind("mousemove")
                 .unbind("mouseup")
                 .unbind("mouseout");
      }
   </script>
   <div>

    </div>

    <script>
        function uploadEx() {
            var canvas = document.getElementById("canvasSignature");
            var dataURL = canvas.toDataURL("image/png");
            document.getElementById('hidden_data').value = dataURL;
            var fd = new FormData(document.forms["form"]);

            var xhr = new XMLHttpRequest();
            xhr.open('POST', '/inc/img/inspection/upload_data.php', true);

            xhr.upload.onprogress = function(e) {
                if (e.lengthComputable) {
                    var percentComplete = (e.loaded / e.total) * 100;
                    console.log(percentComplete + '% uploaded');
                  //alert('Succesfully uploaded');
                }
            };

            xhr.onload = function() {

            };
            xhr.send(fd);

            return false;
        };
        </script>

        </head>
        <style>
        input {
         margin-left: 200cm;
         }

         </style>

        <body>
        <h1>Trailer Inspection</h1>

        <div id="canvasDiv" align="center">
        <!-- It's bad practice (to me) to put your CSS here.  I'd recommend    the use of a CSS file! -->
  <canvas id="canvasSignature" width="955px" height="465px" style="border:2px  solid #000000;"></canvas>


    </div>
    <p><h2></h2></p>
    <p><h4></h4></p>

    <?php if( !empty($table)): ?>
    <p><h3></h3></p>
    <?php if(is_array($table)): ?>
    <?php foreach($table as $h1 => $t1): ?>
    <?php if( !is_int($h1)): ?>
    <p><h3><?php echo $h1; ?></h3></p>
    <?php else: ?>
    <br />
    <?php endif; ?>
    <?php if(is_array($t1)): ?>
    <?php foreach($t1 as $h2 => $t2): ?>
      <?php if( !is_int($h2)): ?>
        <p><h4><?php echo $h2; ?></h4></p>
      <?php else: ?>
        <br />
      <?php endif; ?>
      <?php echo $t2; ?>
    <?php endforeach; ?>
    <?php else: ?>
    <?php echo $t1; ?>
    <?php endif; ?>
    <?php endforeach; ?>
    <?php else: ?>
    <?php echo $table;?>

    <?php endif; ?>
    <?php else: ?>
    <?php endif; ?>



    <br />



    <?php if( !function_exists('form_open')): ?>
    <?php $this->load->helper('form'); ?>
    <?php endif;?>

                                                                                      <form onsubmit="uploadEx();" name="form" id="form" accept-charset="utf-8"  method="post">
              <input name="hidden_data" id="hidden_data" type="hidden" />
              <?php $this->load->helper('string');?>
              <?php $number = random_string('unique');?>
              <input name="sub_id" id="sub_id" type="hidden" value="<?php echo $number; ?>"/> 

              <div>

  <?php if( !empty($options1) AND !empty($label_display1) AND   !empty($field_name1)): ?>
  <?php echo form_label($label_display1.":",$field_name1); ?>
  <?php echo form_dropdown($field_name1,$options1)?>
  <?php endif; ?>

  <?php echo form_label('Carrier Code','car_code'); ?>
  <?php echo form_input(array('name'=>'car_code','type'=>'text')); ?>

  <?php echo form_label('Trailer Number','trlr_num'); ?>
  <?php echo form_input(array('name'=>'trlr_num','type'=>'text')); ?>

  <?php echo form_label('Truck Number','truck_num'); ?>
  <?php echo form_input(array('name'=>'truck_num','type'=>'text')); ?>

  <?php echo form_label('Temp','temp'); ?>
  <?php echo form_input(array('name'=>'temp','type'=>'text')); ?>

  <?php if( !empty($options) AND !empty($label_display) AND  !empty($field_name)): ?>
  <?php echo form_label($label_display.":",$field_name); ?>
  <?php echo form_dropdown($field_name,$options)?>
  <?php endif; ?>

  <?php echo form_label('License Plate','lic_plate'); ?>
  <?php echo form_input(array('name'=>'lic_plate','type'=>'text')); ?>

  <?php echo form_label('Seal','seal'); ?>
  <?php echo form_input(array('name'=>'seal','type'=>'text')); ?>

  <?php echo form_label('STN/Delivery Note','del_note'); ?>
  <?php echo form_input(array('name'=>'del_note','type'=>'text')); ?>

  <?php echo form_label('Ship Number','ship_num'); ?>
  <?php echo form_input(array('name'=>'ship_num','type'=>'text')); ?>

  <input type="hidden" name="draw_num" id="draw_num" value="<?php echo  $number; ?>" />

  <?php echo form_label('Driver Name','driver_name'); ?>
  <?php echo form_input(array('name'=>'driver_name','type'=>'text')); ?>

  <?php echo form_label('Check if Live','live_drop'); ?>
  <?php echo  form_checkbox(array('name'=>'live_drop','type'=>'checkbox','value'=>'1')); ?>


  <?php echo form_label('Check if Damaged','damaged'); ?>
  <?php echo form_checkbox(array('name'=>'damaged','type'=>'checkbox','value'=>'1')); ?>


  <?php echo form_label('Comment','comment'); ?>
  <textarea class="txtarea" style="height:100px; width:350px;" rows="3" name="comment" Id="comment" value=""> </textarea>

  <?php echo form_fieldset_close(); ?>

   </div>
  </br>
 </br>

 <input align="center" type ="submit" name="submit" onclick="uploadEx();">   </input>
</br>
</br>
</form>





</body>

</html>

下面是我的upload_data.php

<?php
$upload_dir = "upload/";
$img = $_POST['hidden_data'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$id = $_POST['sub_id'];
$file = $upload_dir . $id . ".png";
$success = file_put_contents($file, $data);
print $success ? $file : 'Unable to save the file.';
?>

【问题讨论】:

  • 请仅发布与问题相关的代码

标签: javascript php html forms codeigniter


【解决方案1】:

一旦表单中有 onsubmit 事件,您就不需要在提交按钮中进行第二次调用。 在这种情况下,提交按钮中的onclick事件可以在onsubmit事件导致错误之前触发。


此外,您可以尝试通过更改以下参数使 XMLHttpRequest 同步,以避免您的脚本序列执行无序:

改为:

xhr.open('POST', '/inc/img/inspection/upload_data.php', true);

改为:

xhr.open('POST', '/inc/img/inspection/upload_data.php', false);

【讨论】:

  • 我删除了提交按钮中的 onclick 事件,并提交了更多。其中一个上传图片失败,但上传了SQL数据。
  • 我一定会试试这个。谢谢。
  • 您知道,我认为 XMLHttpRequest 问题与 onsubmit 按钮相结合可能是我的问题。只需更改 onsubmit 问题,他们就会间歇性地通过。将其更改为 false 后,它们似乎都通过了。将其更改为 false 客户端在执行任何操作之前等待来自服务器的响应是否正确?
  • 是的,假设在一个三行的脚本中,第二行是 open() 方法,在异步模式下,JS 将执行第一行和第二行,并立即执行第三行,而不等待它的响应。在传输过程中,JS 将执行你附加的回调,更新你的变量,但是一旦第三行已经使用错误的值执行就太晚了。在同步模式下,脚本将冻结您的应用程序在第二行等待服务器传输,以便为第三行提供更新的值。
【解决方案2】:

你从函数中返回 false,但你在 onclick 中没有返回

<input align="center" type ="submit" name="submit" onclick="uploadEx();">  

需要

<input align="center" type ="submit" name="submit" onclick="return uploadEx();">  

【讨论】:

  • 如果我这样做 onclick="return uploadEx();"然后我无法选择提交按钮。我可以“点击”它,但它什么也没做。
  • 它应该运行该功能。您不能同时进行异步 Ajax 调用和提交表单。您可以在 Ajax 调用完成时调用 submit。
猜你喜欢
  • 1970-01-01
  • 2019-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 2018-07-27
  • 1970-01-01
相关资源
最近更新 更多