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

时间:2016-09-30 06:08:11

标签: javascript php jquery

我正在将服务器上的短文本文件读入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,或者我是否有办法合并这两种功能?

3 个答案:

答案 0 :(得分:1)

这是一个粗略的例子,没有错误检查。我不是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>

答案 1 :(得分:1)

除了评论之外,这里还有一种方法,它将font-end和后端组合成一个文件。

该文件使用$ _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>

答案 2 :(得分:0)

我猜你得到的数据是ajax数据。所以需要是$(文件).on(...

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