Understanding HTML

Behind using iframes

Topic status automatically displays here - do not remove.

Bookmark me!Bookmark this topic  Print me!Print this topic

Copying filesInline frames were sanctified in HTML 4.0 (in 1998) and provide the ability to merge separate HTML topics. The benefit they provide over a complete frameset is that they can exist relatively anywhere within a normal HTML document, whereas a frameset completely replaces a normal HTML document with one or more frames.

However, if you only want a section of an HTML page—and not the whole page—to display within another page, the iframe is unsuitable as it is limited to displaying a whole page, and not a subset.

MSDN demonstrated that dynamic loading of an iframe was possible using script, however, my attempts to do so would not work. I could use the sample code to successfully copy named sections out of the iframe's pre-loaded page out into my display document, but I could not change the page in the iframe, nor load it dynamically.

Eventually, I decided it was not possible, blaming the restriction on internet security settings which have been tightened since iframes were ratified. However, as I polished the simple scripting code that did work, I noticed that the pause caused by an alert message provided enough time to have a page load change and take effect. This led me think that the cause of my problem was timing, not the actual code in use.

So, I looked into ways to slow the process down and allow time for a dynamically loaded document to fully load before attempting to copy sections of it out into the display document.  This led me to investigate the properties and methods of the iframe, which revealed an OnReadyStatusChange event. Its example provided just what I wanted, a notification method which fired upon the loading of a document, just like the onload event for an HTML document.

The trick appears to be to assign an event handler to this particular event of the iframe object, and then control the loading, extracting, copying, and unloading processes using script as required.

This I was ultimately able to do after much experimentation, and bring together the common functionality to concentrate the script for maximum flexibility with minimal script. This has been saved as LotechSolutionsDuplication.js which is duplicated below for your reference. Although it contains lines which are wider than this printed page, if you are reading this online it can be copied completely from this HTML page.

Important Important

Please observe copyright laws applicable to your region, and feel free to adapt and use this sample script as you please on your own HTML pages, with the acknowledgement that any such usage or adaptation is reliant upon the sole condition that by doing so, you agree that you are totally and utterly responsible for all consequences of such usage or adaptation, and that you totally and unconditionally absolve me (the original copyright author) from any and all legal and moral responsibility of the consequences of your actions. By use of this sample script, you agree to completely use it at your own risk, and agree to fully and completely take sole legal, ethical, and moral responsibility for your actions in regards to this script.

/* LotechSolutionsDuplication.js  Copyright 2006 Colin Ramsden.
HTTP://WWW.LOTECHSOLUTIONS.COM
Created 13OCT06.
Modification history:
13Oct06	Created
*/


// ***START DUPLICATION SECTION***

/* This is the script section called by the onload event for every topic using duplication.
The 'fnInitialiseFrameWork' function associates the 'onreadystatechange' event of the iframe 
object 'FrameWork' with the 'fnTestStatus' function. This event is triggered and called 
whenever the onready state of the 'FrameWork' is fired as a file is loaded into the iframe.  
There are actually several states which can fire this event, however, only the final 'completed' 
state is used to further trigger the duplication process (copying of pre-named sections). 

This script requires the 'fnInitialiseFrameWork' function be listed in the display page onload 
event to trigger the source file loading and subsequent section duplication process:
 <body onload="fnInitialiseFrameWork();">
 
And of course, a link to this script file is also required on the display page:
 <script type="text/javascript" language="javascript" 
src="../../LotechSolutionsDuplication.js"></script>

This script also expects that the 'FrameWork' iframe object preexists on the display topic, and 
that a script section detailing the source files, sections, and destinations are listed properly.
The named sources and destinations could be either divs or spans, but must match name and type. 
It does not check whether the named source file and sections, or destinations exist in the topics.
It does a simple check that the number of listed source sections does match the number of destinations.

Sample required script section for display page (placed inside header). 
These listed items will need to be customised (where indicated) to suit the number and name of the 
source files and sections, and display page destinations:
*/ 

//create and initialise global tracker to monitor display progress
var ProgressFileCount = 0;
var ProgressComplete = false;

function fnInitialiseFrameWork()
{//called from page onload event
 
 //check script lists for miscount
 fnErrorCheckNumberOfSources();
 
 //alert("Initialising FrameWork");
 //initialise and associate object status change notification
 document.all.FrameWork.onreadystatechange=fnTestStatus;
 
 //load first source file to trigger state change and subsequent duplication
 fnLoadNextTopic();
} 

function fnErrorCheckNumberOfSources()
{//called from fnInitialiseFrameWork
 //alert("Performing Error check script");
 
 //declare common message strings
 var msg;
 var msgNotice = "NOTICE: An error has been detected in the script! \n\n";
 var msgCondition = "does NOT match \n";
 var msgRemedy = "These values need to be readjusted \nin the HTML script section.\n\n";
 var msgApology = "Sorry, but this page may not subsequently \ndisplay as designed.";
 
 //iterate through all nominated source file groups
 for (var SourceFileCount = 1; SourceFileCount <= (aryMatches['SourceFile'].length - 1); SourceFileCount ++)
 {
  //msg = "Current file " + aryMatches['SourceFile'][SourceFileCount];
  //msg += " (" + SourceFileCount + " of " + (aryMatches['SourceFile'].length - 1) + ")";
  //alert(msg);
  
  //check nominated number against listed source counts
  if (aryMatches['NumberOfSourcesInUse'][SourceFileCount] != (aryMatches['SourceSections'][SourceFileCount].length - 1))
  {
   msg = msgNotice; //reinitialises the message string
   msg += "With the source file (" + aryMatches['SourceFile'][SourceFileCount] + "),\n";
   msg += "the nominated number of Sources (" + aryMatches['NumberOfSourcesInUse'][SourceFileCount] + ")\n";
   msg += msgCondition; //inserts common message error condition string
   msg += "the count of listed Sources (" + (aryMatches['SourceSections'][SourceFileCount].length - 1) + ").\n";
   msg += msgRemedy + msgApology; //appends common message strings
   alert(msg);
  }
  
  //check number of listed sources against number of listed destinations 
  if ((aryMatches['SourceSections'][SourceFileCount].length) != (aryMatches['Destinations'][SourceFileCount].length))
  {
   msg = msgNotice; //reinitialises the message string
   msg += "With the source file (" + aryMatches['SourceFile'][SourceFileCount] + "),\n";
   msg += "the count of listed Sources (" + (aryMatches['SourceSections'][SourceFileCount].length - 1) + ")\n";
   msg += msgCondition; //inserts common message error condition string
   msg += "the count of listed Destinations (" + (aryMatches['Destinations'][SourceFileCount].length - 1) + ").\n";
   msg += msgRemedy + msgApology; //appends common message strings
   alert(msg);
  }
 } 
} 

function fnTestStatus()
{//called whenever the iframe status is ready
 //this fires for any change in status 
 //alert("Testing FrameWork Status");

 //test whether iframe status is complete (file is fully loaded)
 if (document.all.FrameWork.readyState == "complete")
 {//ready to copy sections over to main document
  
  //check progress to prevent unnecessary copy action
  if (! ProgressComplete)
  {
   //copy source sections from currently loaded source file to destinations
   fnCopySections();
  }
 }
 else
 {//current readystate is not "complete" 
  //var msg = "TestFrame status is " + document.all.FrameWork.readyState + ".";  
  //alert(msg);
 }
}

function fnLoadNextTopic()
{
 //determine if there is another source file to load next
 if (ProgressFileCount < aryMatches['SourceFile'].length - 1)
 {   
  //increment progress counter
  ProgressFileCount ++;
  
  //var msg = "Current file " + ProgressFileCount + " of " + (aryMatches['SourceFile'].length - 1);
  //msg += "\nLoading topic " + aryMatches['SourceFile'][ProgressFileCount] + ".";  
  //alert(msg);
  
  //load source file
  document.all.FrameWork.src = aryMatches['SourceFile'][ProgressFileCount]; 
 }
 else
 {//finished
  //unload source file
  document.all.FrameWork.src = ""; 
 }
}

function fnCopySections()
{//copies the text where required to prevent source duplication
 //alert("Copying Sections");
 
 //create local variables
 var source;
 var destination; 
 
 //copy source sections to destinations
 for (var count = 1; count <= aryMatches['NumberOfSourcesInUse'][ProgressFileCount]; count ++)
 {
  source = aryMatches['SourceSections'][ProgressFileCount][count];
  destination = aryMatches['Destinations'][ProgressFileCount][count];
  //var msg = "Source = " + source + ".\nDestination = " + destination + ".";
  //msg += "\nNumber of Sources = " + aryMatches['NumberOfSourcesInUse'][ProgressFileCount] + ". ";  
  //msg += "Current count = " + count + ". ";  
  //alert(msg);
  
  //perform the actual duplication copy
  eval(destination + '.innerHTML = document.frames("FrameWork").' + source + '.innerHTML');
  
  //calculate file progress
  if (ProgressFileCount == aryMatches['SourceFile'].length - 1) 
  {//at last source file
   //alert("Progress at last source file");
   
   //calculate section progress
   if (count == aryMatches['NumberOfSourcesInUse'][ProgressFileCount])
   {//at last section to be copied
    
    //set completed flag
    ProgressComplete = true;
    //alert("Progress Completed");
   }
  } 
 }
 //load next sourcefile to trigger state change
 fnLoadNextTopic();
}

//***END DUPLICATION SECTION***

//***END OF FILE***

The only requirements of the page author is to update the source and destination list in the HTML of the displaying page

The only subsequent requirements of the user is to ...

   


See Also

Lotech Solutions' Tips, Tricks, and Procedures

Back to Top