1

I'm trying to do something with iframes and am struggling a little bit at the moment. Basically, I have a script that generates a grid of squares (image below) and I want to make it so that when I click on a square, I display something in a different iframe.

So for instance, say I had frame 1 (which contains the grid) and frame 2 (this is the "display" frame). If I click the top left square, then I want to display "index(0,0)" in the display frame. If I click the (1, 1) square, then I want to display "index(1,1)" and so on.

I already know how to do this within the same frame (ie I can display "index(0,0)" within frame 1 if I click on a square in frame 1), but I am just confused on how to do this in a separate frame. I've tried quite a few things but nothing seems to be working.

I will include all of my code below as well as a picture for your reference. Any help is greatly appreciated!

Javascript:

// I know this isnt good coding practice, but I was getting desperate
// trying things xD
var currentDisplay = "display";

function changeSquare() {
    var image = document.getElementById(this.id);

    // If image is currently green square, change to red, and vice versa
    if (image.src.match("http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png")) {
        image.src = "http://www.clker.com/cliparts/1/J/s/o/7/y/red-square-button-md.png";
    } else {
        image.src = "http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png";
    }
    currentDisplay = this.id;
};

function printInfo() {
    document.write(currentDisplay);
}

// Creates a grid of dimensions width by height
function makeGrid(height, width) {

    // Loop over height and width to create black square objects with
    // buttons in middle
    for (i = 0; i < height; i++) {
        for (j = 0; j < width; j++) {
            // Outer div is black square
            var div = document.createElement("div");
            div.className = "square";
            div.id = ("div").concat(i,",", j);

            var innerDiv0 = document.createElement("div");
            innerDiv0.className = "content";
            div.id = ("innerDiv0").concat(i,",", j);
            div.appendChild(innerDiv0);

            // InnerDiv1 & 2 are table structures (necessary for alignment)
            var innerDiv1 = document.createElement("div");
            innerDiv1.className = "table";
            div.id = ("innerDiv1").concat(i,",", j);
            innerDiv0.appendChild(innerDiv1);

            var innerDiv2 = document.createElement("div");
            innerDiv2.className = "table-cell";
            div.id = ("innerDiv2").concat(i,",", j);
            innerDiv1.appendChild(innerDiv2);

            // Add green square image
            var image = document.createElement("img");
            image.id = ("image").concat(i,",", j);
            image.src = "http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png"; 
            image.className = "rs";
            innerDiv2.appendChild(image);
            document.body.appendChild(div);

            // Add onclick feature
            image.onclick = changeSquare;
        }
    }
};

GridTest.html

<head>
  <link rel="stylesheet" type="text/css" href="GridTest.css">
</head>

<body>
        <script src="GridTest.js">
        </script>
        <script>
            makeGrid(20, 20);
        </script>
</body>

displayPanel.html

<head>
  <link rel="stylesheet" type="text/css" href="GridTest.css">
</head>

<body>
        <script src="GridTest.js">
        </script>
        <script>
            printInfo();
        </script>
</body>

nestTest.html (here is where I create the iframes)

<head>
  <link rel="stylesheet" type="text/css" href="GridTest.css">
  <script src = "GridTest.js"> </script>
</head>


<iframe id="frame1" scrolling="no" src="GridTest.html">
</iframe>

<iframe id="frame2" scrolling="no" src="displayPanel.html"></iframe>

CSS (probably unnecessary but I'll include it anyways)

.square {
    float:left;
    position: relative;
    width: 5%;
    padding-bottom: 2.8125%;
    background-color:#1E1E1E;
    overflow:hidden;
    outline: 1px solid #FFFFFF;
}

.whiteSquare {
    float:left;
    position: relative;
    width: 5%;
    padding-bottom: 2.8125%;
    background-color:#FFFFFF;
    overflow:hidden;
    outline: 1px solid #FFFFFF;
}

/*
 Aspect ratio  |  padding-bottom  |  for 30% width
------------------------------------------------
    1:1        |  = width         |    30%
    1:2        |  width x 2       |    60%
    2:1        |  width x 0.5     |    15%
    4:3        |  width x 0.75    |    22.5%
    16:9       |  width x 0.5625  |    16.875%
    */

.content {
    position:absolute;
    height:40%;
    width:47%;
    padding: 5% 26.5%;
    text-align:center;
}

.content .rs{
    width:auto;
    height:auto;
    max-height:90%;
    max-width:100%;
}

.table{
    display:table;
    height:100%;
    width:100%;
}

.table-cell{
    display:table-cell;
    vertical-align:middle;
    height:100%;
    width:100%;
}

body {
    font-size:20px;
    font-family: 'Lato',verdana, sans-serif;
    color: #000000;
    background:#ECECEC;
}

.numbers{
    font-weight:900;
    font-size:100px;
}

Picture of current result.

  • 1
    Why are you iFraming your own code? Why not just load it normally? – Matthew Herbst Dec 31 '15 at 23:36
  • I thought it would be best to use iframe to lay things out easier, just because the way I created the grid makes it a bit difficult to just lay things out normally. I wanted to nest the grid within a larger structure (if that makes sense) and I figured this would be the best way to do that. I'm starting to think it might not be, though. – RohanShankar Dec 31 '15 at 23:38
  • For communication between iframes, use `postMessage` api. – colecmc Dec 31 '15 at 23:39
  • @RohanShankar I think you should take a look at Twitter's Bootstrap framework or something for layouts. Using iFrames for page layout is going to give you lots of extra work (as this question is showing) and just isn't needed at all, not to mention the performance impact of forcing the user to make additional HTTP requests for the iFrame resources. – Matthew Herbst Dec 31 '15 at 23:57
  • 1
    @Matthew Thanks, I will look into it! – RohanShankar Jan 01 '16 at 00:00

1 Answers1

0

In your changeSquare method, try something like this:

var frame2 = $('#frame2', top.document) //Give you top level frame jQuery Object.

for more backwards compatibility, you can use something like:

window.parent.$('#frame2')

Or something like this for no jQuery:

window.parent.getElementById('#frame2')[attributeName]

Once you have the root iFrame object, you can proceed with regular jQuery/DOM manipulation.

EDIT: here is a fully working and tested solution (Safari/Mac OS). Only the changes are highlighted below:

displayPanel.html:

<head>
  <link rel="stylesheet" type="text/css" href="GridTest.css">
</head>

<body>
        <script src="GridTest.js">
        </script>
        <script>
            printInfo();
        </script>
 <div id="label1"></div> <!--Added a div for displaying text -->
</body>

GridTest.js:

function changeSquare() {
    var image = document.getElementById(this.id);

    //First get a reference to the second frame document
    var secondFrameDocument = window.top.document.getElementById('frame2').contentWindow.document; 

    //Now set the value of the Div    
    secondFrameDocument.getElementById('label1').textContent=this.id;

    // If image is currently green square, change to red, and vice versa
    if (image.src.match("http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png")) {
        image.src = "http://www.clker.com/cliparts/1/J/s/o/7/y/red-square-button-md.png";
    } else {
        image.src = "http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png";
    }
    currentDisplay = this.id;
};

Depending upon your exact scenario, you may run into security issues, particularly with Chrome. A better solution would be to perhaps use two Divs instead of iFrames. Here's a screenshot:enter image description here

MojoJojo
  • 3,897
  • 4
  • 28
  • 54
  • Thanks for the answer! So would something like window.parent.GetElementById("frame2").innerHTML = "some value"; work? – RohanShankar Dec 31 '15 at 23:58
  • Thanks so much! It works now. However like you said I'm running into issues on Chrome. Is there any way to fix this? Regardless I really appreciate the help :) – RohanShankar Jan 01 '16 at 16:39
  • I'm glad I could help. Try running your code from a server such as node.js express or apache web server. Chrome doesn't like files being served from local filesystem. If you run it from a web server, it may work. Check this thread for details: http://stackoverflow.com/questions/17950598/using-iframe-with-local-files-in-chrome . What platform/framework are you using? – MojoJojo Jan 01 '16 at 16:53