Plugin Writing Tutorial

What's involved in writing a plugin for overlib? This section will outline the steps that are required, using the "unofficial" Centerpopup plugin as an example. The most important requirement is that a plugin developer should have a very thorough understanding of the logic and program flow of the core overlib module, and, of course, a strong background in Javascript. The following books by Danny Goodman make excellent reference material and resources:

1. The first thing to decide is what commands will the plugin support. In the Centerpopup plugin, there are only two commands -- CENTERPOPUP and CENTEROFFSET. These commands are made available to the core module by registering them with the statement:

  registerCommands('centerpopup,centeroffset')

2. Next, default values of the appropriate variables and reasonable runtime values of these same variables must be set. This is done in the lines:

  if (typeof ol_centerpopup=='undefined') var ol_centerpopup=0; 
  if (typeof ol_centeroffset=='undefined') var ol_centeroffset='0';
  var o3_centerpopup=0;
  var o3_centeroffset='0'; 

Note that since these lines are outside any function definitions, they are global variables and will be available to all subroutines.

3. Next, two functions must be defined. The first one sets the runtime variables to their associated default values and the second one handles parsing of an overlib command line to check for the appearance of these variables. In our example plugin, the following function:

  function setCenterPopupVariables() {
    o3_centerpopup=ol_centerpopup;
    o3_centeroffset=ol_centeroffset;
  }

will set the runtime variables to their default values. Notice the naming of this function which states clearly what it's purpose is. In all present plugins, the functions which perform this task are similarly named and this naming scheme is a good one to follow. The second function is:

  function parseCenterPopupExtras(pf,i,ar) { 
    var k=i,v; 
    if (k < ar.length) { 
      if (ar[k]==CENTERPOPUP) { eval(pf +'centerpopup=('+pf+'centerpopup==0) ? 1 : 0'); return k; } 
      if (ar[k]==CENTEROFFSET) { k=opt_MULTIPLEARGS(++k,ar,(pf+'centeroffset')); return k; }
    }
    return -1; 
  } 

Again notice how this function is named, and is a good example to follow, but a developer can use any naming convention that he/she wishes. As stated in the description of the plugin architecture, this function will receive three arguments -- the prefix value (either 'ol_' or 'o3_'), the point to which the overlib argument array has been parsed, and the argument array itself. This function checks to see if commands associated with this plugin are present. If they are, it returns the location in the argument array where the match was found, after it has been suitably incremented. Otherwise it just returns a -1 to signal that no match was found. As shown here, other functions can be called for additional processing if needed. Also, note the close similarity of the coding to that in the parseTokens function in the core module.

4. The next step is perhaps one of the hardest. That is deciding how best to call the routines which perform the tasks needed for the plugin. This isn't all that straight forward and can be done in many different ways because of the numerous possibilities that are present. The main thing to keep in mind is that, as a developer, you can't manipulate any of the routines in the core module, except, as done here, by replacing the core routine with your own. If you must do that then it is your responisibility to make sure that the replaced routine maintains all of the capability of the replaced routine and preserves load-order independence. In addition, attention should be given as to whether other plugins are also overloading the same routine because it will mean that your code must account for those changes too and that it must be written in a much more general way than at first envisioned. Remember you can only count on variables associated with your plugin being defined. All other variables must generally be tested to see if they are defined before being used to avoid javascript errors. Here it was decided to replace the disp() function with:

  function disp_centerpopup(statustext) { 
  // call any routine needed before showing popup 
    runHKFun("disp",FBEFORE);
    if (o3_centerpopup) { 
      centerPopupOnScreen();
      runHKFun("showObject",FREPLACE,over);
    } else if (o3_allowmove==0) 	{
      runHKFun("placeLayer",FREPLACE); 
      runHKFun("showObject",FREPLACE,over);
      o3_allowmove=(o3_sticky||!o3_followmouse) ? 0 : 1;
    } 
    runHKFun("disp",FAFTER);
    if (statustext!="") self.status=statustext;
  }

which makes a call to the supporting function centerPopupOnScreen(). This function can be examined in the plugin to see what it does exactly.

5. The final step is to register all of these functions in the core module so that they can be called properly. This is done at the end of the plugin, using the statements:

  registerRunTimeFunction(setCenterPopupVariables);
  registerCmdLineFunction(parseCenterPopupExtras);
  registerHook('disp',disp_centerpopup,FREPLACE);

These are only a few of the "hook points" that have been incorporated into the core module. There are times when a developer must make changes in variables after all of the command line has been parsed. This would be done by calling a function that has been registered and included in the registerPostParseFunction function. At other times, one must call functions either before or after the main code of a core routine is executed (see the lines that have FBEFORE and FAFTER above).

While developing a plugin and you find a situation where some changes in the current organization is needed, please email Robert E. Boughner and state what it is that you want to do and how your job would be easier if something were included. Your suggestions will be considered and may be included in the next release of overlib.



contents
home
manual
support
license
download
plugins