
Links for
Stardard
Version of
overLIB
home
manual
articles
support
|
A proposed plug-in capability
for overLIB |
| By Robert E. Boughner |
| 1. |
Requirements
for an overLIB plug-in |
|
A plug-in capability for overLIB requires, at a minimum,
that consideration be given to the following points.
- Be able to easily add new parameters, along with any values
that may be associated with them.
- Be able to easily establish the runtime and default variables
associated with these parameters as global variables and
to set values for the default variables. Here, I refer to
runtime variables as those variables that are prefaced with
o3_ in the case of the normal
overLIB code and prefaced with o
for the mini version of overLIB. The default variables are
those that are prefaced with ol_.
- During each invocation of an overLIB call, be able to
easily set the runtime variables to the current value of
the default variables. In addition, it must be easy to parse
the overLIB command line for the appearance of these parameters,
performing any necessary processing that may be required,
and to continue with command line parsing after this processing
is done. This command line parsing must be independent of
any order that the parameters may appear.
- Be able to easily replace core routines with similar functioning
routines that are needed to handle new parameters that are
being added.
- Be able to call external routines, either at the very
beginning or very end of normal core routine coding. This
capability may be needed to do extra processing associated
with the added parameters, either for setting variables
associated with the added parameters or for cleaning up.
- In the case of the layer generation functions, be able
to easily establish alternate pathways for processing. Currently
there are at least three alternate pathways in overLIB --
simple popups, popups with captions, and popups that either
specify full html code or have a background specification
and three different cases to consider CSSOFF, CSSSTYLE,
and CSSCLASS
|
| 2. |
Proposed
Solution |
The plug-in strategy that I propose here addresses each of
these items as discussed here. Based on Erik's initial comments
about the first release of this proposed plugin capability,
I've made a few changes in its implementation to address some
of his concerns.
The current version of overLIB assigns numerical values to all
parameters, ranging from 1 to around 70 or 80. The only purpose
that I can tell that this serves is to help in determining which
parameter is specified on the command line during the parsing
phase. However, it does have one practical benefit which was
taken advantage of in the Beta releases of v3.51. All parameters
occur with none or more additional associated parameter values.
This feature was used to modify the start of parsing to eliminate
the old requirement in overLIB that the very first argument
in the call had to be either a text string or the parameter
INARRAY so that any parameter can be specified
as the first argument value. If you are supplying a string value,
it must be the first argument. If you're not supplying
a text string then any argument, including FUNCTION
and INARRAY, can come first, but it is not
required that these latter parameters must be first. This change
is made possible by checking the typeof
the argument and setting things up so that the following parsing
block gets executed if that type is a 'number'.
I make mention of this because there have been some suggestions
that this approach be scrapped in favor of assigning parameters
string values that match their names. I don't recommend that
this be done because for one thing the feature mentioned above
would have to be modified (although not a big deal) and for
another thing, I suggest letting javascript handle
the numerical assignments in the following way:
- In each module, the parameters it will handle are passed
as a comma delimited, lower-case string argument to the
routine registerCommands(). This routine
uses Javascript methods to generate numerical values associated
with these parameters and to convert them to their capitalized
form that one normally sees in overLIB. The global variable
pmCnt (which stands for parameter
count) is a running count
of this numerical sequence, starting with the value of 1;
the sequencing is simply continued when subsequent modules
are loaded. I adopted this approach because:
- It shortens filesize.
- It is easier to type parameter names without worrying
about whether the caps lock key is engaged or not. However,
you can use capitals or mixed case in typing them if
you wish. All of these will automatically be converted
to an upper case form. This comment only pertains to
the parameter description that is passed to the routine
registerCommands; you won't be able
to specify parameters on the overLIB command line, either
as mixed case or lowercase, because its value won't
be known and you'll get a javascript error. Only the
capitalized names as used now in overLIB are known and
won't cause any problems when used on the command line.
- You can easily add (or remove) additional parameters
by just inserting (deleting) them in this command string.
What this means is that any mini version of overLIB should
not replace these parameters with their numerical values
but should retain the capitalized parameters by name because
their values can now change depending on the order the different
plug-in modules are loaded.
- As an example, the core module uses the following code
to define the commands that it will handle:
var pmCnt = 1;
var pMtr = new Array();
coreCmds =
'inarray,caparray,sticky,background,noclose,caption,left,right,center,'+
'offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,' +
'border,status,autostatus,autostatuscap,height,closetext,snapx,snapy,' +
'fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,' +
'above,below,capicon,textfont,captionfont,closefont,textsize,' +
'captionsize,closesize,frame,timeout,function,delay,hauto,'+
'vauto,closeclick,wrap,followmouse,'mouseoff,cssoff';
registerCommands(coreCmds);
where the function registerCommands
is defined as
function registerCommands(cmdStr) {
if (typeof cmdStr != 'string') return;
var pM = cmdStr.split(',');
pMtr = pMtr.concat(pM);
for (var i=0; i< pM.length; i++)
eval(pM[i].toUpperCase() + ' = ' + pmCnt++);
}
Because registerCommands is defined
in the core module, subsequent modules can simply call
this function with a string containing the commands it
supports as it loads. As an example, the module which
supports draggable popups has this as the first statement
of the module: registerCommands('draggable,altcut,dragimg')
- The above code is what would be in the core library module
which will have all of the capability that was found in
v3.33 of overLIB, plus a few additional features that I
feel should be in a core library module, such as mouseout/mouseoff,
mousecapture capability with other scripts, and delay on
mouseout, but none of the advanced features such as CSSSTYLE
and CSSCLASS or a drop shadow effect. These would be incorporated
into separate modules that could be loaded if the user requires
that particular capability. By removing most of the comments,
but not the fancy formatting that aids in understanding
how the program logic works, I've managed to reduce the
core file size to about 37K which is around the same size
as v3.33, but with more functionality, and is only about
10K larger than v3.50 mini version. (If I perform the same
formatting tricks that are used in the mini version, the
file size saving is only around 3K for the core module and
is certainly not worth the extra effort involved.)
Most of the following modules would have coding similar
to the above to continue the numerical values assigned
to the parameters. As can be seen, this numbering will
change with any change in the order of loading the modules
or if more parameters are added and/or removed in a given
module. However, by always referring to the parameters
by their capitalized names there shouldn't be any problems
since then one doesn't really care what their values are.
Nothing special is needed for item #2 listed above. This is
already being done in overLIB now and the plug-in structure
can easily continue with the same approach. A global variable
is one that is defined outside any subroutine so that it is
known to all subroutines. It makes no difference whether this
definition comes at very beginning of the program, as it does
now in overLIB, or if it is interspersed among the different
plug-in modules just as long as the runtime and default variables
are external to all subroutines. Note: Any variable defined
within a subroutine without using var before
it, also becomes a global variable. This feature is used in
the registerCommands routine.
For items #3 - #6 above, I propose a registration type procedure.
Based on the discussion of those items above, there are at
least six different types of registrations that would be needed
as outlined in the following table:
| Types of function
registrations |
| Typ |
Functionality |
Parameter |
| 0 |
Replace core function |
FREPLACE |
| 1 |
Run function before normal overLIB code is
executed |
FBEFORE |
| 2 |
Run function after normal overLIB code is executed |
FAFTER |
| 3 |
Alternate pathway function |
FALTERNATE |
| * |
Functions which set runtime variables and handle command
line parsing |
|
| * |
Functions which are called after normal parsing is done
for additional checking |
|
* No numbering is needed for
these types of functions because the registration routines
registerRunTimeFunction, registerCmdLineFunction,
and registerPostParseFunction take care of
these as explained below.
|
| 3. |
Registration
Proceedure |
|
The registration function is registerFunction(fnHookTo,
fnRef, Typ, [optPm]) where
- fnHookTo
- name of the core module function to establish a hook to,
a string value
- fnRef
- a reference to the function being applied. For Typ
= 1 or 2, this can also be an array of function references.
- Typ
- a value from 0 through 3 associated with the functionality
shown in the table above. The parameters given in the above
table can be used to simplify remembering which one is which.
- optPm
- is an optional parameter whose value depends on the Typ
of function being registered. When Typ is 3, this
third argument will take one of the following values: CSSOFF,
CSSCLASS, CSSSTYLE, or CSSW3C. Its purpose is to provide
access to the particular alternate function being registered.
When Typ is 1 or 2, the use of the third agrument
is explained below. At present, this argument isn't used
when Typ is 0.
The call to this function would be made at the very end of
a plug-in module so that there won't be forward referencing
of function names that may cause problems with the javascript
interpreter. The following statements, which occur at the
very end of the core module, illustrates how this function
would be called:
registerFunction("ol_content_simple", ol_content_simple, FALTERNATE, CSSOFF);
registerFunction("ol_content_caption", ol_content_caption, FALTERNATE, CSSOFF);
registerFunction("ol_content_background", ol_content_background, FALTERNATE, CSSOFF);
These calls are registering the basic layer-generation functions
associated with the different types of popups. optPm
is CSSOFF because this is the default for the core
module.
When Typ is either 1 or 2, and there are several
functions to be executed, these functions get run in the order
in which they are registered. However, there may be situations
where certain supporting routines must be run before others.
In order to allow for modules to be called in any order, I've
used the last variable optPm to indicate
which functions the function being registered must come before
in the execution chain. In this case, optPm
can be either a single function reference or an array of function
references (which doesn't include fnRef).
The registration code re-arranges the order of the internal
array which holds these function references so that fnRef
comes before the function(s) specified by optPm,
which are placed at the very end of this internal array. If
optPm isn't specified (or is the null object),
the function being registered just gets placed at the end
of this internal array like it would normally. An example
where order is important is the module which handles the DropShadow
effect and the one that handles reference mark properties.
For this case, a supporting routine in the DropShadow module
must be executed before a particular function in the reference
mark module. This is taken care of using the following code
snippet at the end of the DropShadow module:
var before = (typeof rmrkPreface != 'undefined' ? rmrkPreface : null);
registerFunction("createPopup", generateShadow,FAFTER, before);
Without the addition of this enhancement, popups were not
positioned correctly if the Reference Mark module were loaded
before the DropShadow module, because the Reference Mark routines
were obtaining wrong information about the popup's width and
height values.
|
| 4. |
The runTime and
cmdLine arrays. |
| For item #3 above, I've defined two arrays, runTime
and cmdLine, which hold function references
to routines which will handle the tasks described there. Functions
in the runTime array are called to set runtime
variables to their associated default values, or possibly even
initialize other global variables as needed. Functions in the
cmdLine array handle parsing of parameter values
on an overLIB command line. Functions are added to these arrays
using either the registerRunTimeFunction or
registerCmdLineFunction routines, respectively.
Arguments to these two routines are either a function reference
or an array of function references. The functions within these
arrays are called from either setRunTimeVariables(),
which occurs at the end of the initialization statements
near the beginning of the overlib() routine, or from
parseCmdLine(pf,i,ar) routine, which appears
at the end of the series of checks within the parseTokens
routine. This second function has three input arguments -- the
first is the parsing prefix
value, pf which is either ol_
or o3_ (since the routine must handle
both parsing and setting of default values), the second argument
is the index to which the input argument array has been parsed
when the routine is called, and the last argument is the argument
array to the overlib() routine. If there is a match,
parseCmdLine should return the index where a match
occurred, suitably incremented. If there is no match, it should
just return the value -1.
A suggested format that can be used for the parsing routines
is the following example, which is taken from the CSSSTYLE
module:
function parseCSSStyleExtras(pf,i,ar) {
var k = i;
if (k < ar.length) {
if (ar[k] == CSSSTYLE) { eval(pf + 'css = ' + ar[k]); return k; }
if (ar[k] == FGCLASS) { eval(pf + 'fgclass = "' + ar[++k] + '"'); return k; }
if (ar[k] == BGCLASS) { eval(pf + 'bgclass = "' + ar[++k] + '"'); return k; }
if (ar[k] == TEXTFONTCLASS) { eval(pf + 'textfontclass = "' + ar[++k] + '"'); return k; }
if (ar[k] == CAPTIONFONTCLASS) { eval(pf + 'captionfontclass = "' + ar[++k] + '"'); return k; }
if (ar[k] == CLOSEFONTCLASS) { eval(pf + 'closefontclass = "' + ar[++k] + '"'); return k; }
if (ar[k] == PADUNIT) { eval(pf + 'padunit = "' + ar[++k] + '"'); return k; }
if (ar[k] == HEIGHTUNIT) { eval(pf + 'heightunit = "' + ar[++k] + '"'); return k; }
if (ar[k] == WIDTHUNIT) { eval(pf + 'widthunit = "' + ar[++k] + '"'); return k; }
if (ar[k] == TEXTSIZEUNIT) { eval(pf + 'textsizeunit = "' + ar[++k] + '"'); return k; }
if (ar[k] == TEXTDECORATION) { eval(pf + 'textdecoration = "' + ar[++k] + '"'); return k; }
if (ar[k] == TEXTSTYLE) { eval(pf + 'textstyle = "' + ar[++k] + '"'); return k; }
if (ar[k] == TEXTWEIGHT) { eval(pf + 'textweight = "' + ar[++k] + '"'); return k; }
if (ar[k] == CAPTIONSIZEUNIT) { eval(pf + 'captionsizeunit = "' + ar[++k] + '"'); return k; }
if (ar[k] == CAPTIONDECORATION) { eval(pf + 'captiondecoration = "' + ar[++k] + '"'); return k; }
if (ar[k] == CAPTIONSTYLE) { eval(pf + 'captionstyle = "' + ar[++k] + '"'); return k; }
if (ar[k] == CAPTIONWEIGHT) { eval(pf + 'captionweight = "' + ar[++k] + '"'); return k; }
if (ar[k] == CLOSESIZEUNIT) { eval(pf + 'closesizeunit = "' + ar[++k] + '"'); return k; }
if (ar[k] == CLOSEDECORATION) { eval(pf + 'closedecoration = "' + ar[++k] + '"'); return k; }
if (ar[k] == CLOSESTYLE) { eval(pf + 'closestyle = "' + ar[++k] + '"'); return k; }
if (ar[k] == CLOSEWEIGHT) { eval(pf + 'closeweight = "' + ar[++k] + '"'); return k; }
}
return -1;
}
I believe that when set up this way all parsing functions
will be called, in sequence, to search for a match in the
parameters supplied to the overLIB call. If you try to access
some parameter that isn't defined in either the core module
or one of the plug-in modules, you'll get a javascript
error of some type. Also, coded in this manner, the routine
will serve to both parse and set default variables. There
are several examples of how this capability can be employed
to toggle some behavior on or off in the Command References
for the Core Module and the Reference Mark module.
Routines within the postParse
array must be written so that they satisfy the following condition:
if they execute without problems, return a true value, otherwise
return false to signal an error and the overLIB call will
be aborted at this point. The rationale for having this array
is to make checks which can only be done after all of the
command line has been parsed and do some further processing.
An obvious use of this is in conjunction with the cross frame
STICKY support contained in the overlib_crossframe.js
module to set the appropriate value of the overLIB global
variable fnRef. Functions are added
to this array via the registerPostParseFunction
routine, which takes either a single function reference or
an array of function references. Like the other cases, this
call should be placed near the end of a module to avoid forward
referencing of function references. Functions in the postParse
array are accessed through a call to the postParseChecks()
function.
Here is an example of how the postParseChecks()
is currently being used in the core module:
. . .
parseTokens('o3_', overlib.arguments);
if (!postParseChecks()) return false;
. . .
|
| 5. |
Calling Functions |
Once a function has been registered, it is called
using runHKFun(fnHookTo, Typ, other
arguments required). The last argument in the
above call are the arguments that would normally be supplied
in a normal overLIB call. Depending on the call this argument
may be absent. For example, the call to the overLIB function
hideObject() from within the nd() function
is done as follows:
if (over != null) runHKFun("hideObject",FREPLACE,over);
which replaces the normal overLIB call hideObject(over).
If no functions have been registered for fnHookTo
when Typ equals 0 or 3, then runHKFun()
defaults to executing the core function whose name is fnHookTo
with arguments given by the last argument in the call to runHKFun().
When Typ is 1 or 2, then runHKFun()
just returns.
For all of this to work, appropriate calls to runHKFun()
must be inserted at the appropriate places within the core
module. Those core functions which can only be changed by
overloading them (i.e., supplying functions which have the
same name in subsequent modules) are:
- olMouseMove - Formerly mouseMove
- no_overlib
- overlib
- nd
- set_background
- cClick
- compatibleframe
- setOLParams
- parseTokens
- layerWrite
- repositionTo
- reorderMouseCapture - Function which switches
the order of mouse capture execution.
- opt_FRAME
- opt_FUNCTION
- opt_NOCLOSE
- fnReference - Object constructor for registration
proceedure
- registerFunction - Main function registration
routine
- runHKFun - Main entry point for calling functions
to be executed
- argToString - Supporting routine used by registerHook
- reorder - Another supporting routine used by
registerHook
- registerCommands - Routine that defines global
variables for use by overLIB
- registerRunTimeFunction - A function to add routines
to the internal runTime array
- registerCmdLineFunction - A function to add routines
to the internal cmdLine array
- registerPostParseFunction - A function which
adds routines to the internal postParse
array
- isFunction - Checks that its arguments are function
references. Used by the previous three registration functions.
Returns true if its argument is a function reference otherwise
it returns false.
These routines were not made part of the registration procedure
because they are either external calls to overLIB or are not
likely to be changed in any subsequent module add-in. If this
changes in the future then some of them could probably be
added to the registration procedure if needed. It highly recommended
that you don't overload functions but work through the registration
process so that some consistency can be maintained.
Core module routines which are affected by the registration
process include:
- olMain - Formerly was overlib3xx.
- hideObject
- ol_content_background
- ol_content_simple
- ol_content_caption
- createPopup - A new function, which occurs in
olMain, that was added to make the plug-in procedure
easier to implement.
- disp
- placeLayer
- showObject
- cursorOff - Function which is needed for the
mouseout/mouseoff feature
The layer generation functions can also be replaced if needed.
However, if they are, those functions are automatically associated
with the CSSOFF parameter, i.e, they will be called when the
parameter CSSOFF is active.
|
| 6. |
Info Object |
|
As a prelude to a possible future requirement that a module
needs to have a certain minimum core level of support to operate
correctly, I've added an Info object with
the properties given in the table below. Authors of plugins
may use this information as they see best. Please let me know
if you think that some other information should also be included.
If you do, then please also specify your reasons why that
information should be included.
At present, the global variable olInfo holds
this information. I'm certain that there will be changes made
to this object as further development of a plugin strategy
evolves.
| The Info Object |
| Property |
Type |
Default Value |
| version |
number |
4.00 |
| simpleversion |
number |
400 |
| major |
number |
4.0 |
| minor |
number |
0.0 |
| prerelease |
boolean |
true |
| revision |
number |
0 |
|
| 7. |
Modules |
|
Using the approach outlined here, I have developed the modules
listed in the table below. As far as I know, these can all
be called in any order, although this hasn't been tested extensively
and further testing may indicate that this isn't the case.
|
|
Just a few comments with regard to these modules:
- These modules all work in the new browser released by
Opera v7 Final. The CrossFrame Sticky support module, overlib_crossframe.js,
doesn't function in this browser if frames are nested. Non-nesting
frames work without problems.
- Use of CSSCLASS with a DropShadow effect doesn't display
correctly in Netscape 4.x. If there is no DropShadow effect
being applied, then CSSCLASS works fine. I believe this
is a shortcoming in this browser. I didn't do anything to
correct this deficiency because it wasn't worth the effort
considering that the Netscape 4.x browser is being used
less and less frequently, and one can get around the difficulty
by using either CSSSTYLE or just a plain popup.
- There are problems in the Netscape 4.x browser when you
use popups that employ CSSSTYLE and CSSCLASS parameters
on the same page. As soon as the popup which uses CSSSTYLE
is shown, it will mess up the display of the popups which
use CSSCLASS. If the page is manually reloaded, this problem
clears up until the popup using CSSTYLE is shown again.
I recommend that you avoid this situation entirely by using
one or the other of these parameters for your popups. This
problem doesn't seem to occur if normal popups are used
with those having CSSSTYLE.
- The definition of over for IE has been changed
so that it doesn't contain the 'style' property in its definition,
i.e. it refers to just the overDiv container object like
it does for Netscape 4.x and Netscape 6+, which has necessitated
the appropriate coding modifications to handle this. This
change was made because in developing the above modules,
the code snippet
var ovObj = (olIe4 ?
o3_frame.all['overDiv'] : over) kept popping up because
a reference to the container object was frequently needed
. This change has simplified coding somewhat.
- The module overlib_cssw3c.js allows popups to be styled
exclusively via CSS Style rules. It is designed to be used
with more recent browsers that are CSS compliant. I specifically
disable this capability in Netscape 4.x because of its numerous
quirks in applying CSS Style rules that I didn't want to
be bothered with trying to make it work in that browser.
It employs a much simpler table structure for the popup
than a normal overLIB popup, which is fully explained in
the CSSW3C Command Reference.
- There are major problems of overlib popups displaying
correctly in IE5 on a Macintosh platform. Since my development
platform is primarily a Windows PC, it is difficult for
me to figure out how to overcome some of these obstacles.
Hopefully, someone who works normally with a Mac will be
willing to undertake some of these investigations.
As a final comment, it should be mentioned that any developer
who wishes to develop a module for possible future inclusion
in the overlib utility should strive to write that module
so that it will work in any order that it is called. There
are numerous examples how this can be done in the modules
that have been developed thus far. The Reference Mark module
has an example of a suggested coding style in the routine
rmrk_placeLayer that replaces the
core function placeLayer. This is
just a recommendation; each developer is free to write modules
in their own style of coding. If the module can't be loaded
independently of other modules, then the precise order that
is required should be clearly stated.
|
| 8. |
Examples using
this approach |
|
Examples using these modules together are given below where
I also indicate the statements that would go in the HEAD section
to include the modules.
- Reference Mark and DropShadow
<SCRIPT TYPE="text/javascript" SRC="overlb.js"></SCRIPT>
<SCRIPT TYPE="text/javascript" SRC="overlib_mark.js"></SCRIPT>
<SCRIPT TYPE="text/javascript" SRC="overlib_dropscroll.js"></SCRIPT>
- DropShadow and Draggable
<SCRIPT TYPE="text/javascript" SRC="overlib.js"></SCRIPT>
<SCRIPT TYPE="text/javascript" SRC="overlib_dropscroll.js"></SCRIPT>
<SCRIPT TYPE="text/javascript" SRC="overlib_draggable.js"></SCRIPT>
- W3C Styling of popups
<SCRIPT TYPE="text/javascript" SRC="overlib.js"></SCRIPT>
<SCRIPT TYPE="text/javascript" SRC="overlib_cssw3c.js"></SCRIPT>
|
|
|
| Status |
|
|
|
Plug-in Proposal
Third revision:
01-17-2003 |
|