2017-04-05 21 views
2

我正在使用elm中的端口来访问浏览器的全屏API。在Chrome中一切正常,但在Firefox中不起作用。我得到的错误是:Request for full-screen was denied because Element.mozRequestFullScreen() was not called from inside a short running user-generated event handler. 但是,我认为我理解了错误消息,因为我希望它能够工作,因为我通过单击按钮访问全屏API。中间只有一个榆树港。有没有人解决过这个问题?在elm中使用端口的全屏API在Firefox中不起作用

这是我的榆木代码:

port module Main exposing (..) 

import Html exposing (Html, button, div, text) 
import Html.Events exposing (onClick) 
import Html.Attributes exposing (class) 


main = 
    Html.program { init = init, view = view, update = update, subscriptions = subscriptions } 



-- Model 


type alias Model = 
    { fullscreen : Bool } 


init : (Model, Cmd Msg) 
init = 
    ({ fullscreen = False } 
    , Cmd.none 
    ) 



-- Ports 


port activateFullscreen : String -> Cmd msg 


port deactivateFullscreen : String -> Cmd msg 


subscriptions : Model -> Sub Msg 
subscriptions model = 
    Sub.none 


type Msg 
    = FullscreenMode Bool 



-- Update 


update : Msg -> Model -> (Model, Cmd Msg) 
update msg model = 
    case msg of 
     FullscreenMode on -> 
      let 
       m = 
        { model | fullscreen = on } 
      in 
       if on then 
        (m, activateFullscreen "") 
       else 
        (m, deactivateFullscreen "") 



-- views 


fullScreenButton : Model -> Html Msg 
fullScreenButton model = 
    case model.fullscreen of 
     False -> 
      button [ onClick (FullscreenMode True) ] 
       [ text "fullscreen on" ] 

     True -> 
      button [ onClick (FullscreenMode False) ] 
       [ text "fullscreen off" ] 


view : Model -> Html Msg 
view model = 
    div [ class "app" ] [ fullScreenButton model ] 

和我的html代码:

<!doctype html> 
<html> 
    <head> 
    <meta charset="utf-8"> 
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> 
    <title>Fullscreen Test</title> 
    </head> 
    <body> 
    <div id="main"></div> 
    <script src="main.js"></script> 
    <script> 
     (function() { 
     window.onload = function() { 
      var node = document.getElementById('main'); 
      var app = Elm.Main.embed(node); 
      app.ports.activateFullscreen.subscribe(function() { 
      var element = document.querySelector('.app'); 
      if (element.requestFullscreen) { 
       element.requestFullscreen(); 
      } else if (element.webkitRequestFullscreen) { 
       element.webkitRequestFullscreen(); 
      } else if (element.mozRequestFullScreen) { 
       element.mozRequestFullScreen(); 
      } else if (element.msRequestFullscreen) { 
       element.msRequestFullscreen(); 
      } 
      }); 
      app.ports.deactivateFullscreen.subscribe(function() { 
      if (document.exitFullscreen) { 
       document.exitFullscreen(); 
      } else if (document.webkitExitFullscreen) { 
       document.webkitExitFullscreen(); 
      } else if (document.mozCancelFullScreen) { 
       document.mozCancelFullScreen(); 
      } else if (document.msExitFullscreen) { 
       document.msExitFullscreen(); 
      } 
      }); 
     }; 
     }()); 
    </script> 
    </body> 
</html> 
+0

大概火狐这样做是为了防止网站随意劫持您的屏幕。我很想知道Chrome和IE是否做了类似的事情,但对构成“短时间运行的用户生成的事件处理程序”的内容有不同的看法。正如你所提到的,这最终是由一个按钮点击触发的,但由于中间有一堆Elm生成的代码,所以会有一定程度的间接性。这可能只是Firefox不认为它是“短跑”。 –

+1

在http://stackoverflow.com/a/43297759/2688中有一个解决方法,它使用'window.open',这可能会起作用(只需使用直接JavaScript的字符串'onClick'属性) – bdukes

回答

0

如上bdukes“的评论指出,有一种变通方法这个问题。 我们可以使用我们放在全局窗口对象上的函数,而不是使用端口进行全屏处理。 的按钮产生的榆树代码将是这样的:

button [ onClick (FullscreenMode True), attribute "onClick" "window.enterFullScreen()" ] 
    [ text "fullscreen on" ] 

我仍然会保持榆树的onClick有更新的内部状态。

在JavaScript中,我们可以再定义enterFullScreen功能,并有处理我们的逻辑:

window.enterFullScreen = function() { 
    var element = document.querySelector('.app'); 
    if (element.requestFullscreen) { 
     element.requestFullscreen(); 
    } else if (element.webkitRequestFullscreen) { 
     element.webkitRequestFullscreen(); 
    } else if (element.mozRequestFullScreen) { 
     element.mozRequestFullScreen(); 
    } else if (element.msRequestFullscreen) { 
     element.msRequestFullscreen(); 
    } 
};