13
respostas

Situação estranha no escopo javascript

Olá boa tarde! Só pra entender um problema estranho com escopo a situação seria a seguinte: Tenho um projeto javascript e quero usar dentro dele a API do iframe do youtube. Porém acontece algo estranho com o escopo desta API e ela fica fora do escopo e não consigo usar ela dentro por exemplo de alguma função. Veja o exemplo abaixo ao tentar usar dentro de uma função mesmo se eu passar variáveis por parametros não funciona. Sabe explicar porque este problema de escopo acontece, já que posso passar por parâmetros até mesmo a var global window e porque não consigo passar o escopo desta API para dentro de uma função para usar em projetos variados? Segue um exemplo com a API e abaixo uma função auto executável onde não está sendo possível usar o escopo/API. Obrigado pela atenção.

<!doctype html>
<html lang="en">
<head>
</head>
<body>

<div id="player"></div>

<script type="text/javascript">
    var tag = document.createElement('script');
    tag.src = "//www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    var player;  //<iframe width="1920" height="1080" src="https://www.youtube.com/embed/k7IPr-rhrPE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

    function onYouTubeIframeAPIReady () {
        player = new YT.Player('player', {
            width: '682',
            height: '383',
            videoId: 'k7IPr-rhrPE',
            playerVars: {
                'controls' : 0,
                'modestbranding' : 1,
                'rel' : 0,
                'showinfo' : 0,

            },
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
            }
        });
    }
    var ready = false;
    function onPlayerReady(event) {
        ready = true;
    }

    function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.PLAYING) {
            // Video playing
        } else {
            //Video has paused
        }
    }

    function stopVideo() {
        player.stopVideo();
    }

    function playVideo() {
        if(ready) player.playVideo();
        else setTimeout(function(){ playVideo() },1000);
    }
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-+-
    (function (w) {

        //AQUI DENTRO API NÃO FUNCIONA

    })(window);
</script>
</body>
</html>
13 respostas

Oi Rogério tudo bem?

Pelas regras da internet você não pode controlar um site em outro domínio usando javascript a não ser que aquele site dê permissão ao seu site.

Isso evita o usuário abrir uma página maliciosa com um iframe de um site de terceiro com campo de login e senha e a página maliciosa roubar os dados digitados no iframe.

Espero ter ajudado!!!

Olá André entendi esta situação de regra da internet apesar que podemos fazer um iframe direto sem usar a API mas o problema seria que não teríamos alguns recursos como por exemplo um evento informando que acabou o video porém usando alguns players que suportam a API isso é possível. Mas usei este exemplo da API do youtube para fins didáticos para entender mais sobre o escopo em javascript. Eu poderia também fazer isso que foi feito ou seja posso proteger um iframe ou uma instanciação do meu código do meu site com determinado conteúdo de forma a não disponibilizar escopo como acontece no exemplo? É possível me dar um exemplo prático de como protejo meu código ou instanciação como feito no API? Ou um exemplo prático de como consigo contornar este esta proteção para fins exclusivamente didáticos? Obrigado pela atenção...

Atualmente não dá para contornar com iframe pois todas as falhas já foram corrigidas pelos navegadores. Se existe alguma forma de burlar eu não sei dizer.

Consegui fazer a API funcionar dentro da minha função anônima auto-executável :) veja no código abaixo;

 var tag = document.createElement('script');
    tag.src = "//www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);



    var player;  //<iframe width="1920" height="1080" src="https://www.youtube.com/embed/k7IPr-rhrPE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

    /*function onYouTubeIframeAPIReady () {
        player = new YT.Player('player', {
            width: '682',
            height: '383',
            videoId: 'k7IPr-rhrPE',
            playerVars: {
                'controls' : 0,
                'modestbranding' : 1,
                'rel' : 0,
                'showinfo' : 0,

            },
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
            }
        });
    }*/
    var ready = false;
    function onPlayerReady(event) {
        ready = true;
    }

    function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.PLAYING) {
            // Video playing
        } else {
            //Video has paused
        }
    }

    function stopVideo() {
        player.stopVideo();
    }

    function playVideo() {
        if(ready) player.playVideo();
        else setTimeout(function(){ playVideo() },1000);
    }
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-+-
    (function (w) {

        //AQUI DENTRO API NÃO FUNCIONA
        w.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady () {
            w.player = new YT.Player('player', {
                width: '682',
                height: '383',
                videoId: 'k7IPr-rhrPE',
                playerVars: {
                    'controls' : 0,
                    'modestbranding' : 1,
                    'rel' : 0,
                    'showinfo' : 0,

                },
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                }
            });
        }
    })(window);

E também colocando o resto dos códigos dentro da função :)

<script type="text/javascript">
    var tag = document.createElement('script');
    tag.src = "//www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);



    //var player;  //<iframe width="1920" height="1080" src="https://www.youtube.com/embed/k7IPr-rhrPE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

    /*function onYouTubeIframeAPIReady () {
        player = new YT.Player('player', {
            width: '682',
            height: '383',
            videoId: 'k7IPr-rhrPE',
            playerVars: {
                'controls' : 0,
                'modestbranding' : 1,
                'rel' : 0,
                'showinfo' : 0,

            },
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
            }
        });
    }*/


   /* var ready = false;
    function onPlayerReady(event) {
        ready = true;
    }

    function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.PLAYING) {
            // Video playing
        } else {
            //Video has paused
        }
    }

    function stopVideo() {
        player.stopVideo();
    }

    function playVideo() {
        if(ready) player.playVideo();
        else setTimeout(function(){ playVideo() },1000);
    }*/
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-+-
    (function (w) {

        //AQUI DENTRO API NÃO FUNCIONA
        w.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady () {
            w.player = new YT.Player('player', {
                width: '682',
                height: '383',
                videoId: 'k7IPr-rhrPE',
                playerVars: {
                    'controls' : 0,
                    'modestbranding' : 1,
                    'rel' : 0,
                    'showinfo' : 0,

                },
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                }
            });
        }



        w.ready = false;
        w.onPlayerReady = function onPlayerReady(event) {
            w.ready = true;
        }

        w.onPlayerStateChange = function onPlayerStateChange(event) {
            if (w.event.data == w.YT.PlayerState.PLAYING) {
                // Video playing
            } else {
                //Video has paused
            }
        }

        w.stopVideo = function stopVideo() {
            w.player.stopVideo();
        }

        w.playVideo = function playVideo() {
            if(ready) w.player.playVideo();
            else setTimeout(function(){ w.playVideo() },1000);
        }
    })(window);

Legal!!! Gostei do código! Continue assim e bons estudos!!!

Até a cdn da API ou seja agora posso usar esta API dentro dos meus projetos :)

<script src="https://www.youtube.com/iframe_api"></script>
<script type="text/javascript">
   /* var tag = document.createElement('script');
    tag.src = "//www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);*/



    //var player;  //<iframe width="1920" height="1080" src="https://www.youtube.com/embed/k7IPr-rhrPE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

    /*function onYouTubeIframeAPIReady () {
        player = new YT.Player('player', {
            width: '682',
            height: '383',
            videoId: 'k7IPr-rhrPE',
            playerVars: {
                'controls' : 0,
                'modestbranding' : 1,
                'rel' : 0,
                'showinfo' : 0,

            },
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
            }
        });
    }*/


   /* var ready = false;
    function onPlayerReady(event) {
        ready = true;
    }

    function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.PLAYING) {
            // Video playing
        } else {
            //Video has paused
        }
    }

    function stopVideo() {
        player.stopVideo();
    }

    function playVideo() {
        if(ready) player.playVideo();
        else setTimeout(function(){ playVideo() },1000);
    }*/
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-+-
    (function (w) {

        //AQUI DENTRO API NÃO FUNCIONA
        w.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady () {
            w.player = new YT.Player('player', {
                width: '682',
                height: '383',
                videoId: 'k7IPr-rhrPE',
                playerVars: {
                    'controls' : 0,
                    'modestbranding' : 1,
                    'rel' : 0,
                    'showinfo' : 0,

                },
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                }
            });
        }



        w.ready = false;
        w.onPlayerReady = function onPlayerReady(event) {
            w.ready = true;
        }

        w.onPlayerStateChange = function onPlayerStateChange(event) {
            if (w.event.data == w.YT.PlayerState.PLAYING) {
                // Video playing
            } else {
                //Video has paused
            }
        }

        w.stopVideo = function stopVideo() {
            w.player.stopVideo();
        }

        w.playVideo = function playVideo() {
            if(ready) w.player.playVideo();
            else setTimeout(function(){ w.playVideo() },1000);
        }
    })(window);
</script>

Valeu um abraço a por tentar ajudar! Fui fazendo testes e isso é um exemplo que podemos superar muitos desafios é só ter persistência. Este seria um excelente exemplo a ser usado nos cursos de javascript quando se tratar de assunto de escopo. Bons estudos...

Disponha e bons estudos!!!

Boa noite, Rogério! Como vai?

Eu não entendi muito bem o que vc quis dizer sobre escopo e a não possibilidade de utilizar a API dentro da IIFE, até pq vc não exemplificou em forma de código o que não estava funcionando inicialmente! Inclusive, se vc quiser tirar esse assunto a limpo é só dizer que eu te ajudo! Mande aqui um exemplo de código que vc estava tentando fazer e que não estava dando certo e eu tentarei te guiar à luz do conhecimento!

Contudo, o que precisa ficar registrado e que é muito importante é que no mundo JavaScript existem apenas dois tipos de escopo: global e funcional! Tudo que está fora de uma função é de escopo global ( podendo ser utilizado/sobrescrito em qualquer lugar, inclusive em outros arquivos ). Já o que está dentro de uma função somente pode ser acessado dentro dela mesma!

Pegou a ideia? Qualquer coisa é só falar!

Grande abraço e bons estudos, meu aluno!

Olá boa tarde professor! No primeiro código que mandei(segue código repetido abaixo) a API está fora da IIFE então funciona, porém se colocar a API dentro da IIFE a mesma deixava de funcionar , depois descobri que pra funcionar dentro de outra função é necessário atribuir as funções variaveis com mesmo nome e sempre colocando: window.nomefunção e para variáveis window.nomevar. Sei que não é uma boa prática usar variaveis globais porém no caso desta API se não fizer isso não funciona dentro de outra função entendeu? Esta foi a única maneira que consigo fazer funcionar dentro de uma função, mas se tiver outra dica de como fazer funcionar sem usar deste modo global a dica será bem vinda. Um abraço.

<!doctype html>
<html lang="en">
<head>
</head>
<body>

<div id="player"></div>

<script type="text/javascript">
    var tag = document.createElement('script');
    tag.src = "//www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    var player;  //<iframe width="1920" height="1080" src="https://www.youtube.com/embed/k7IPr-rhrPE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

    function onYouTubeIframeAPIReady () {
        player = new YT.Player('player', {
            width: '682',
            height: '383',
            videoId: 'k7IPr-rhrPE',
            playerVars: {
                'controls' : 0,
                'modestbranding' : 1,
                'rel' : 0,
                'showinfo' : 0,

            },
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
            }
        });
    }
    var ready = false;
    function onPlayerReady(event) {
        ready = true;
    }

    function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.PLAYING) {
            // Video playing
        } else {
            //Video has paused
        }
    }

    function stopVideo() {
        player.stopVideo();
    }

    function playVideo() {
        if(ready) player.playVideo();
        else setTimeout(function(){ playVideo() },1000);
    }
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-+-
    (function (w) {

        //AQUI DENTRO API NÃO FUNCIONA

    })(window);
</script>
</body>
</html>

Opa, Rogério! Então, o que não ficou claro é quem é essa tal de API que vc queria acessar dentro da IIFE. No seu código vc escreveu //AQUI DENTRO API NÃO FUNCIONA, mas quem é API? É uma variável? É uma função? Por isso eu te pedi um exemplo de código que vc queria que funcionasse no lugar desse comentário feito no código mas que na prática não funcionou.

Se vc puder mandar esse exemplo pra que eu possa entender poderei tentar te ajudar de forma mais efetiva!

Veja abaixo o exemplo, porém agora não vai funcionar:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Api Youtube</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

</head>
<body>


<div id="player"></div>

<script type="text/javascript">
    var tag = document.createElement('script');
    tag.src = "//www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    var player;  //<iframe width="1920" height="1080" src="https://www.youtube.com/embed/k7IPr-rhrPE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


    //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-+-
    (function () {

        function onYouTubeIframeAPIReady () {
            player = new YT.Player('player', {
                width: '682',
                height: '383',
                videoId: 'k7IPr-rhrPE',
                playerVars: {
                    'controls' : 0,
                    'modestbranding' : 1,
                    'rel' : 0,
                    'showinfo' : 0,

                },
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                }
            });
        }
        var ready = false;
        function onPlayerReady(event) {
            ready = true;
        }

        function onPlayerStateChange(event) {
            if (event.data == YT.PlayerState.PLAYING) {
                // Video playing
            } else {
                //Video has paused
            }
        }

        function stopVideo() {
            player.stopVideo();
        }

        function playVideo() {
            if(ready) player.playVideo();
            else setTimeout(function(){ playVideo() },1000);
        }

    })();
</script>
</body>
</html>