读取txt文件到数组+增量变量点击访问下一个数组元素:PHP或Javascript


Read txt file to array + increment variable on click to access next array element: PHP or Javascript?

我正在读取服务器上的短文本文件到PHP变量($data),并首先访问数组中的前2项以显示它们。

然后当用户单击其中一个项目(也发送表单数据)时,我想增加指定数组项目($counter)的PHP变量。

从文件中读取似乎是最容易的PHP,但增量在点击似乎更容易与Javascript -我不能找出一个好方法来锻造两者。解决这个问题的最好方法是什么?我对这两种语言都很陌生。

从文件中读取的php/html代码(工作):

<?php
function getData($subtest_nr) {
    $data = file("subtests/$subtest_nr.txt");
    return $data;
}
$subtest_nr = "7";
$counter = 0;
$data = getData($subtest_nr); ?>
<form id="myform" method="post">
    <div class="four_images">
        <div class="flex-item">
            <input type="radio" name="image" value="7.11" id="alt1" class="hidden">
            <label for="alt1"><img src="images/<?php echo $data[$counter]; ?>"></label>
        </div>
        <div class="flex-item">
            <input type="radio" name="image" value="7.12" id="alt2" class="hidden">
            <label for="alt2"><img src="images/<?php echo $data[$counter+1] ?>"></label>
        </div>
    </div>
</form>

jQuery中变量递增的快速尝试:

jQuery(function($) {
    var counter = 0;
    $("img").click(function(){
        counter++;
        $("p").text(counter);
    });
});

所以我的问题是,如果我应该瞄准要么只有PHP或Javascript/jQuery的两个功能,或者如果有一种方法让我合并两者?

除了这些注释之外,这里还有一种将字体前端和后端合并到一个文件中的方法。

文件使用$_SERVER['PHP_SELF']变量来查找正在执行的文件的名称。我们使用它来将请求的后端php文件的正确名称写入javascript中——这使得我们可以为单文件解决方案命名任何我们想要的名称,而不必担心在源代码的某个地方更新硬编码的url。头疼吗?: p)

index . php

<?php
    if ( isset($_GET['firstItem']) && isset($_GET['numItems']) )
    {
        $firstItem = $_GET['firstItem'];
        $numItems = $_GET['numItems'];
        // should do error checking here
        $subtestNumber = 7;
        $filename = sprintf("subtests/%d.txt", $subtestNumber);
        // dummy, used for testing
        $filename = 'sampleInput.txt';
        $fileHandle = fopen($filename, "rt");
        for ($numLinesToSkip=0; $numLinesToSkip<$firstItem; $numLinesToSkip++)
            fgets($fileHandle);
        $results = array();
        for ($itemCount=0; $itemCount<$numItems; $itemCount++)
        {
            $curLine = fgets($fileHandle);
            //
            // you may wish to remove the trailing new-line character here
            //
            array_push($results, $curLine);
        }
        fclose($fileHandle);
        echo json_encode($results);
        die;                            // stop execution now - dont output the html below
    }
?><!doctype html>
<html>
<head>
<script>
"use strict";
function newEl(tag){return document.createElement(tag)}
function byId(id){return document.getElementById(id)}
// useful for HtmlCollection, NodeList, String types
function forEach(array, callback, scope){for (var i=0,n=array.length; i<n; i++)callback.call(scope, array[i], i, array);} // passes back stuff we need
function ajaxGet(url, onLoad, onError)
{
    var ajax = new XMLHttpRequest();
    ajax.onreadystatechange = function(){if (this.readyState==4 && this.status==200) onLoad(this);}
    ajax.onerror = function() {error.log("ajax request failed to: "+url);onError(this);}
    ajax.open("GET", url, true);
    ajax.send();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
    byId('goBtn').addEventListener('click', onGoBtnClicked);
}
function onGoBtnClicked(evt)
{
    var firstIndex = byId('firstRecordInput').value;
    var numItems = byId('numRecordsInput').value;
    // we want to request data from this same file, so get php to print it into the javascript source
    var filename = '<?php echo $_SERVER['PHP_SELF'];?>';
    // construct the url from the filename and the (GET) parameters we'd like to pass to the php
    var url = filename + '?firstItem=' + firstIndex + '&numItems=' + numItems;
    // ask for it, fire the onDataReceived function with the XMLHttpRequest object as the only input
    ajaxGet(url, onDataReceived, function(){alert('ajax failed! :(');} )
}
/*
    ------------------------------------------------------------
     format of html the onDataReceived function needs to create
     - .four_images div just once for the whole response
     - .flex-item once for each item returned
    ------------------------------------------------------------
    <div class="four_images">
        <div class="flex-item">
            <input type="radio" name="image" value="7.11" id="alt1" class="hidden">
            <label for="alt1"><img src="images/<?php echo $data[$counter]; ?>"></label>
        </div>
        <div class="flex-item">
            <input type="radio" name="image" value="7.12" id="alt2" class="hidden">
            <label for="alt2"><img src="images/<?php echo $data[$counter+1] ?>"></label>
        </div>
    </div>
*/
function onDataReceived(ajax)
{
    // get the raw data - it'll be a string something like `["file1.txt'n","file2.swf'n"]`
    var rawData = ajax.response;
    // parse it and turn it from a string into some javascript objects. 
    // this has same the effect as typing the following into your source-code
    //
    //  var parsedData = [ "file1.txt'n", "file2.swf'n" ];
    //
    //  except, you can do it with unknown data. BUT: we must know the *format*
    //  of the data so we know what to do with it. We happen to know that
    //  the data will be an array
    var parsedData = JSON.parse(rawData);
    // make the outer wrapper - refer above for the structure of the created HTML
    // this wrapper needs to exist so the makeItem function can append content
    // to it in the forEach call
    var div = newEl('div');
    div.className = 'four_images';
    // for each of the items in the parsedData array, call the makeItem function - once this forEach call is done,
    // we have the contents of the form all sitting in the [div] element - the makeItem function is inside this onDataReceived function
    // so that it can 'see' the [div] variable in order to append each item to it.
    forEach(parsedData, makeItem);
    // show the results
    byId('myForm').innerHTML = '';
    byId('myForm').appendChild(div);
    // this function has now finished executing. the makeItem function exists here (unfortunately) so that
    // the [div] element remains in scope.
    // called with the current element in the collection as dataItem, it's index in the collection as index and the collection itself as arrayOfItems
    //  we're making use of the item's index to correctly set the id of the radio-button and then to make the label refer to it (which it doesn't actually
    //  need to do in this case, since the label element contains the input)
    //  another use of index is to place a comma between items i.e "1,2,3,4,5,6" - there are two approaches. The naive one is to place a comma after each
    // item except the last one. To do this - we need to know how many items there are in total - sometimes this is very expensive to compute.
    // the other approach, is to put a comma _before_ all items except the first one.
    function makeItem(dataItem, index, arrayOfItems)
    {
        var itemDiv = newEl('div');                 
        itemDiv.className = 'flex-item';            
        var input = newEl('input');                 
        input.type = 'radio';                       
        input.name = 'image';                       
        input.value = 'putSomethingUsefulHere';     // **** the example had 7.11 and 7.12 here - I've no idea how they were determined ***
        input.id = "alt" + (index+1);               
        input.className = 'hidden';
        var label = newEl('label');
        label.for = 'alt' + (index+1);
        var img = newEl('img');
        img.src = 'images/' + dataItem;
        label.appendChild(img);
        itemDiv.appendChild(input);
        itemDiv.appendChild(label);
        div.appendChild(itemDiv);
    }
}
</script>
<style>
.panel
{
    border: solid 1px black;
    border-radius: 8px;
    padding: 8px;
    background-color: #eef;
    display:inline-block;
}
</style>
</head>
<body>
    <div class='panel'>
        <label>Index of first record: <input type='number' id='firstRecordInput' value='0'/></label><br>
        <label>Number of records: <input type='number' id='numRecordsInput' value='2'/></label>
        <hr>
        <div style='text-align: center'><button id='goBtn'>Retrieve records</button></div>
        <hr>
        <form id='myForm'>
        </form>
    </div>
</body>
</html>

这里有一个粗略的示例,没有错误检查。我不使用jQuery,所以您需要将其转换为使用jQuery的ajax方法。不能告诉你想要达到的每一张图片点击,所以你可以编辑回来。

我的主要目的是展示一种方法,通过这种方法,前端可以维护状态信息,并可以使用它从(哑)后端请求所需的信息。

sampleInput.txt

file1.txt
file2.swf
file1.pdf
file1.exe
file1.asm

getItems.php

<?php
    $firstItem = $_GET['firstItem'];
    $numItems = $_GET['numItems'];
    // should do error checking here
    $subtestNumber = 7;
    $filename = sprintf("subtests/%d.txt", $subtestNumber);
    // dummy, used for testing
    $filename = 'sampleInput.txt';
    $fileHandle = fopen($filename, "rt");
    for ($numLinesToSkip=0; $numLinesToSkip<$firstItem; $numLinesToSkip++)
        fgets($fileHandle);
    $results = array();
    for ($itemCount=0; $itemCount<$numItems; $itemCount++)
    {
        $curLine = fgets($fileHandle);
        //
        // you may wish to remove the trailing new-line character here
        //
        array_push($results, $curLine);
    }
    fclose($fileHandle);
    echo json_encode($results);
?>

getStuff.html

<!doctype html>
<html>
<head>
<script>
"use strict";
function newEl(tag){return document.createElement(tag)}
function byId(id){return document.getElementById(id)}
// useful for HtmlCollection, NodeList, String types
function forEach(array, callback, scope){for (var i=0,n=array.length; i<n; i++)callback.call(scope, array[i], i, array);} // passes back stuff we need
function ajaxGet(url, onLoad, onError)
{
    var ajax = new XMLHttpRequest();
    ajax.onreadystatechange = function(){if (this.readyState==4 && this.status==200) onLoad(this);}
    ajax.onerror = function() {error.log("ajax request failed to: "+url);onError(this);}
    ajax.open("GET", url, true);
    ajax.send();
}
/////////////////////
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
    byId('goBtn').addEventListener('click', onGoBtnClicked);
}
function onGoBtnClicked(evt)
{
    var firstIndex = byId('firstRecordInput').value;
    var numItems = byId('numRecordsInput').value;
    var url = 'getItems.php?firstItem=' + firstIndex + '&numItems=' + numItems;
    ajaxGet(url, onDataReceived, function(){alert('ajax failed! :(');} )
}
/*
<div class="four_images">
        <div class="flex-item">
            <input type="radio" name="image" value="7.11" id="alt1" class="hidden">
            <label for="alt1"><img src="images/<?php echo $data[$counter]; ?>"></label>
        </div>
        <div class="flex-item">
            <input type="radio" name="image" value="7.12" id="alt2" class="hidden">
            <label for="alt2"><img src="images/<?php echo $data[$counter+1] ?>"></label>
        </div>
    </div>
*/
function onDataReceived(ajax)
{
    var rawData = ajax.response;
    var parsedData = JSON.parse(rawData);
    var div = newEl('div');
    div.className = 'four_images';
    forEach(parsedData, makeItem);
    byId('myForm').innerHTML = '';
    byId('myForm').appendChild(div);
    function makeItem(dataItem, index, arrayOfItems)
    {
        var itemDiv = newEl('div');
        itemDiv.className = 'flex-item';
        var input = newEl('input');
        input.type = 'radio';
        input.name = 'image';
        input.value = 'putSomethingUsefulHere';
        input.id = "alt" + (index+1);
        input.className = 'hidden';
        var label = newEl('label');
        label.for = 'alt' + (index+1);
        var img = newEl('img');
        img.src = 'images/' + dataItem;
        label.appendChild(img);
        itemDiv.appendChild(input);
        itemDiv.appendChild(label);
        div.appendChild(itemDiv);
    }
}
</script>
<style>
.panel
{
    border: solid 1px black;
    border-radius: 8px;
    padding: 8px;
    background-color: #eef;
    display:inline-block;
}
</style>
</head>
<body>
    <div class='panel'>
        <label>Index of first record: <input type='number' id='firstRecordInput' value='0'/></label><br>
        <label>Number of records: <input type='number' id='numRecordsInput' value='2'/></label>
        <hr>
        <div style='text-align: center'><button id='goBtn'>Submit</button></div>
        <hr>
        <form id='myForm'>
        </form>
    </div>
</body>
</html>

我猜你得到的数据是ajax数据。所以需要输入$(document).on(…

var counter = 0;
$(document).on('click','img', function(){
    counter++;
    $("p").text(counter);
});