dongyang2229 2018-03-19 16:29
浏览 71
已采纳

jQuery.Timer Ajax将多个表单值发送到辅助页面

I'm using this jquery timer to collect time spent while it is running.

https://github.com/walmik/timer.jquery http://jquerytimer.com/

In a prior Stack Overflow post we were able to Post to another page the current accumulated time using jQuery Ajax (jQuery.timer how to get current value in php?). Many thinks to @Dakis

It seems our current solution is trying to save on any Stop and Restart of the Timer. It only needs to do a Save to DB routine IF the “Save Time and Notes” button is selected.

I’ve been researching jQuery Ajax and understand that a key/value pair is needed to be sent to the server/receiving page. I understand the first value identifies the target from which to get the "key", but I could not get a clear understanding of proper formatting for the second “value”. 'task': $('.ta_tasks').data('task’) does not seem to be passing the value as expected.

I’ve added a TextArea with an ID of “ta_tasks” and appended the current working AJAX with:

data: {
  'time': $('.timer').data('seconds'),
  'state': $('.timer').data('state'),
  'task': $('.ta_tasks').data('task’)

On the receiving page I added a simple alert to see if the value is being received but it is not. If I can figure out how to properly send the contents of the TextArea I could also figure out how to submit a value from the “Save Time and Notes” button so that a Pause and Restart will not also submit to the database.

Working page: http://sgdesign.com/timer2.php

Parent page script:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/timer.jquery/0.7.1/timer.jquery.min.js" type="text/javascript"></script>

    <script type="text/javascript">
        $(document).ready(function () {
            var hasTimer = false;

            /**
             * Save the current timer value.
             * 
             * Performs an ajax request to the server, which will 
             * save the timer value in a database table and return
             * a corresponding message.
             */
            function saveTime() {
                $.ajax({
                    method: 'post',
                    dataType: 'html',
                    url: 'saveTime.php',
                    data: {
                        'time': $('.timer').data('seconds'),
                        'state': $('.timer').data('state'),
            'task': $('.ta_tasks').data('task')
                    },
                    success: function (response, textStatus, jqXHR) {
                        displayAlert('success', response);
                    },
                    error: function (jqXHR, textStatus, errorThrown) {
                        /*
                         * If the status code of the response is the custom one 
                         * defined by me, the developer, in saveTime.php, then I 
                         * can display the corresponding error message. Otherwise, 
                         * the displayed message will be a general user-friendly 
                         * one - so, that no system-related infos will be shown.
                         */
                        var message = (jqXHR.status === 420)
                                ? jqXHR.statusText
                                : 'An error occurred during your request. Please try again.';

                        displayAlert('danger', message);
                    },
                    complete: function (jqXHR, textStatus) {
                        //...
                    }
                });
            }

            /**
             * Display a bootstrap alert.
             * 
             * @param type string success|info|warning|danger.
             * @param message string Alert message.
             * @return void
             */
            function displayAlert(type, message) {
                var alert = '<div class="alert alert-' + type + ' alert-dismissible" role="alert">'
                        + '<button type="button" class="close" data-dismiss="alert" aria-label="Close">'
                        + '<span aria-hidden="true">&times;</span>'
                        + '</button>'
                        + '<span>' + message + '</span>'
                        + '</div>';

                $('.messages').html(alert);
            }

            // Init timer start
            $('.save-timer-btn').on('click', function () {
                saveTime();
            });

            // Init timer start
            $('.start-timer-btn').on('click', function () {
                hasTimer = true;
                $('.timer').timer({
                    editable: true
                });
                $(this).addClass('d-none');
                $('.pause-timer-btn').removeClass('d-none');
            });

            // Init timer resume
            $('.resume-timer-btn').on('click', function () {
                $('.timer').timer('resume');
                $(this).addClass('d-none');
                $('.pause-timer-btn').removeClass('d-none');
            });

            // Init timer pause
            $('.pause-timer-btn').on('click', function () {
                $('.timer').timer('pause');
                $(this).addClass('d-none');
                $('.resume-timer-btn').removeClass('d-none');

                saveTime();
            });

            // Remove timer. Leaves the display intact.
            $('.remove-timer-btn').on('click', function () {
                hasTimer = false;
                $('.timer').timer('remove');
                $(this).addClass('d-none');
                $('.start-timer-btn').removeClass('d-none');
                $('.pause-timer-btn, .resume-timer-btn').addClass('d-none');
            });

            // Additional focus event for this demo
            $('.timer').on('focus', function () {
                if (hasTimer) {
                    $('.pause-timer-btn').addClass('d-none');
                    $('.resume-timer-btn').removeClass('hidden');
                }
            });

            // Additional blur event for this demo
            $('.timer').on('blur', function () {
                if (hasTimer) {
                    $('.pause-timer-btn').removeClass('d-none');
                    $('.resume-timer-btn').addClass('d-none');
                }
            });
        });
    </script>

Target Page contents:

<?php
// Price per hour variable
$cost = 50;

# require 'connection.php';

// Validate the timer value.
if (!isset($_POST['time']) || empty($_POST['time'])) {
/*
 * This response header triggers the ajax error because the status 
 * code begins with 4xx (which corresponds to the client errors).
 * I defined 420 as the custom status code. You can choose whatever
 * code between 401 and 499 which is not officially assigned, e.g.
 * which is marked as "Unassigned" in the official HTTP Status Code Registry.
 * See the link.
 * 
 * @link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml HTTP Status Code Registry.
 */
header('HTTP/1.1 420 No time value defined. Did you start the timer?');
exit();
}

// Validate the timer state.
if (!isset($_POST['state']) || empty($_POST['state'])) {
header('HTTP/1.1 420 No timer state recognized. Did you start the timer?');
exit();
}

// Read the posted values.
$time = $_POST['time'];
$state = $_POST['state']; /* The state of the timer when the saving operation was triggered. */
$task = $_POST['ta_tasks'];
$r = $cost / 3600 * $time;
$rate = round($r, 2);

/*
 * Save the timer value in a db table using PDO library.
 */
/* $sql = 'INSERT INTO my_timer_table (
        time
    ) VALUES (
        :time
    )';
$statement = $connection->prepare($sql);
$statement->execute([
':time' => $time,
]);

// Print success message.
echo 'Time (' . $time . ' seconds) successfully saved when timer was ' . $state . '.';
exit();  */
?>

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
<script>
    var a =  "<?php echo $task; ?>";
    alert ('task: ' + a);
</script>
</head>

<body>
<?php function secondsToTime($seconds) {
$dtF = new \DateTime('@0');
$dtT = new \DateTime("@$seconds");
return $dtF->diff($dtT)->format('%h hours, %i minutes and %s seconds');
// return $dtF->diff($dtT)->format('%a days, %h hours, %i minutes and %s seconds');
}
?>
<?php echo secondsToTime($time);
echo '<br>'; 
echo 'Tasks: '.$task .'<br>'; 
echo 'Cost: $'. $rate;
?>
</body>
</html>

Goal Summary Proper formatting of data in: 'task': $('.ta_tasks').data('task’) Understanding of Why so as to learn how to also transfer when the 'Save Time and Notes" button to invoke saving Cost and Notes to DB

generic image of page result

  • 写回答

3条回答 默认 最新

  • dtjo51649 2018-03-19 17:57
    关注

    Don't define functions inside $(document).ready. Bring them outside.

    Functions in PHP should reside only in pages destined for this purpose. See PSR-1 Side Effects. In principle you should definitely read: PSR-1 and PSR-2. Optional, especially PSR-4.

    When you try to read a value sent through ajax, then you should read the value, not the CSS selector. So: Wrong: $task = $_POST['ta_tasks'];, correct: $task = $_POST['task'];.

    Before validating posted values (on top of the page saveTime.php) you shouldn't declare any variables or do other things - so to say. So no $cost = 50; before validations, but after them. Still, if you want to define constants for saveTime.php, then better bring them in another file, which you can include.

    In this case, the data() method is a proprietary method of http://jquerytimer.com ! You can use it to fetch some values (timer value, timer state, etc). But, in order to fetch the value of a html control you need to use val(), or text(), or innerHtml, etc. In a word: native js or jquery methods/functions. So, use like this:

    data: {
        'time': $('.timer').data('seconds'),
        'state': $('.timer').data('state'),
        'task': $('#ta_tasks').val()
    }
    

    Do you see the selector ('#ta_tasks')? It references an id (because of #). You used .ta_tasks, therefore referencing a class name. Which you didn't define.

    Better: use the camelCase naming convention for html id's and names, and the "hyphen-separated" form for css classes:

    data: {
        'time': $('.timer').data('seconds'),
        'state': $('.timer').data('state'),
        'task': $('#ta_tasks').val()
    }
    
    //...
    
    <textarea id="taTasks" name="taTasks" class="form-control" rows="4">Doh!</textarea>
    

    Avoid as much as possible referencing php code from javascript or css code. If you need a php value inside a javascript code, then pass it through a javascript function - as argument, or save the php value inside an attribute of a html control and read it through referencing the attribute by js/jquery methods/functions. As an example, see the code in saveTime.php, which saves the task value in a hidden input and alerts it from js code.


    index.php

    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
            <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
            <meta charset="UTF-8" />
            <!-- The above 3 meta tags must come first in the head -->
    
            <title>Demo - Timer</title>
    
            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    
            <script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
            <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/timer.jquery/0.7.1/timer.jquery.min.js" type="text/javascript"></script>
    
            <script type="text/javascript">
                $(document).ready(function () {
                    var hasTimer = false;
    
                    // Init timer start
                    $('.save-timer-btn').on('click', function () {
                        saveTime();
                    });
    
                    // Init timer start
                    $('.start-timer-btn').on('click', function () {
                        hasTimer = true;
                        $('.timer').timer({
                            editable: true
                        });
                        $(this).addClass('d-none');
                        $('.pause-timer-btn').removeClass('d-none');
                    });
    
                    // Init timer resume
                    $('.resume-timer-btn').on('click', function () {
                        $('.timer').timer('resume');
                        $(this).addClass('d-none');
                        $('.pause-timer-btn').removeClass('d-none');
                    });
    
                    // Init timer pause
                    $('.pause-timer-btn').on('click', function () {
                        $('.timer').timer('pause');
                        $(this).addClass('d-none');
                        $('.resume-timer-btn').removeClass('d-none');
    
                        saveTime();
                    });
    
                    // Remove timer. Leaves the display intact.
                    $('.remove-timer-btn').on('click', function () {
                        hasTimer = false;
                        $('.timer').timer('remove');
                        $(this).addClass('d-none');
                        $('.start-timer-btn').removeClass('d-none');
                        $('.pause-timer-btn, .resume-timer-btn').addClass('d-none');
                    });
    
                    // Additional focus event for this demo
                    $('.timer').on('focus', function () {
                        if (hasTimer) {
                            $('.pause-timer-btn').addClass('d-none');
                            $('.resume-timer-btn').removeClass('d-none');
                        }
                    });
    
                    // Additional blur event for this demo
                    $('.timer').on('blur', function () {
                        if (hasTimer) {
                            $('.pause-timer-btn').removeClass('d-none');
                            $('.resume-timer-btn').addClass('d-none');
                        }
                    });
                });
    
                /**
                 * Save the current timer value.
                 * 
                 * Performs an ajax request to the server, which will 
                 * save the timer value in a database table and return
                 * a corresponding message.
                 */
                function saveTime() {
                    $.ajax({
                        method: 'post',
                        dataType: 'html',
                        url: 'saveTime.php',
                        data: {
                            'time': $('.timer').data('seconds'),
                            'state': $('.timer').data('state'),
                            'task': $('#taTasks').val()
                        },
                        success: function (response, textStatus, jqXHR) {
                            displayAlert('success', response);
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            var message = (jqXHR.status === 420)
                                    ? jqXHR.statusText
                                    : 'An error occurred during your request. Please try again.';
    
                            displayAlert('danger', message);
                        },
                        complete: function (jqXHR, textStatus) {
                            //...
                        }
                    });
                }
    
                /**
                 * Display a bootstrap alert.
                 * 
                 * @param type string success|info|warning|danger.
                 * @param message string Alert message.
                 * @return void
                 */
                function displayAlert(type, message) {
                    var alert = '<div class="alert alert-' + type + ' alert-dismissible" role="alert">'
                            + '<button type="button" class="close" data-dismiss="alert" aria-label="Close">'
                            + '<span aria-hidden="true">&times;</span>'
                            + '</button>'
                            + '<span>' + message + '</span>'
                            + '</div>';
    
                    $('.messages').html(alert);
                }
            </script>
        </head>
        <body>
    
            <div class="container">
                <div class="row">
                    <div class="col-xs-12">
                        <h4>
                            Timer Demo 2
                        </h4>
                    </div>
                </div>
                <div class="row">
                    <div class="col-xs-6 messages"></div>
                </div>
                <div class="row">
                    <div class="col-md-3">
                        <input type="text" id="timer" name="timer" class="form-control timer" placeholder="0 sec">
                    </div>
                    <div class="col-md-9">
                        <button type="button" class="btn btn-success start-timer-btn">
                            Start
                        </button>
                        <button type="button" class="btn btn-success resume-timer-btn d-none">
                            Resume
                        </button>
                        <button type="button" class="btn btn-danger pause-timer-btn d-none">
                            Pause
                        </button>
                        <button type="button" class="btn btn-danger remove-timer-btn d-none">
                            Remove Timer
                        </button>
    
                        <button type="button" class="btn btn-primary save-timer-btn">
                            Save Time and Notes
                        </button>
                    </div>
                </div>
    
                <div class="row mt-1">
                    <div class="col-sm-12">
                        <lable for="taTasks">Notes to accompany task:</lable>        
                        <textarea id="taTasks" name="taTasks" class="form-control" rows="4">Doh!</textarea>
                    </div>
                </div>
    
    
            </div>
    
        </body>
    </html>
    

    saveTime.php

    <?php
    require_once 'functions.php';
    
    // Validate the timer value.
    if (!isset($_POST['time']) || empty($_POST['time'])) {
        header('HTTP/1.1 420 No time value defined. Did you start the timer?');
        exit();
    }
    
    // Validate the timer state.
    if (!isset($_POST['state']) || empty($_POST['state'])) {
        header('HTTP/1.1 420 No timer state recognized. Did you start the timer?');
        exit();
    }
    
    // Validate the task.
    if (!isset($_POST['task']) || empty($_POST['task'])) {
        header('HTTP/1.1 420 No task value received.');
        exit();
    }
    
    // Price per hour variable
    $cost = 50;
    
    // Read the posted values.
    $time = $_POST['time'];
    $state = $_POST['state']; /* The state of the timer when the saving operation was triggered. */
    $task = $_POST['task'];
    $r = $cost / 3600 * $time;
    $rate = round($r, 2);
    ?>
    <script type="text/javascript">
        $(document).ready(function () {
            alertTask();
        });
    
        function alertTask() {
            var task = $('#task').val();
            alert(task);
        }
    </script>
    <input type="hidden" id="task" name="task" value="<?php echo $task; ?>">
    <?php
    echo secondsToTime($time);
    echo '<br>';
    echo 'Tasks: ' . $task . '<br>';
    echo 'Cost: $' . $rate;
    ?>
    

    functions.php

    <?php
    
    function secondsToTime($seconds) {
        $dtF = new \DateTime('@0');
        $dtT = new \DateTime("@$seconds");
        return $dtF->diff($dtT)->format('%h hours, %i minutes and %s seconds');
        // return $dtF->diff($dtT)->format('%a days, %h hours, %i minutes and %s seconds');
    }
    

    Edit 1: In index.php, I brought the js functions outside of $(document).ready. I forgot to do it earlier.

    Edit 2: Changed hidden to d-none in

    $('.resume-timer-btn').removeClass('hidden');
    

    Edit 3: I found the problem about which I commented. It was in my saveTime.php code: I loaded the jquery library, but it was already loaded in index.php. More of it: since you are loading the content of saveTime.php in a html page (index.php) which already has all resources loaded, you don't need to structure the saveTime.php as a whole structured html (with doctype, head, body, etc). It is completely enough to just define the content and script tags that you need. So, I reedited saveTime.php correspondingly.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序
  • ¥15 onvif+openssl,vs2022编译openssl64