Sozi icon indicating copy to clipboard operation
Sozi copied to clipboard

Unable to control my embedded Sozi form outside the <iframe> as described in the documentation

Open SirClickALot opened this issue 2 years ago • 4 comments

Summary of your problem or feature request

I cannot seem to control my embedded Sozi form outside the

I am Sozi 23.07.25-1690311612

I use a drawing program called Xara Designer Pro+ but I include that info here purely for compliance as there is no problem with SVG itself.

Steps to reproduce the problem

Understanding the guidance on embedding

I have read and understood the guidance (https://sozi.baierouge.fr/pages/tutorial-embedding.html) on communicating with a Sozi when it is embedded in an an IFRAME and below is the

<iframe id="sozi-frame"src="https://sirclickalot.co.uk/assets/books/gcse-computer-science-plus/chapters/computer-systems/topics/introduction-to-computer-systems/journeys/the-basic-computer-system-process-breakdown/braille-to-english-landscape.sozi.html" width="100%" height="100%" frameborder="0" scrolling="auto"></iframe>

This all seems to work exactly as expected.

Why have I given the

You will notice that I have given the

var sozi_frame = document.getElementById("sozi-frame");

I can 'see' this

Here is the full tweaked version of my javascript - I am not interested in the Sozi frame titles so mine is slightly cut down from the guidance example...

<script>
    var sozi_frame = document.getElementById("sozi-frame");
    var sozi_player = sozi_frame.contentWindow.sozi.player;
    alert(sozi_player);

    var btnPrev   = document.getElementById("btn-prev");
    var btnNext   = document.getElementById("btn-next");

    btnPrev.addEventListener("click", function () {
        player.moveToPrevious();
    }, false);

    btnNext.addEventListener("click", function () {
        player.moveToNext();
    }, false);    
</script>

NOTE the crude but illustrative alert() on the third line - we never reach this point because the value of sozi_player is null.

The Javascript console reports...

Uncaught TypeError: Cannot read properties of undefined (reading 'player')

I am at a loss here, can anyone please help me to see what I'm missing?

Why does my sozi_player frame appear to be missing its .player?

Resources for anyone who can help

HERE is the working HTML that tries to target the 'player' using the grey btnNext and btnPrev at the bottom right corner.

HERE is an archive of my Sozi for reference.

Thanks all, getting this solved will open the doors to me using and promoting Sozi widely in our open source education project so I would be very grateful for any advice given.

SirClickALot avatar Jul 30 '23 05:07 SirClickALot

There is an important difference between your code and the tutorial. In the tutorial, the script is inserted in:

window.addEventListener("load", function () {
    ...
}, false);

Have you tried this?

I suspect that your script is executed too early. It tries to access sozi_frame.contentWindow.sozi before it has been assigned. The tutorial works because it waits until the content of the iframe is fully loaded and the Sozi presentation is ready to play.

aumouvantsillage avatar Aug 08 '23 19:08 aumouvantsillage

Thank you very much for responding Guillaume - great spot - obvious now you've pointed it out but many thanks for helping me to move this on.

I have managed now to get my NEXT frame external button working perfectly as is demonstrated here very convincingly but for some reason that I cannot explain, the PREVIOUS frame button fails because JavaScript is reporting...

Uncaught TypeError: player.moveToPrevious is not a function

Which cannot be right because I'm pretty sure the function exists in the player.

Here is the full code with plenty of console.debug lines to verify that everything is firing as it should be...

<iframe
    src="my-sozi.html"
    width="100%"
    height="100%"
    frameborder="0"
    scrolling="auto">
</iframe>

<script>
    window.addEventListener("load", function() {

        // Get the <iframe>
        var frame = document.querySelector("iframe");
        // Give it keyboard focus
        frame.focus()

        // Get the 'player' object from the Sozi content
        var player = frame.contentWindow.sozi.player;
        console.log("Here is the 'player' object...");
        console.log(player);

        // Get the PREVIOUS button (in my case, a <span>)
        var btnPrev = document.getElementById("btn-prev");
        console.log("Here is the 'PREVIOUS frame button' object...");
        console.log(btnPrev);

        // Add a listener to watch for mouse clicks
        btnPrev.addEventListener("click", function() {
            player.moveToPrevious();
            console.log("Moving to PREVIOUS frame");
        }, false);
        console.log("Added the PREVIOUS button listener");

        // Get the NEXT button (in my case, a <span>)
        var btnNext = document.getElementById("btn-next");
        console.log("Here is the 'NEXT frame button' object...");
        console.log(btnNext);

        // Add a listener to watch for mouse clicks
        btnNext.addEventListener("click", function() {
           player.moveToNext();
           console.log("Moving to NEXT frame");
        }, false);
        console.log("Added the NEXT button listener");

    }, false);
</script>

<style>
    #btn-prev, #btn-next {
        cursor: pointer;
    }
    #btn-prev:hover, #btn-next:hover {
        filter: brightness(0) saturate(100%) invert(37%) sepia(7%) saturate(4533%) hue-rotate(147deg) brightness(98%) contrast(75%);
    }
</style>

If anyone can spot the problem, I'd be very grateful - I'm ALMOST there!

SirClickALot avatar Aug 12 '23 10:08 SirClickALot

Which cannot be right because I'm pretty sure the function exists in the player.

I was also pretty sure it existed until I checked. I don't remember the exact reasons but I think that it was removed when the PlayerController class was introduced to help create presentations that can be controlled remotely. I have forgotten to update the documentation.

Can you try this simple change and tell me how it works for you?

var player = frame.contentWindow.sozi.playerController;

aumouvantsillage avatar Aug 14 '23 14:08 aumouvantsillage

That's it - 100% fixed! Thank you very much for that. As a result of this, it's probably worth updating the documentation page.

Here is my first successful embedded Sozi in action; there will be more.

SirClickALot avatar Aug 15 '23 04:08 SirClickALot