[removed] Can data be passed bi-directionally thro

2020-02-15 02:51发布

For anyone with specific knowledge of it, this all relates to the WordPress "Theme Customizer", though that's not necessary to answer this.

Basically, I have a page (in PHP) which contains a left-side "pane" of settings which apply to the contents of an iframe, which is the right portion of the screen.

Conceptually, I'm looking to use jQuery draggable to make the CSS background-position of the main background image adjustable via the draggable function. I need to apply draggable() on the customize.php page, enqueue the script there, and then manipulate the DOM inside the iframe. It needs to be done at the container/parent level because there is a setting at that level which will update the X and Y coordinates and save them in the settings stored there.

I think what I need might be impossible, but I'm wondering if it's possible with javascript to do both of the following:

  1. Get the content of the iframe
  2. Manipulate the DOM inside the iframe, adjust the background image via draggable() and store background-position coordinates as a data-attribute and then save them to the appropriate setting input field.

In my experience, manipulating the DOM inside an iframe from the "parent" / container level is difficult and I'm wondering if there's something I don't know, it's definitely impossible, or there is some workaround? (Note that the originating domain is the same, so there would not be any cross-domain iframe issues)

1条回答
我只想做你的唯一
2楼-- · 2020-02-15 03:04

Here is a reduced code of my test implementation for parent iframe communication. i added some samples how it could be used. But i have to note that it is out of my labs section, and i currently don't have had the time to check if it is fully cross browser compatible. but if it is not there will only be some minor change that are have to be done. (EDIT tested in current chrome, ff and IE 6-9)

I hope this will help you with you problem. But again i cannot guarantee right now that it will work perfectly (but i'm pretty sure).

code of the parent

<!doctype html>
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>index</title>
    <script src="jquery.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" charset="utf-8">

    (function($, window, undefined) {

        var iframe;

        // the connector object the will be passed to the iframe and will be used as "API"
        var parentConnector = {
            _window   : window, // a reference to the parents window (not really necessary but nice to have)
            $ : $,              // a reference to the parents jQuery that can be accessed from the iframe (use with caution)

            // here you will define you "API" for the parent (the functions you want to call from the iframe )
            setElementValue : function(selector, value ) {
                $(selector).val(value);
            }

        }

        // this function is called by the iframe to register the iframe in the parent
        window.registerIFrame = function( iframeHelper ) {
            //if you have multible iframe in the parent you could change the code here to store them in e.g. an arrray or with a key in an object
            iframe = iframeHelper;

            // register the parent in the iframe
            iframe.registerParent(parentConnector);
        }



        $(document).on("click",".slideUp",function(event) {
            event.preventDefault();

            /*
            call a function on the helper object, this is the savest way for the commincation because
            there is it minimizes the risk to mix the differnt context
            */
            iframe.slideUp();

            /*
            This way would work at least in chrome, with the current version with jquery, but it relays the jQuery implementation
            that the correct document is used.
            */
            iframe.$(".info-from-parent").val("slideUp");

            /*
            One thing you should NEVER do is the following:

            iframe.$(".info-from-parent").append( $("<div></div>") );

            The reason you should not do this is because this mixes DOMElements of different context.
            This will result in unexpected crashes/bahaviors in some browsers (but could work in others, or at least it will look like it would work)
            */

        });


        // same as the slide down, it is just there to have some interaction sample
        $(document).on("click",".slideDown",function(event) {
            event.preventDefault();
            iframe.slideDown();
            iframe.$(".info-from-parent").val("slideDown");
        });


    })(jQuery, window);

    </script>
</head>
<body>
    <input type="text" class="info-from-iframe"><br>
    <a href="#" class="slideUp">slideUp</a> <a href="#" class="slideDown">slideDown</a><br>
    <iframe src="iframe.html"></iframe>

</body>
</html>

code of the iframe

<!doctype html>
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>iframe</title>
    <script src="jquery.js" type="text/javascript" charset="utf-8"></script>
    <script>

    (function($,window,undefined) {

        //the connector object the will be passed to the parent and will be used as "API"
        var iframeConnector = {

            _window : window,     // a reference to the iframes window (not really necessary but nice to have)
            _parent : undefined,
            $ : $,                // a reference to the iframes jQuery that can be accessed from the parent (use with caution)

            // this function is called by the parent to register the parent in the iframe
            registerParent : function( parent ) {
                this._parent = parent;
            },

            /* here you will define you "API" for the iframe (the functions you want to call from the parent )*/
            slideUp : function() {
                $(".test").slideUp();
            },

            slideDown : function() {

                $(".test").slideDown();
            },

            setElementValue : function(selector, value ) {
                $(selector).val(value);
            }

        };

        // register the iframe in the parent
        window.parent.registerIFrame(iframeConnector); 

        $(document).mousemove(function(event) {
            //use the parents "API" to call a function in the parent
            iframeConnector._parent.setElementValue(".info-from-iframe", event.clientX+", "+event.clientY);
        });

    })(jQuery,window);


    </script>
</head>
<body>
    <input type="text" class="info-from-parent"><br>
    <div class="test">
        iframe
    </div>
</body>
</html>
查看更多
登录 后发表回答