Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my code not work in Safari or Opera?

There is a function in js which displays messages to the table (messages are stored in json). In Google Chrome, it works, but Safari, Opera or Microsoft Edge - no! There is a mistake in code which is associated with the call to setTimeout (callback, 5000)(nothing is sent to the callback).So, For (var i = 0; i <respond.length; i ++) will not work since respond === undefined.

But why is it so?

callback(
  [{
      "time": "1500303264",
      "user": "qwe",
      "message": "we",
      "id": 1
    },
    {
      "time": "1500303987",
      "user": "Max",
      "message": "q",
      "id": 2
    }
  ]);

function smile(mess) {
  var smile = ":)";
  var graficSmile = "<img src = './image/Smile.png' alt='Smile' align='middle'>";
  var string_with_replaced_smile = mess.replace(smile, graficSmile);

  var sad = ":("
  var graficSad = "<img src = './image/Sad.png' alt='Smile' align='middle'>";
  var string_with_replaced_smile_and_sad = string_with_replaced_smile.replace(sad, graficSad);

  return string_with_replaced_smile_and_sad;
}

$.getJSON('data/messages.json', callback);
var exists = [];

function callback(respond) {
  var timeNow = Date.now();

  for (var i = 0; i < respond.length; i++) {
    var data = respond[i];

    if (exists.indexOf(data.id) != -1) continue;

    var timeInMessage = data.time * 1000;
    var diff_time = (timeNow - timeInMessage);

    if (diff_time <= 3600000) {
      var rowClone = $('.mess_hide').clone().removeClass('mess_hide');

      var newDate = new Date(timeInMessage);
      var dateArray = [newDate.getHours(), newDate.getMinutes(), newDate.getSeconds()]
      var res = dateArray.map(function(x) {
        return x < 10 ? "0" + x : x;
      }).join(":");

      $('#messages').append(rowClone);
      $('.time', rowClone).html(res);
      $('.name', rowClone).html(data.user);
      $('.message', rowClone).html(smile(data.message));
      $('.scroller').scrollTop($('#messages').height());

      exists.push(data.id);
    }
  }
  setTimeout(function(){callback(respond)}, 5000);
}
.scroller {
  width: 490px;
  height: 255px;
  max-height: 255px;
  overflow-y: auto;
  overflow-x: hidden;
}

table#messages {
  min-height: 260px;
  width: 100%;
  background: #fffecd;
  border: none;
}

table#messages::-webkit-scrollbar {
  width: 1em;
}

table#messages::-webkit-scrollbar-track {
  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}

table#messages::-webkit-scrollbar-thumb {
  background-color: darkgrey;
  outline: 1px solid slategrey;
}

tr {
  height: 20%;
  display: block;
}

td.time,
td.name {
  width: 70px;
  max-width: 75px;
  text-align: center;
}

td.name {
  font-weight: bold;
}

form#text_submit {
  display: inline-flex;
  align-items: flex-start;
}

input#text {
  width: 370px;
  height: 30px;
  margin-top: 20px;
  background: #fffecd;
  font-family: 'Montserrat';
  font-size: 16px;
  border: none;
  align-self: flex-start;
}

input#submit {
  padding: 0;
  margin-left: 21px;
  margin-top: 21px;
  height: 30px;
  width: 95px;
  background: #635960;
  border: none;
  color: white;
  font-family: 'Montserrat';
  font-size: 16px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="scroller">
  <table id="messages">
    <tr class="mess_hide">
      <td class="time"></td>
      <td class="name"></td>
      <td class="message"></td>
    </tr>
  </table>
</div>
<form method="POST" id="easyForm">
  <input type="text" name="text" id="text">
  <input type="submit" value="Send" id="submit">
</form>
</div>

Chrome Chrome

Opera Opera

like image 735
Trick Avatar asked Jul 18 '17 20:07

Trick


2 Answers

  1. Since it is assumed that the var exists - array, but the value of the array ([]) is assigned to it only later, after the call $.getJSON(...). So, when callback is called for the first time value [] is not set for exists.We just need to move var exists above the first call of callback.
  2. When callback is called by the timer, nothing is passed to it. But timer needs to reread the messages from the file and display them on the screen.So, instead setTimeout(function(){callback(respond)}, 5000); we need setTimeout(function(){$.getJSON('data/messages.json', callback);}, 5000);.

var exists = [];
$.getJSON('data/messages.json', callback);

function callback(respond) {
  var timeNow = Date.now();

  for (var i = 0; i < respond.length; i++) {
    var data = respond[i];

    if (exists.indexOf(data.id) != -1) continue;

    var timeInMessage = data.time * 1000;
    var diff_time = (timeNow - timeInMessage);

    if (diff_time <= 3600000) {
      var rowClone = $('.mess_hide').clone().removeClass('mess_hide');

      var newDate = new Date(timeInMessage);
      var dateArray = [newDate.getHours(), newDate.getMinutes(), newDate.getSeconds()]
      var res = dateArray.map(function(x) {
        return x < 10 ? "0" + x : x;
      }).join(":");

      $('#messages').append(rowClone);
      $('.time', rowClone).html(res);
      $('.name', rowClone).html(data.user);
      $('.message', rowClone).html(smile(data.message));
      $('.scroller').scrollTop($('#messages').height());

      exists.push(data.id);
    }
  }
  setTimeout(function() {
    $.getJSON('data/messages.json', callback);
  }, 5000);
}
like image 130
Trick Avatar answered Nov 12 '22 11:11

Trick


Since callback requires an array to be passed as an argument, setTimeout must ensure that when it calls callback, it passes the array.

Change

setTimeout(callback, 5000);

to

setTimeout(function(){callback(respond)}, 5000);

which allows callback to be called with an argument as the body of an anonymous function that will be called by setTimeout.

Also, as a side note, if you used respond.forEach() instead of a counting for loop, the code would be much cleaner:

   respond.forEach(function(data) {

    if (exists.indexOf(data.id) != -1) continue;

    var timeInMessage = data.time * 1000;
    var diff_time = (timeNow - timeInMessage);

    if (diff_time <= 3600000) {
      var rowClone = $('.mess_hide').clone().removeClass('mess_hide');

      var newDate = new Date(timeInMessage);
      var dateArray = [newDate.getHours(), newDate.getMinutes(), newDate.getSeconds()]
      var res = dateArray.map(function(x) {
        return x < 10 ? "0" + x : x;
      }).join(":");

      $('#messages').append(rowClone);
      $('.time', rowClone).html(res);
      $('.name', rowClone).html(data.user);
      $('.message', rowClone).html(smile(data.message));
      $('.scroller').scrollTop($('#messages').height());

      exists.push(data.id);
    }
  });
like image 23
Scott Marcus Avatar answered Nov 12 '22 12:11

Scott Marcus