在循环内多次执行JavaScript倒数脚本

时间:2019-05-05 18:19:39

标签: php symfony doctrine-orm symfony4

我正在使用Symfony,目前正在尝试从数据库中显示这些元素,但是这里有一个转折,因为这些元素中的每个元素都有持续时间,因此我必须显示该持续时间的倒数。 / p>

我已经实现了倒计时脚本(尽管它仍然有一些问题),但是它仅以第一个值执行,而其他行中的字段保持空白。

我现在将解释代码:我有很多停车场,每个停车场都有很多汽车(票数):我的页面显示了停车场,与之相关的汽车,以及每辆汽车的数量和停车时间允许(时间已在数据库的一栏中注册)。

我还在脚本中使用cookie来节省分钟和几秒钟,所以我不知道如何对多个值进行操作。 这是我的照片:

  

enter image description here

这是我的代码(对不起,很乱):

{% extends 'Agent/Baseagent.html.twig' %}

{% block title %}Parking index{% endblock %}

{% block body %}

    {% for parking in user.parkings %}
         <h2>Parking</h2>
             {{ parking.libelle }}

              <h2>voitures</h2>
<table id="file_export" class="table table-striped table-bordered">
                <thead>

                <tbody>
            {% for voitures in parking.voitures %}
                <tr>
                <td>
               {{ voitures.matricule }}
                </td>


                <td>
                <div id="timer" class="js-user-rating" data-is-test="{{ voitures.time}}"></div>
                <td class="center"><span id="demo"></span></td>

                 <script>
 var firstTime = true;

function countdown(minutes) {
    var seconds = 60;
    var mins = minutes;

    if(firstTime && getCookie("minutes")&&getCookie("seconds"))
    {
            firstTime = false;

         var seconds = getCookie("seconds");
         var mins = getCookie("minutes");
    }

    function tick() {

        var counter = document.getElementById("timer");
        setCookie("minutes",mins,10)
        setCookie("seconds",seconds,10)
        var current_minutes = mins-1
        seconds--;
        counter.innerHTML = 
        current_minutes.toString() + ":" + (seconds < 10 ? "0" : "") + String(seconds);
        //save the time in cookie



        if( seconds > 0 ) {
            setTimeout(tick, 1000);
        } else {

            if(mins > 1){

               // countdown(mins-1);   never reach “00″ issue solved:Contributed by Victor Streithorst    
               setTimeout(function () { countdown(mins - 1); }, 1000);

            }
        }
    }
    tick();
}
function setCookie(cname,cvalue,exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays*24*60*60*1000));
    var expires = "expires=" + d.toGMTString();
    document.cookie = cname+"="+cvalue+"; "+expires;
}
 function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1);
        if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}
countdown(55);
                 </script>

                </td>
                </tr>
             {% endfor %}
        {% else %}
            <tr>
                <td colspan="6">no records found</td>
            </tr>
        {% endfor %}
                </tbody>
            </table>{% endblock %}


我的旅行实体

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\VoitureRepository")
 */
class Voiture
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=200)
     */
    private $matricule;

    /**
     * @ORM\Column(type="datetime")
     */
    private $gareele;



    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Parking", inversedBy="voitures")
     * @ORM\JoinColumn(nullable=false)
     */
    private $parking;

    /**
     * @ORM\Column(type="boolean")
     */
    private $parked;

    /**
     * @ORM\Column(type="integer")
     */
    private $time;



    public function getId(): ?int
    {
        return $this->id;
    }

    public function getMatricule(): ?string
    {
        return $this->matricule;
    }

    public function setMatricule(string $matricule): self
    {
        $this->matricule = $matricule;

        return $this;
    }

    public function getGareele(): ?\DateTimeInterface
    {
        return $this->gareele;
    }

    public function setGareele(\DateTimeInterface $gareele): self
    {
        $this->gareele = $gareele;

        return $this;
    }



    public function getParking(): ?Parking
    {
        return $this->parking;
    }

    public function setParking(?Parking $parking): self
    {
        $this->parking = $parking;

        return $this;
    }

    public function getParked(): ?bool
    {
        return $this->parked;
    }

    public function setParked(bool $parked): self
    {
        $this->parked = $parked;

        return $this;
    }

    public function getTime(): ?int
    {
        return $this->time;
    }

    public function setTime(int $time): self
    {
        $this->time = $time;

        return $this;
    }


}

和我的控制器(没什么特别的,只需获取与所连接用户有关的停车位)即可:

/**
 * @Route("/agent")
 */
class AgentController extends AbstractController
{
    /**
     * @Route("/", name="agent", methods={"GET"})
     */
    public function index(): Response
    {

        $use = $this->get('security.token_storage')->getToken()->getUser();

        $user = $this->getUser();   
        $parkingz=$this->getUser()->getParkings();

        return $this->render('Agent/Agent.html.twig', [
            'user' => $user,
            'parkingz'=>$parkingz,
        ]);
    }

2 个答案:

答案 0 :(得分:1)

您遇到了一些嵌套问题(脚本标记需要退出for循环),重复的ID和不正确的计时系统。如果您需要实时更新内容,请使用时间戳和系统时钟来确定实际剩余时间。

首先向您的实体添加方法以获取到期时间戳(以秒为单位)

class Voiture
{
  ...

  public function getExpiresAt()
  {
    $gareele = $this->getGareele();
    $expires = clone $gareele;
    $expires->modify('+' . $this->getTime() . ' min');

    return $expires->format('U');
  }
}

然后在模板中,将计时器范围更改为具有class="timer"(不需要id),并添加带有过期时间戳记的data属性。该脚本将遍历所有.timer,并更新文本以反映该时间点的剩余天数,小时数,分钟数和秒数。在这里,我通过使用函数内的setTimeout()每隔100毫秒更新一次文本。

{% extends 'Agent/Baseagent.html.twig' %}

{% block title %}Parking index{% endblock %}

{% block body %}

  {% for parking in user.parkings %}
    <h2>Parking</h2>
    {{ parking.libelle }}

    <h2>voitures</h2>
    <table id="file_export" class="table table-striped table-bordered">
      <thead></thead>

      <tbody>
      {% if parking.voitures|length > 0 %}
        {% for voitures in parking.voitures %}
          <tr>
            <td>
              {{ voitures.matricule }}
            </td>
            <td class="center">
              <span class="timer" data-expires="{{ voitures.getExpiresAt() }}"></span>
            </td>
          </tr>
        {% endfor %}
      {% else %}
        <tr>
          <td colspan="6">no records found</td>
        </tr>
      {% endif %}
      </tbody>
    </table>
  {% endfor %}

  <script>
    var timers = document.querySelectorAll('.timer')

    function updateTimers () {
      var rightNow = Math.floor(Date.now()/1000) // in seconds
      timers.forEach(function (timer) {

        var expires = parseInt(timer.dataset.expires) // in seconds

        if (rightNow > expires) {
          // Time expired
          timer.innerText = 'Expired'
        } else {
          var seconds = expires - rightNow
          var minutes = Math.floor(seconds/60)
          var hours = Math.floor(minutes/60)
          var days = Math.floor(hours/24)
          seconds = ('0' + String(seconds%60)).slice(-2)
          minutes = ('0' + String(minutes%60)).slice(-2)
          hours = ('0' + String(hours%24)).slice(-2)
          timer.innerText = days + 'd ' + hours + 'h ' + minutes + 'm ' + seconds + 's'
        }

      })

      setTimeout(function () {
        updateTimers()
      }, 100)
    }

    updateTimers()
  </script>

{% endblock %}

注意

如果要通过ajax添加更多计时器(在页面加载后),则应放置以下行:

var timers = document.querySelectorAll('.timer')

在功能块内部,用于在每次调用时搜索新的计时器。

答案 1 :(得分:0)

有重复的ID(“ test”,“ demo”),每个voiture都有一个。

From MDN doc

  

id全局属性定义一个唯一标识符(ID),该标识符必须为   在整个文档中是唯一的。其目的是识别元素   链接(使用片段标识符),脚本或样式时   (使用CSS)。

document.getElementById("demo")将返回一个结果,可能是DOM中的第一个结果。 (我怀疑这里var test = $('#test').data("isTest");也是正确的,但是我不太熟练使用jQuery)。

也许您可以通过“名称”属性进行选择,然后将代码更改为具有一个<script>元素,该元素遍历所需的节点。