Подождите, пока DOM завершит манипуляции, прежде чем вызывать подсказку - PullRequest
0 голосов
/ 09 мая 2020

Страница должна быть обработана до вызова подсказки. В текущей реализации prompt(...) прерывает манипуляции с DOM, а hint отображается только после того, как пользователь нажимает OK в окне подсказки.

Хотя el.innerHTML = 'Please, reply to prompt'; вызывается перед var res = prompt('Hello world');, элемент HTML с id='hint' не будет обновляться, пока пользователь не нажмет OK в окне подсказки.

<!DOCTYPE html>
<script type="text/javascript">
    function callNativeApp() {
        console.log('callNativeApp called');
        try {
            // Show hint message
            var el = document.getElementById('hint'); 
            el.innerHTML = 'Please, reply to prompt';

            // Call prompt            
            var res = prompt('Hello world');

            // Write result of prompt reply to html
            document.getElementById('prompt-call-output').innerHTML = res;
        } catch(err) {
            console.log('The native context does not exist yet');
        }
    }
</script>
<html>
    <head>
    </head>
    <body>
        <button onclick="callNativeApp()">Call native app</button>
        <p id="hint"></p>
        <p id="prompt-call-output"></p>
    </body>
</html>

Как изменить текущий код, чтобы сначала отображалась страница. И только после этого вызывается подсказка ()? Например, каким-то образом заставить дерево DOM обновляться (refre sh) перед вызовом подсказки?

Решение с тайм-аутом для вызова var res = prompt('Hello world');, например,

setTimeout(function() {
    var res = prompt('Hello world');
    document.getElementById('prompt-call-output').innerHTML = res;
}, 100);

, не применимо, поскольку наша текущая кодовая база зависит от последовательности команд, которые идут после вызова prompt(...).

Экран, который показывает, что hint не отображается при вызове подсказки, даже если настройка текстовой подсказки вызывается перед вызовом подсказки: enter image description here

И hint отображается, только когда окно подсказки закрыто:

enter image description here

1 Ответ

0 голосов
/ 09 мая 2020

Это одна из проблем, связанных с сообщениями подсказок, предупреждений и подтверждений, они блокируют выполнение javascript, так как браузер ожидает взаимодействия с пользователем, также считаются плохими реализация UX :

Диалоговые окна являются модальными окнами; они не позволяют пользователю получить доступ к остальной части интерфейса программы, пока диалоговое окно не будет закрыто. По этой причине вам не следует злоупотреблять какой-либо функцией, которая создает диалоговое окно (или модальное окно). в этой ссылке из bluebird адрес, который он использует Promises с диалоговыми окнами asyn c:

function promptPromise(message) {
  var dialog       = document.getElementById('dialog');
  var input        = dialog.querySelector('input');
  var okButton     = dialog.querySelector('button.ok');

  dialog.querySelector('.message').innerHTML = String(message);
  dialog.className = '';

  return new Promise(function(resolve, reject) {
    dialog.addEventListener('click', function handleButtonClicks(e) {
      if (e.target.tagName !== 'BUTTON') { return; }
      dialog.removeEventListener('click', handleButtonClicks);
      dialog.className = 'hidden';
      if (e.target === okButton) {
        resolve(input.value);
      } else {
        reject(new Error('User cancelled'));
      }
    });
  });
}

document.addEventListener('DOMContentLoaded', function() {
  var button = document.getElementById('action');
  var output = document.getElementById('prompt');
  button.addEventListener('click', function() {
    promptPromise('What is your name?').then(function(name) {
      output.innerHTML = '' + name;
    })
    .catch(function() {
      output.innerHTML = '¯\\_(ツ)_/¯';
    });
  });
});
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Async Dislogs Example</title>
  <script src="//cdn.jsdelivr.net/bluebird/3.0.5/bluebird.js"></script>
  <script type="text/javascript">
    document.addEventListener('DOMContentLoaded', function() {
      var time = document.getElementById('time-stamp');
      clockTick();
      setInterval(clockTick, 1000);
      function clockTick() {
        time.innerHTML = '' + new Date();
      }
    });
  </script>
  <style type="text/css">
    #dialog {
      width: 200px;
      margin: auto;
      border: thin solid black;
      padding: 10px;
      background: lightgreen;
    }
    .hidden {
      display: none;
    }
  </style>
</head>
<body>
  <p>The current time is <span id="time-stamp"></span>.</p>
  <p>Your name is <span id="prompt"></span>.</p>
  <button id="action">Set Name</button>
  <div id="dialog" class="hidden">
    <div class="message">foobar</div>
    <input type="text">
    <div>
      <button class="ok">Ok</button>
      <button class="cancel">Cancel</button>
    </div>
  </div>
</body>
</html>

Для вашего фрагмента кода реализация будет примерно такой:

function promptPromise(message) {
  var dialog       = document.getElementById('dialog');
  var input        = dialog.querySelector('input');
  var okButton     = dialog.querySelector('button.ok');

  dialog.querySelector('.message').innerHTML = String(message);
  dialog.className = '';

  return new Promise(function(resolve, reject) {
    dialog.addEventListener('click', function handleButtonClicks(e) {
      if (e.target.tagName !== 'BUTTON') { return; }
      dialog.removeEventListener('click', handleButtonClicks);
      dialog.className = 'hidden';
      if (e.target === okButton) {
        resolve(input.value);
      } else {
        reject(new Error('User cancelled'));
      }
    });
  });
}

document.addEventListener('DOMContentLoaded', function() {
  var button = document.getElementById('action');
  var output = document.getElementById('hint');
  var el = document.getElementById('hint'); 
  
  button.addEventListener('click', function() {
    el.innerHTML = 'Please, reply to prompt';
    promptPromise('Hello world').then(function(name) {
      document.getElementById('prompt-call-output').innerHTML = '' + name;
    })
    .catch(function() {
      output.innerHTML = '¯\\_(ツ)_/¯';
    });
  });
});
#dialog {
  width: 200px;
  margin: auto;
  border: thin solid black;
  padding: 10px;
  background: lightgreen;
}
.hidden {
  display: none;
}
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <button id="action">Call native app</button>
        <p id="hint"></p>
        <p id="prompt-call-output"></p>
        <div id="dialog" class="hidden">
          <div class="message">foobar</div>
          <input type="text">
          <div>
            <button class="ok">Ok</button>
            <button class="cancel">Cancel</button>
          </div>
        </div>
    </body>
</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...