Fancybox (jQuery) - Passing information from parent to iframe and iframe back to parent

I am trying to open a fancybox iframe on my page. Pass over some basic information to the iframe. Then I want to make it so that the iframe talks back to it's parent.

I am passing nameid-1 throughout statically, though I would really like to have this as variable such as: var nameid=$(this).attr('nameid')

I just don't know how to execute this all correctly as I am new to Ajax/Javascript and struggling with the logic.

Base.html

JS:

<script type='text/javascript'>
//<![CDATA[   
// Popup Function
$(document).ready(function () {
    $('a.openinformation').fancybox({
        openEffect: 'fade',
        openSpeed: 500 //,
    });
});
// Update from iFrame
function setInformation(userText) {
    $('#displayfield-nameid-1').html(userText);
    $('#showhide-nameid-1').show();
}
//]]>
</script>

HTML:

<div>
    <a class="openinformation fancybox.iframe" href="iframe.html" nameid= "1" originalname="Mary Poppins"  >Mary Poppins</a>
</div>

<div id ="showhide-nameid-1" style=" display:none; background:#0CF;">
    <p>Replacement Name: <span id="displayfield-nameid-1"></span></p>
</div>

iframe.html

JS :

<script type='text/javascript'>
//<![CDATA[ 
// Start  
$(window).load(function () {
    // When Loaded  get going.
    $(document).ready(function () {
        $('a.doupdate').click(function () {
            parent.setInformation($(this).text());
            parent.$.fancybox.close();
        });
        $('a.closeremove').click(function () {
            parent.$('#showhide-nameid-1').hide();
            parent.$.fancybox.close();
        });
    });
});
//]]>
</script>

HTML

<p>The old name: $originalname;</p>
<p>The id for this column is: $nameid</p>

<p>Please select a new name:</p>
<div><a class="doupdate" href="#">Display new married  name :  Mary Smith</a></div>
<div><a class="doupdate" href="#">Display new married  name:  Sandy Shore</a></div>
<div><a class="closeremove" href="#" id="1">Clear (Hide)  married Names Box</a></div>

Your question can be dived in two parts :

  1. How to pass data (stored in variables) from parent page to an iframe (opened in fancybox)
  2. How to manipulate data (and/or store such data in variables) inside the iframe and then pass those values to the parent page when fancybox is closed.

1). Pass data from parent page to (fancybox) iframe

I think your best choice is to store all your data in a single javascript object like :

var parentData = {};

... so you can pass a single object to the iframe instead of several variables. Then you can add different properties and values to that object like :

parentData.nameid       = "1";
parentData.originalname = "Mary Poppins";

... or more if you need so.

You still may want to pass that information statically through (HTML5) data attributes like :

<a data-nameid="1" data-originalname="Mary Poppins" href="iframe.html" class="openinformation">Mary Poppins</a>

... and push the data values into the parentData object within the fancybox beforeLoad callback like :

beforeLoad : function () {
    parentData.nameid       = $(this.element).data("nameid");
    parentData.originalname = $(this.element).data("originalname");
}

... that would give you much more flexibility IMHO.

Now, the only thing you need to do in the iframed page is to refer to those properties as parent.parentData.nameid and parent.parentData.originalname any time you need them, e.g.

having this html (iframe.html)

<p>The old name: <span id="originalname"></span></p>
<p>The id for this column is: <span id="nameid"></span></p>

... you can use this script to write the values of the parent object like :

$("#nameid").text(parent.parentData.nameid);
$("#originalname").text(parent.parentData.originalname);

Notice you cannot do (as in php)

<p>The old name: $originalname;</p>

... so we used <span> tags to write their content via javascript.


2). Pass data from iframed page to parent page.

First thing you need to do is to declare in your parent page, an object to store data from the iframe and a function to process it like :

var iframeData = {};
function setInformation(data) {
    return iframeData = data;
};

Then in the iframed page, you can write different properties/values to the iframeData object and run the setInformation() function (in the parent page) from the iframe to pass the values to the parent page like :

$(".doupdate").on("click", function (e) {
    e.preventDefault();
    iframeData.newname = $(this).find("span").text(); // set object property/value
    parent.setInformation(iframeData); // pass it to parent page
    parent.$.fancybox.close();
});

The code above assumes you have a similar html like

<a class="doupdate" href="#">Display new married  name :  <span>Mary Smith</span></a>

... notice I wrapped the name I want pass in a span tag. Optionally you could separate it in 2 spans like :

<span class="fname">Mary</span><span class="lname">Smith</span>

... and write them in separated values like :

iframeData.fname = $(this).find("span.fname").text();
iframeData.lname = $(this).find("span.lname").text();

For the clear button, I would just reinitialize the variable and close fancybox like

$('a.closeremove').on("click", function (e) {
    e.preventDefault();
    iframeData = {}; // reset variable
    parent.setInformation(iframeData); // pass it to parent page
    parent.$.fancybox.close();
});

... and perform the manipulation of the parent page from the parent page itself using the fancybox afterClose callback like :

afterClose : function () {
    if ( objLength(iframeData) > 0 ) {
        $('#displayfield-nameid-1').html(iframeData.newname);
        $('#showhide-nameid-1').show();
    } else {
        $("#displayfield-nameid-1").empty();
        $('#showhide-nameid-1').hide();
    }
}

... notice I will only show the selector #showhide-nameid-1 if the iframeData object's length is bigger than 0. Because that, I need a function to validate the object's length :

Based on this answer, you could do:

function objLength(iframeData) {
    // ref https://stackoverflow.com/a/5533226/1055987
    var count = 0, i;
    for (i in iframeData) {
        if (iframeData.hasOwnProperty(i)) {
            count++;
        }
    }
    return count;
};

... which will return the object's length.

Last note :

Since the iframed page is referring to the parent page using the prefix parent, it will return js errors if it's opened outside an iframe. You may want to validate first if the iframed page is actually contained inside an iframe before trying to access data back and forth to/from the parent page like :

if (window.self !== window.top) {
    // the page is inside an iframe
}

See DEMO and feel free to explore the source code of both pages.