Get new line from file after x seconds


#1

So, thanks to @texnixe I got a ‘pull random tweet from text file’ php-snippet working …

I would like to add a feature, that a new line is printed every x seconds … I googled a lot, but that just confused me more. Do you have any ideas, please? : )

<?php $file = "tweets.txt"; //$file = kirby()->roots()->index() . DS . "tweets.txt"; ?>
<?php if(filesize($file) > 0): ?>
<?php $tweets = file($file, FILE_IGNORE_NEW_LINES); ?>
<?php $tweet = $tweets[array_rand($tweets)]; ?>
        <blockquote class="tweet" cite="https://twitter.com/usernamn">
          <p><?php echo $tweet ?></p>
          <p>&mdash;&nbsp;<a href="https://twitter.com/username">@username</a></p>
        </blockquote>
<?php endif ?>

Thank you very much in advance.


#2

“Every few seconds” can only be done in the frontend with JavaScript. You would need to print a few quotes in PHP as hidden text (either hidden with CSS or as JSON array in a <script> tag) and cycle through them via JS.


#3

Or alternatively, make a timed Ajax call to a route that executes the code.


#4

Technically it can be done with PHP, using sleep().


#5

Yeah, but if you put the script to sleep, the rest of the script is not executed.


#6

Would you have an example to that AJAX-way? I think I never used AJAX before, or I don’t know of it … O: )


#7

Here you go:

// route in config.php
c::set('routes', array(
  array(
    'pattern' => 'api/gettweet',
    'action'  => function() {
      $file = kirby()->roots()->index() . DS . 'tweets.txt';
      $html = "";
      if(filesize($file) > 0) {
      $tweets = file($file, FILE_IGNORE_NEW_LINES);
      $tweet = $tweets[array_rand($tweets)];
      $html = '<blockquote class="tweet" cite="https://twitter.com/username"><p>' . $tweet . '</p><p>&mdash;&nbsp;<a href="https://twitter.com/username">@username</a></p></blockquote>';
      }
      echo $html;

    }
  ),
));
// javascript
function gettweet() {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'api/gettweet');
  xhr.send(null);
  xhr.onreadystatechange = function () {
    var DONE = 4; // readyState 4 means the request is done.
    var OK = 200; // status 200 is a successful return.

    if (xhr.readyState === DONE) {
      if (xhr.status === 200) {
        var element = document.getElementById("tweets");
        var response = xhr.responseText;
        element.innerHTML = response;
      } else {
        console.log('Error: ' + xhr.status); // An error occurred during the request.
      }
    }
  }
}

// set timer
window.setInterval(gettweet, 3000);

Or if you are using jQuery:

function gettweet() {
  var url = "api/gettweet";
  $.get(url, function(response) {
        $('#tweets').html(response);
  });
}
// show an initial tweet on page load
$(document).ready(function() {
    gettweet();
});
// set the interval for a new tweet
setInterval(gettweet, 3000);

Display new content after x seconds with routes and ajax …
#8

Dear @texnixe, wow, thank you so very much!

If I’m understanding this correctly, I need the first snippet in my config.php in either case, if it’s javascript or jQuery. I’d prefer javascript, to be honest. The jQuery snippet has an option for an interval, which I can’t see in javascript, but I’m still new to js, so it may be my fault, heh.

Can I use setInterval(gettweet, 3000); in plain javascript?

BTW, I’m still looking for a rock solid alternative to $(document).ready(function() { in javascript, but haven’t found one in the last weeks. I found an article on stackoverflow, which states, it is not that simple in pure javascript. Pity! One alternative would be loading the script in the body or after the body, but I don’t like that to be honest. Every js in the head of a website is a clean solution, I think. O: )


#9

I think the easiest would be to put the function at the end of the document before the closing body tag.

<!--  some HTML -->
<script>
  gettweet();
</script>
</body>
```
As regards the interval, you can do this:

```
window.setInterval(gettweet, 3000);
```

IHMO, if there is no reason to do it, your javascript should be at the end of the document, not in the head to prevent render blocking.