Не удалось выполнить «requestFullscreen» в «Элементе». API может быть инициирован только жестом пользователя [дубликат]

Мы оказываемся во вселенной, которая, по-видимому, развивается по измерению, которое мы называем «временем». Мы не понимаем, какое время, но мы разработали абстракции и словарный запас, которые позволяют рассуждать и говорить об этом: «прошлое», «настоящее», «будущее», «до», «после».

Компьютерные системы, которые мы строим - все больше и больше - имеют время как важное измерение. В будущем будут созданы определенные вещи. Тогда другие вещи должны произойти после того, как эти первые вещи в конечном итоге произойдут. Это основное понятие, называемое «асинхронность». В нашем мире с более сложной сетью наиболее распространенный случай асинхронности ожидает, что какая-то удаленная система ответит на какой-либо запрос.

Рассмотрим пример. Вы называете молочника и заказываете молоко. Когда это произойдет, вы хотите положить его в свой кофе. Вы не можете положить молоко в свой кофе прямо сейчас, потому что его еще нет. Вы должны подождать, пока это произойдет, прежде чем положить его в свой кофе. Другими словами, следующее не будет работать:

var milk = order_milk();
put_in_coffee(milk);

Поскольку JS не знает, что ему нужно дождаться окончания order_milk, прежде чем он выполнит put_in_coffee. Другими словами, он не знает, что order_milk является асинхронным - это то, что не приведет к молоку до некоторого будущего времени. JS и другие декларативные языки, выполняйте один оператор за другим, не ожидая.

Классический подход JS к этой проблеме, используя тот факт, что JS поддерживает функции как объекты первого класса, которые могут быть переданы, заключается в передаче функции в качестве параметра для асинхронного запроса, который затем будет вызываться, когда он будет выполнять свою задачу в будущем. Это подход «обратного вызова». Это выглядит так:

order_milk(put_in_coffee);

order_milk запускает, заказывает молоко, тогда, когда и только когда он прибывает, он вызывает put_in_coffee.

Проблема с этот подход обратного вызова состоит в том, что он загрязняет нормальную семантику функции, сообщающей свой результат с помощью return; вместо этого функции должны сообщать свои результаты, вызывая обратный вызов, заданный как параметр. Кроме того, этот подход может быстро стать громоздким при работе с более длинными последовательностями событий. Например, предположим, что я хочу дождаться, когда молоко будет помещено в кофе, а затем и только затем выполните третий шаг, а именно - выпить кофе. В конце концов мне нужно написать что-то вроде этого:

order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }

, где я перехожу к put_in_coffee как к молоку, чтобы положить в него, так и к действию (drink_coffee), чтобы выполнить как только молоко был введен. Такой код становится трудно писать, читать и отлаживать.

В этом случае мы могли бы переписать код в вопросе как:

var answer;
$.ajax('/foo.json') . done(function(response) {
  callback(response.data);
});

function callback(data) {
  console.log(data);
}

Enter обещает

. Это была мотивация для понятия «обещание», которое является особым типом ценности, представляющим собой будущий или асинхронный результат какого-то рода. Он может представлять что-то, что уже произошло, или это произойдет в будущем, или, возможно, никогда не произойдет вообще. Обещания имеют один метод, названный then, которому вы передаете действие, которое должно быть выполнено, когда был достигнут результат, представленный обещанием.

В случае нашего молока и кофе мы создаем order_milk, чтобы вернуть обещание о прибытии молока, затем укажите put_in_coffee как действие then следующим образом:

order_milk() . then(put_in_coffee)

. Одно из преимуществ этого заключается в том, что мы можем объединить их вместе для создания последовательностей будущие вхождения («цепочка»):

order_milk() . then(put_in_coffee) . then(drink_coffee)

Давайте применим обещания к вашей конкретной проблеме. Мы завершим нашу логику запроса внутри функции, которая возвращает обещание:

function get_data() {
  return $.ajax('/foo.json');
}

На самом деле, все, что мы сделали, добавлено к return к вызову $.ajax. Это работает, потому что jQuery $.ajax уже возвращает вид обетоподобной вещи. (На практике, не вдаваясь в подробности, мы предпочли бы обернуть этот вызов, чтобы вернуть реальное обещание, или использовать некоторую альтернативу $.ajax, которая делает это.) Теперь, если мы хотим загрузить файл и дождаться его завершите, а затем сделайте что-нибудь, мы можем просто сказать

get_data() . then(do_something)

, например,

get_data() . 
  then(function(data) { console.log(data); });

. При использовании обещаний мы заканчиваем передачу множества функций в then, поэтому часто полезно использовать более компактные функции стрелок в стиле ES6:

get_data() . 
  then(data => console.log(data));

Ключевое слово async

Но все еще есть что-то неопределенное в том, что нужно писать код одним способом, если синхронно и совершенно по-другому, если асинхронно. Для синхронного мы пишем

a();
b();

, но если a является асинхронным, с обещаниями мы должны написать

a() . then(b);

Выше, мы сказали: «JS не имеет никакого способа узнать что ему нужно дождаться завершения первого вызова, прежде чем он выполнит второй ». Было бы неплохо, если бы можно было сказать JS? Оказывается, существует ключевое слово await, используемое внутри специального типа функции, называемого функцией «async». Эта функция является частью предстоящей версии ES, но уже доступна в транспилерах, таких как Babel, с учетом правильных настроек. Это позволяет нам просто написать

async function morning_routine() {
  var milk   = await order_milk();
  var coffee = await put_in_coffee(milk);
  await drink(coffee);
}

. В вашем случае вы могли бы написать что-то вроде

async function foo() {
  data = await get_data();
  console.log(data);
}
16
задан Marcio Barroso 26 March 2015 в 16:07
поделиться

5 ответов

Вы не можете force показать веб-сайт в полноэкранном режиме.

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

Все JS fullscreen api будут вызывать ошибку, подобную этой: "Failed to execute 'requestFullScreen' on 'Element': API can only be initiated by a user gesture." Если вы попробуйте просто называть его из вашего кода.

Я довольно чертовски уверен, что Flash похож на то, что он требует взаимодействия с пользователем в полноэкранном режиме. В противном случае мы увидели бы нашу долю полноэкранных всплывающих окон, которые почти невозможно закрыть.

20
ответ дан Cerbrus 26 August 2018 в 17:25
поделиться

Другие ответы уже описывают, как вы можете перейти в полноэкранный режим более или менее независимым от браузера способом. Однако проблема взаимодействия с пользователем остается.


Вы не можете заставить свою веб-страницу отображаться в полноэкранном режиме по соображениям безопасности. Для этого требуется взаимодействие с пользователем.

Кроме того, браузер покидает полноэкранный режим, когда пользователь переходит на другую страницу, даже на том же веб-сайте, и (ей) ему придется выполнять «взаимодействие с пользователем» на каждой странице чтобы вернуться в полноэкранный режим. Вот почему ваш сайт должен быть одной страницей, если вы хотите, чтобы он был полноэкранным.


Вот что я предлагаю: используйте одну страницу всплеска, у которой есть скрытый iFrame на нем.

Всякий раз, когда пользователь щелкает в любом месте или нажимает любую клавишу, просто установите этот iFrame в полноэкранный режим и покажите его. Когда вы получаете событие при выходе из полноэкранного режима, снова скройте iFrame, чтобы отобразить всплеск.

Ссылки открываются в том же кадре по умолчанию, поэтому вы останетесь в полноэкранном режиме, пока пользователь явно не покинет его или некоторые ссылки не откроются новая вкладка.

Вот пример, который работает в Chrome: ( См. его в действии. Используйте другие ответы, чтобы сделать его независимым от браузера.)

<html>
<head>
    <script language="jscript">
        function goFullscreen() {
            // Must be called as a result of user interaction to work
            mf = document.getElementById("main_frame");
            mf.webkitRequestFullscreen();
            mf.style.display="";
        }
        function fullscreenChanged() {
            if (document.webkitFullscreenElement == null) {
                mf = document.getElementById("main_frame");
                mf.style.display="none";
            }
        }
        document.onwebkitfullscreenchange = fullscreenChanged;
        document.documentElement.onclick = goFullscreen;
        document.onkeydown = goFullscreen;
    </script>
</head>
<body style="margin:0">
    <H1>Click anywhere or press any key to browse <u>w3schools</u> in fullscreen.</H1>
    <iframe id="main_frame" src="http://www.w3schools.com" style="width:100%;height:100%;border:none;display:none"></iframe>
</body>
</html>

PS Мне нравится ссылка, предоставленная @jsve выше, и это еще лучше: изменить вашу ОС :). Кроме того, я не веб-разработчик. Просто подумал, что этот вопрос будет интересен для исследования.

5
ответ дан EvgEnZh 26 August 2018 в 17:25
поделиться

Возможно, вы сможете использовать методы requestFullScreen (), как описано в https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode .

Примечание: для этого все еще требуется вход пользователя - но избегайте использования вспышки.

function toggleFullScreen() {
  if (!document.fullscreenElement &&    // alternative standard method
      !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement ) {  // current working methods
    if (document.documentElement.requestFullscreen) {
      document.documentElement.requestFullscreen();
    } else if (document.documentElement.msRequestFullscreen) {
      document.documentElement.msRequestFullscreen();
    } else if (document.documentElement.mozRequestFullScreen) {
      document.documentElement.mozRequestFullScreen();
    } else if (document.documentElement.webkitRequestFullscreen) {
      document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
    }
  } else {
    if (document.exitFullscreen) {
      document.exitFullscreen();
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen();
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen();
    }
  }
}

toggleFullScreen();

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

3
ответ дан Kami 26 August 2018 в 17:25
поделиться

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

 onClick="window.open('pageName.html', 'test', 'fullscreen=yes')"

Это не является полнофункциональным, но работает лучше, чем любые другие методы, которые я нашел. Вероятно, вы не сможете это сделать без взаимодействия с пользователем, поэтому использование чего-то вроде всплывающего экрана позволяет свести к минимуму вторжение в нечто более общепринятое.

1
ответ дан Nicholas 26 August 2018 в 17:25
поделиться

Это не совсем то, что искали OP, но в моей конкретной ситуации я нашел комбинацию режима киоска и некоторого динамического стиля для работы.

Я искал, чтобы запустить браузер с конкретный URL-адрес и запустить его в полноэкранном режиме. Вариант использования практически не влияет на взаимодействие пользователя на терминале на заводе-изготовителе со статусом. После включения питания он должен отображать только статус без взаимодействия (т. Е. Отображать ни один из элементов интерфейса конфигурации, если пользователь не взаимодействует).

Возможно, не реалистично на сложном сайте, но мое использование было конкретным " панель "(div в этом случае). Чтобы сфокусироваться на конкретном div, я спрятал другие div и установил соответствующие стили. Если происходит взаимодействие пользователя с изменением от и до полноэкранного режима, я (1) использую обычный файл myElement. * RequestFullScreen (). * ExitFullscreen () вызывает, (2) показывает / скрывает другие divs и (3) переключатель между классами ниже:

.right-pane-fullscreen
{
    margin-left: 0px;
}

.right-pane-normal
{
    margin-left: 225px;
}

Связанное обсуждение того, как использовать режим киоска в Chrome (имейте в виду, что другие процессы Chrome, запущенные до запуска режима киоска, могут помешать этому работать) Открытие браузера Chrome в режиме полного окна или киоска на окнах 7

0
ответ дан pigeon 26 August 2018 в 17:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: