Javascript: как временно отключить все действия на странице?

на странице с событием Ajax я хочу отключить все действия, пока не вернется вызов Ajax(чтобы предотвратить проблемы с двойной отправкой и т. д.)

я попробовал это, добавивreturn false; к текущим событиям onclick при "блокировке" страницы и удалении этого позже при "разблокировке" страницы. Однако действия больше не активны после того, как они" разблокированы " - вы просто не можете вызвать их.

почему это не работает? См. пример ниже. Любая другая идея для достижения моя цель?

пример кода:
и ссылка, и кнопка показывают предупреждение JS; при нажатии lock, а затем разблокировать обработчик событий такой же, как и раньше, но не работает...?!?
Код предназначен для работы с Тринидадом в конце концов, но должен работать и снаружи.

<html><head><title>Test</title>

<script type="text/javascript">
function lockPage()
{
  document.body.style.cursor = 'wait';
  lockElements(document.getElementsByTagName("a"));
  lockElements(document.getElementsByTagName("input"));

  if (typeof TrPage != "undefined")
  {
    TrPage.getInstance().getRequestQueue().addStateChangeListener(unlockPage);
  }
}

function lockElements(el)
{
  for (var i=0; i<el.length; i++)
  {
    el[i].style.cursor = 'wait';
    if (el[i].onclick)
    {
      var newEvent = 'return false;' + el[i].onclick;
      alert(el[i].onclick + "nnlock -->nn" + newEvent);
      el[i].onclick = newEvent;
    }
  }
}

function unlockPage(state)
{
  if (typeof TrRequestQueue == "undefined" || state == TrRequestQueue.STATE_READY)
  {
    //alert("unlocking for state: " + state);
    document.body.style.cursor = 'auto';
    unlockElements(document.getElementsByTagName("a"));
    unlockElements(document.getElementsByTagName("input"));
  }
}

function unlockElements(el)
{
  for (var i=0; i<el.length; i++)
  {
    el[i].style.cursor = 'auto';
    if (el[i].onclick && el[i].onclick.search(/^return false;/)==0)
    {
      var newEvent = el[i].onclick.substring(13);
      alert(el[i].onclick + "nnunlock -->nn" + newEvent);
      el[i].onclick = newEvent;
    }
  }
}
</script>

<style type="text/css">
</style>
</head>

<body>

<h1>Page lock/unlock test</h1>

<p>Use these actions to lock or unlock active elements on the page:
<a href="javascript:lockPage()">lock</a>,
<a href="javascript:unlockPage()">unlock</a>.</p>

<p>And now some elements:</p>

<a onclick="alert('This is the action!');return false;" href="#">link action</a> &nbsp;
<input type="button" value="button action" onclick="alert('This is another action!')"/>
</body>
</html>

Спасибо, ребята, за ваши идеи и ответы.

теперь я вижу, что я перепутал строки и функции, которые, очевидно, не может работать ;(

Я должен был дать понять, что мы используем некоторые веб-библиотеки FW и тегов (Trinidad), которые создают код обработки событий (и Ajax), поэтому я не могу редактировать это напрямую или использовать синхронный Ajax и т. д.

кроме того, Ajax-это только один сценарий, в котором этот код должен быть выполнен. Его цель-запретить пользователю дважды отправлять страницу / действие, что также актуально для не-Ajax-страниц, где вы можете нажать кнопку doulbe. Я знаю, что это не совсем безопасно, и это только должно быть "удобство", чтобы избежать слишком частого получения страницы ошибки навигации (у нас есть защита на стороне сервера, конечно).

Итак, попробуем наложение div, вероятно.

еще раз спасибо,
Кристоф.

5 ответов


как насчет настройки глобального var

actions_disabled = 0

инкремент при запуске вызова AJAX затем декремент, когда он заканчивается. Все ваши обработчики" действий " могут начать с

if (actions_disabled) return false;

гораздо проще, чем отладка самомодифицирующегося кода!

кроме того, чтобы заблокировать элементы управления, вы можете установить:

control.disabled="disabled"

который будет иметь бонус серого их, что делает его очевидным для пользователя, что они не могут представить. Чтобы разблокировать, просто set:

control.disabled=""

новая идея, основанная на комментариях (не может цитировать код в комментариях, он появляется ...):

вы всегда можете просто повесить дополнительные атрибуты с объектов Javascript:

чтобы заблокировать, вы могли:

control.onclick_old = control.onclick
control.onclick = "return false;"

чтобы разблокировать, вы можете:

control.onclick = control.onclick_old

Я однажды достиг этой цели, создав DIV, который охватывал область, которую я хотел отключить, установив его z-index выше, чем любой из других элементов на странице, а затем установка его opacity to 0. По умолчанию этот DIV был скрыт display: none, чтобы это ни во что не вмешивалось. Однако, когда я хотел, чтобы область была отключена, я просто установил ее display до block.

Стив


"Аякса". Асинхронный. Просто сделайте запрос HTTP синхронным. Проблема решена.


проблема с вашим кодом является результатом того, что вы не справляетесь с типами в javascript.

когда вы говорите:

var newEvent = 'return false;' + el[i].onclick

это принуждает el[i].onclick (который является функцией) в строку, а затем объединяет ее со строкой " return false;". Затем, когда вы переназначаете его так:

el[i].onclick = newEvent;

onclick, который ранее был функцией, теперь является строкой.

затем вы пытаетесь воскресить свою старую функцию из строки, взяв подстрока:

var newEvent = el[i].onclick.substring(13);

что нормально, за исключением newEvent все еще строка! Поэтому, когда вы снова назначаете его onclick, вы назначаете строковое представление исходной функции, а не саму функцию.

вы можете использовать eval для оценки строки и возврата функции, но, пожалуйста, не делайте этого. Есть несколько лучших способов сделать это, как было предложено другими комментаторами.

Я также хотел бы спросить, почему вы хотите использовать AJAX вообще если вы не хотите разрешать асинхронные запросы.


использование оверлея div не мешает пользователю вводить вкладку на вашу страницу. Обычно это нормально, так как большинство пользователей не вкладывают через страницу в любом случае.

Если вы используете какие-либо сочетания клавиш на своей странице, они все равно будут доступны, поэтому для них потребуется отдельная обработка.

Alse, я предполагаю, что щелчок элемента, который может иметь фокус (например. Ан <a> tag), затем нажав enter, все равно вызовет двойную отправку.