pronouncedJerry
pronouncedJerry

Reputation: 45

Is it possible to load Mootools in a parent frame and then re-use it in iframes?

Example

-- begin: index.html --
<!doctype html>
<html>
<head>
<title>Index</title>
<script type="text/javascript" src="mootools.js"></script>
</head>
<body>
<iframe src="iframe.html" id="innerFrame">blah</iframe>
</body>
</html>
-- end: index.html --

-- begin: iframe.html --
<!doctype html>
<html>
<head>
<title>iFrame</title>
</head>
<body>
<form>
<input id="inputField" type="text" value="this is text." />
</form>
<script type="text/javascript">
$('inputField').set('value', 'updated text');
</script>
</body>
</html>
-- end: iframe.html --

Currently, $('inputField').set('value', 'updated text'); doesn't work :-\

Upvotes: 0

Views: 970

Answers (3)

freenatec
freenatec

Reputation: 571

My previous answer offered two alternative ways of doing the task in question ("load Mootools in a parent frame and then re-use it in iframes"). The first method didn't "re-use" the Mootools functionality loaded into the parent frame, but was rather an alternative way to load the script in the inner iframe. The second method was just a hacky way of copying over the script by putting the entire mootools core source inline in a script element and then copying that element's content into a script element in the iframe's head (hardly optimal).

This following method does programatically extend the window and document objects of the inner iframe. Again, it is assumed that both the parent page and the iframe are on the same domain.

In my (brief and simple) testing, loading the source in both parent and iframe resulted in 72.1 KB transferred at around 130ms (to finish loading both the parent and iframe pages), while the page that loaded the source and then extended the iframe was 36.8 KB and took around 85ms to load both parent and iframe. (that's with gzip on the server...file size of uncompressed/unminified core source is around 134 kb).

For this method a few trivial additions/edits are made to the mootools core source. Download an uncompressed version of mootools-core-1.3.2.js, and rename it to 'mootools-core-init.js' (or whatever). The following steps assume that you checked all boxes on the core builder page except 'Include Compatibility'.

Add this to the top of the 'mootools-core-init.js' file (above the first self-calling anonymous function):

var initMootoolsCore = function(){

var window = this;
var document = this.document;

Add this to the very bottom of the core js file:

};

initMootoolsCore.call(window);

Do the following find/replace tasks:

1

  • Find:})();
  • Replace: }).call(this);

2

  • Find: if (Browser.Element) Element.prototype = Browser.Element.prototype;
  • Replace: if (this.Browser.Element) Element.prototype = this.Browser.Element.prototype;

3

  • Find: var IFrame = new Type
  • Replace: var IFrame = this.IFrame = new Type

4

  • Find: var Cookie = new Class
  • Replace: var Cookie = this.Cookie = new Class

(download | compressed version)

In your parent index.html file, put the following script element in the head

<script type="text/javascript" src="mootools-core-init.js"></script>

Finally, in your iframe.html file, put the following inline script element in the head to extend the iframe's window and document (it must be before any included or inline scripts that need to use Mootools):

<script type="text/javascript">parent.initMootoolsCore.call(window);</script> 

Upvotes: 0

freenatec
freenatec

Reputation: 571

Yes, assuming the iframe and it's parent window are on the same domain, it is possible to load the Mootools scripts once in the parent, and then programmatically extend the IFrame's window and document, instead of re-loading the script within the iframe. It is not the default behavior, as you've noticed, and probably for good reason - I'm guessing most people will tell you it's more trouble than it's worth.

In fact, the IFrame shortcut element constructor used to do that exact thing, but it was ultimately considered to be too much of a hack and not worth the effort to maintain as part of the framework long-term, so they dropped it - this why the documentation for IFrame is kind of odd ("IFrame Method: constructor, Creates an IFrame HTML Element and extends its window and document with MooTools.", and then right below after the example, "Notes: An IFrame's window and document will not be extended with MooTools methods.").

So, the most straightforward way to have $(..) useable in your iframe is just to have the iframe include the Mootools script. If you're feeling fancy, you could also have your parent window inject the Mootools script into the iframe's HEAD, for example:

index.html

<html>
<head>
<title>Parent</title>   
<script type="text/javascript" src="mootools.js"></script>
</head> 
<body>

     <iframe id="innerFrame"></iframe>

<script type="text/javascript">
 var mooFrame = new IFrame("innerFrame", {      
    src:"iframe.html",
    events: {
        load: function(){

            var mooEl = new Element('script', {
                type: 'text/javascript',
                src: "mootools.js",
                events: {
                    load: function(){
                        //passed to mooFrame by the iframe
                        this.pageReady();

                    }.bind(this)

                }
            });             

            this.contentDocument.head.appendChild(mooEl);

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

iframe.html

 <html>
 <head>
 <title>Iframe</title>   
 </head>
 <body>
 <div id="iframe_element"></div>

 <script type="text/javascript">
     parent.mooFrame.pageReady = function(){

         /* Put your iframe javascript in here */
     $('iframe_element').set("text", "Fancy!"); 

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

Update (July 29th): I was fooling around with this idea again and realized there's a fairly obvious though pretty ham-fisted way to transfer Mootools functionality defined in the parent index.html window to the inner iframe: simply include the entire Mootools source into the parent window (remove the src attribute from the existing script element and add an id), and copy that newly enormous element's text into the new script node that gets injected into the head of the iframe. Inlining the Mootools code in the script element in this fashion gives you access to the contents of the element, which you don't get when the javascript is loaded from an external file via the src attribute.

Of course, this..concept is only relevant if the parent window and iframe are on the same-domain, (same as the code provided above).

The obvious drawback is that the Mootools source isn't cached. I'm not sure if there's a use-case where this method would be more optimal than just including mootools in both parent and iframe. In any event, change the index.html file to this:

<html>
<head>
<title>Parent</title>   
<script type="text/javascript" id="mootools_js">

**COPY-PASTE THE CONTENTS OF mootools-core.js HERE**

</script>
</head> 
<body>

     <iframe id="innerFrame"></iframe>

<script type="text/javascript">
 var mooFrame = new IFrame("innerFrame", {      
    src:"iframe.html",             
    events: {
        load: function(){
            var mooEl = new Element('script', {
                id: 'mootools_iframe_core',
                type: 'text/javascript',
                html:  $('mootools_js').innerHTML
            });

           this.contentDocument.head.appendChild(mooEl);
           this.pageReady();


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

Upvotes: 2

Lawrence McAlpin
Lawrence McAlpin

Reputation: 2785

No, the iframe.html is an independent page. It does not "inherit" anything from the previous page.

Upvotes: 0

Related Questions