home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC-Online 1998 February
/
PCOnline_02_1998.iso
/
browser
/
net_linx
/
nethelp-v404.nif
/
nethelp-v404
/
nethelp
/
System.js
< prev
next >
Wrap
Text File
|
1997-06-04
|
23KB
|
801 lines
/* ==================================================================
FILE: System.js
DESCR: System class for Netscape Help implementation.
NOTES:
================================================================== */
// Dev. switches.
var TRACE = false
var ASSERT = true
var ERR_DLGS = true
var ERRS_TO_CONSOLE = false
// "Constants."
var VERSION = "2.0"
var LAYERED_TOPICS = false
var JAVA_DEPENDENT = false
var STAMP_CONSOLE = false
var OK_NAV_VERSIONS = ".4."
var CHECK_HREFS = false
var CONTENTS = "CntTool.htm"
var INDEX = "IdxTool.htm"
var SEARCH = "SrhTool.htm"
var NAVUI = "NavUI.htm"
var TOOLUI = "ToolUI.htm"
var STATUS = "Status.htm"
var MESSAGE_BGCOLOR = "#fafad2"
var TOOL_BGCOLOR = "#99ccff"
//trace( "System.js" )
// Runtime error handling.
// window.onerror = errHandler
// Version stamp.
if ( STAMP_CONSOLE && navigator.javaEnabled() ) {
java.lang.System.out.println( "System.js, version " + VERSION )
java.lang.System.out.println( "Client: " + navigator.appVersion )
}
/*
DESCR: Handles the onhelp event.
PARAMS: URL The URL to load.
RETURNS:
NOTES:
*/
function onHelpHandler( URL )
{
//trace( "onHelpHandler(" + URL + ")" )
//alert( "onHelpHandler(" + URL + ")" )
systemObj.loadTopic( URL, false )
}
/*
DESCR: Traces execution to the console.
PARAMS: msg The trace text.
RETURNS:
NOTES:
*/
function trace( msg )
{
if ( TRACE ) java.lang.System.out.println( "System: " + msg )
}
// Create system object.
var systemObj = new system( JAVA_DEPENDENT, OK_NAV_VERSIONS )
assert( ( typeof( systemObj ) == "object" ), SYS_CONSTRUCT )
/*
DESCR: Help implementation system class.
PARAMS: bJavaDependent Pass true if the system is Java dependent,
false if not.
OKNavVersions String representing valid versions of Navigator.
RETURNS:
NOTES:
*/
function system( bJavaDependent, OKNavVersions )
{
//trace( "system constructor" )
this.backStack = new stack()
this.forwardStack = new stack()
this.navVersion
this.topic
this.contents
//this.aSysSecWnds = new Array() // Sys-owned secondary windows.
this.currentTool = CONTENTS // Set default tool.
this.bIdxTitlesPageUp = false
this.currentSubsystem = ""
this.visibleLayerIdx = ""
this.bToolUIloaded = false
this.bNavUIloaded = false
this.bContentsLoaded = false
this.bIndexLoaded = false
this.bStarted = false
this.bNewSubsystem = false
this.preproc = preproc
this.componentCallback = componentCallback
this.idxTitlesUp = idxTitlesUp
this.loadTopic = loadTopic
this.newSubsystem = newSubsystem
this.exit = exit
this.print = print
this.back = back
this.forward = forward
//this.openSecWnd = openSecWnd
this.loadTool = loadTool
this.setToolButton = setToolButton
this.msg = msg
this.manageLayers = manageLayers
this.badURLerror = badURLerror
this.componentsReadyEvt = componentsReadyEvt
this.loadEvt = loadEvt
this.unloadEvt = unloadEvt
this.stashPersistentData = stashPersistentData
this.snatchPersistentData = snatchPersistentData
// Preprocessing.
if ( !this.preproc( bJavaDependent, OKNavVersions ) ) {
return
}
// Load components.
top.StatusFrame.location.replace( STATUS )
top.ToolUIFrame.location.replace( TOOLUI )
top.NavFrame.location.replace( NAVUI )
top.ToolFrame.location.replace( this.currentTool )
}
/*
DESCR: Pre-Help processing.
PARAMS: bJavaDependent Pass true if the system is Java dependent,
false if not.
OKNavVersions String representing valid versions of Navigator.
RETURNS:
NOTES:
*/
function preproc( bJavaDependent, OKNavVersions )
{
//trace( "preproc()" )
// Make sure Java is enabled if needed. Otherwise, abort.
if ( bJavaDependent && !navigator.javaEnabled() ) {
this.msg( NO_JAVA_ERR_MSG, "" )
return false
}
// Validate version of navigator. Render in ".integer." form.
var version = navigator.appVersion
this.navVersion =
"." + version.substring( 0, ( version.indexOf( "." ) + 1 ) )
if ( OKNavVersions.indexOf( this.navVersion ) == -1 ) {
this.msg( WRONG_NAV_VER_ERR_MSG, "" )
return false
}
return true
}
/*
DESCR: Tracks component loading.
PARAMS: componentName The document-name of the component.
RETURNS:
NOTES: Components call this method on load. Triggers ready
event when all loaded.
*/
function componentCallback( componentName )
{
//trace( "componentCallback(" + componentName + ")" )
//alert( "componentCallback(" + componentName + ")" )
// Track component loading.
// Note: for some reason, can't write to status frame until Contents
// is loaded, so we do this later.
//if ( componentName == STATUS ) top.StatusFrame.setStatusWait()
if ( componentName == TOOLUI ) this.bToolUIloaded = true
if ( componentName == NAVUI ) this.bNavUIloaded = true
if ( componentName == CONTENTS ) {
// Keep house.
top.StatusFrame.setStatusWait()
top.ToolUIFrame.bDisableBtnBar = false
this.bContentsLoaded = true
this.bIndexLoaded = false
// Create a Contents object.
this.contents = new top.ToolFrame.contents( TOOL_BGCOLOR )
assert( ( typeof( this.contents ) == "object" ), CNT_CONSTRUCT )
// If this is not a system load and we're just changing to the
// Contents tool, set the Content's dataset and update. Otherwise,
// this will happen when a topic is loaded.
if ( this.bStarted ) {
this.contents.setDataset( this.currentSubsystem )
this.contents.updateTree( this.topic.URL )
top.StatusFrame.setStatusClear()
}
}
if ( componentName == INDEX ) {
top.ToolUIFrame.bDisableBtnBar = false
this.bIndexLoaded = true
this.bContentsLoaded = false
if ( this.bStarted ) top.StatusFrame.setStatusClear()
}
// Set the blender button down for the current tool.
if ( componentName == TOOLUI ) {
this.setToolButton( ( this.currentTool == CONTENTS ? 0 : 1 ), 1 )
}
// Get moving if we're ready, but not already underway.
if ( !this.bStarted &&
this.bToolUIloaded && this.bNavUIloaded &&
( this.bContentsLoaded || this.bIndexLoaded ) ) {
this.bStarted = true
this.componentsReadyEvt()
}
}
/*
DESCR: Handles components ready "event."
PARAMS:
RETURNS:
NOTES:
*/
function componentsReadyEvt()
{
//trace( "componentsReadyEvt()" )
// Set onhelp handler.
top.setOnhelpHandler( "onHelpHandler" )
}
/*
DESCR: Enables external state-setting of the tool UI button bar.
PARAMS: buttonIdx Identifies the button on the bar.
newState The state to set.
RETURNS:
NOTES:
*/
function setToolButton( buttonIdx, newState )
{
//trace( "setToolButton" )
assert( defined( top.ToolUIFrame.btnBar ), TOOLUI )
if ( defined( top.ToolUIFrame.btnBar ) ) {
// Set.
with ( top.ToolUIFrame.btnBar.aButtons[ buttonIdx ] ) {
setState( newState )
bOn = true
}
}
}
/*
DESCR: onload handler.
PARAMS:
RETURNS:
NOTES:
*/
function loadEvt()
{
//trace( "loadEvt()" )
//alert( "loadEvt()" )
// Snatch important data for persistence on reload due to window resizing.
this.snatchPersistentData()
}
/*
DESCR: onunload handler.
PARAMS:
RETURNS:
NOTES:
*/
function unloadEvt()
{
//trace( "unloadEvt()" )
//alert( "unloadEvt()" )
// Stash important data for persistence on reload due to window resizing.
this.stashPersistentData()
// Clean up topic (topic-owned secondary windows, etc.).
if ( defined( this.topic ) ) this.topic.destruct()
// Close any system-owned secondary windows.
//for ( var i = 0; i < this.aSysSecWnds.length; i++ ) {
// if ( defined( this.aSysSecWnds[ i ] ) ) this.aSysSecWnds[ i ].close()
//}
}
/*
DESCR: Stores data needed to maintain state on reload due to resize.
PARAMS:
RETURNS:
NOTES:
*/
function stashPersistentData()
{
//trace( "stashPersistentData" )
if ( defined( top.aPersistentData ) ) {
var i = 0
top.aPersistentData[ i++ ] = this.currentTool
top.aPersistentData[ i++ ] = this.forwardStack
top.aPersistentData[ i++ ] = this.backStack
//this.topic
//this.visibleLayerIdx
}
}
/*
DESCR: Retrieves data needed to maintain state on reload due to resize.
PARAMS:
RETURNS:
NOTES:
*/
function snatchPersistentData()
{
//trace( "snatchPersistentData" )
if ( defined( top.aPersistentData[ 0 ] ) ) {
var i = 0
this.currentTool = top.aPersistentData[ i++ ]
this.forwardStack = top.aPersistentData[ i++ ]
this.backStack = top.aPersistentData[ i++ ]
}
}
/*
DESCR: Loads the Contents, Index, or Find tool.
PARAMS: toolName The document-name of the tool.
RETURNS:
NOTES:
*/
function loadTool( toolName )
{
//trace( "loadTool(" + toolName + ")" )
assert( ( toolName == CONTENTS ||
toolName == INDEX ||
toolName == SEARCH ), TOOLNAME )
// Contents tool.
if ( toolName == CONTENTS && !this.bContentsLoaded ) {
// Keep house.
top.StatusFrame.setStatusWait()
top.ToolUIFrame.bDisableBtnBar = true
top.ToolFrame.location.replace( toolName )
}
// Index tool.
else if ( toolName == INDEX && !this.bIndexLoaded ) {
// Keep house.
top.StatusFrame.setStatusWait()
top.ToolUIFrame.bDisableBtnBar = true
top.ToolFrame.location.replace( toolName )
}
// Search tool.
else if ( toolName == SEARCH ) {
// We are using native find functionality in lieu of Search tool.
// Be sure to invoke Find against the topic frame.
top.TopicFrame.find()
}
// Track current tool, but exempt the search tool since we are just
// using Find and we still have a Help tool loaded.
if ( toolName != SEARCH ) this.currentTool = toolName
}
/*
DESCR: Closes the Help window.
PARAMS:
RETURNS:
NOTES:
*/
function exit()
{
//trace( "exit()" )
// Close frameset.
top.close()
}
/*
DESCR: Moves back in Help history.
PARAMS:
RETURNS:
NOTES: Presumes button is disabled on empty stack.
*/
function back()
{
//trace( "back()" )
// Since the Index's titles page may be in the topic frame, but not
// part of history, we don't really wan't to go Back. Just restore
// the current topic without adding it to history.
if ( this.bIdxTitlesPageUp ) {
this.loadTopic( this.topic.URL, false )
return
}
assert( !this.backStack.isEmpty(), BACK_STACK )
this.forwardStack.push( this.topic.URL )
this.loadTopic( this.backStack.pop(), true )
}
/*
DESCR: Moves forward in Help history.
PARAMS:
RETURNS:
NOTES: Presumes button is disabled on empty stack.
*/
function forward()
{
//trace( "forward()" )
assert( !this.forwardStack.isEmpty(), FORWARD_STACK )
this.backStack.push( this.topic.URL )
this.loadTopic( this.forwardStack.pop(), true )
}
/*
DESCR: Tracks the Index's topic titles page in the topic window.
PARAMS:
RETURNS:
NOTES:
*/
function idxTitlesUp()
{
//trace ( "idxTitlesUp()" )
this.bIdxTitlesPageUp = true
// The Index titles page is not part of the topics history, so make
// sure that Forward is disabled and Back is enabled.
assert( defined( top.NavFrame.btnBar ), NAV_BAR )
if ( defined( top.NavFrame.btnBar ) ) {
top.NavFrame.btnBar.aButtons[ 0 ].enable( true )
top.NavFrame.btnBar.aButtons[ 1 ].enable( false )
}
}
/*
DESCR: Handles tasks when the Help subsystem changes.
PARAMS: newSubsystem A simple filename representing the subsystem
(the topic filename).
RETURNS:
NOTES:
*/
function newSubsystem( newSubsystem )
{
//trace( "newSubsystem('" + newSubsystem + "')" )
//alert( "newSubsystem('" + newSubsystem + "')" )
assert( ( newSubsystem.toLowerCase().indexOf( ".htm" ) > -1 ),
SUBSYS_VALUE + newSubsystem )
// Track the current subsystem.
this.currentSubsystem = newSubsystem
// Reinitialize the visible layer index, since nothing is visible yet.
this.visibleLayerIdx = ""
// Load the new header.
top.HeaderFrame.location.replace( this.topic.headerURL )
// Set the Contents tool's dataset.
if ( this.currentTool == CONTENTS ) {
this.contents.setDataset( newSubsystem )
}
}
/*
DESCR: Loads a topic.
PARAMS: URL The non-nethelp version of the URL.
bHistoryLoad true if this is a load due to Back or Forward;
false, otherwise.
RETURNS:
NOTES:
*/
function loadTopic( URL, bHistoryLoad )
{
//trace( "loadTopic(" + URL + ")" )
assert( ( URL.toLowerCase().indexOf( ".htm" ) > -1 ), URL_VALUE + URL )
// Update Index titles page flag. If we are loading a topic, it can't
// be the URL in the topic window.
this.bIdxTitlesPageUp = false
// Keep house if there is an existing topic...
if ( defined( this.topic ) ) {
// Track as history, if this is _not_ a history load, and if we are
// not reloading the same URL for some (good) reason. Note that
// forward stack should be cleared.
if ( !bHistoryLoad && ( this.topic.URL != URL ) ) {
this.backStack.push( this.topic.URL )
this.forwardStack.clear()
}
// "Destruct" the current topic.
this.topic.destruct()
}
// See if we need to change subsystems.
var bNewSubsystem =
( makeSimpleFilename( URL ) != this.currentSubsystem ? true : false )
// If we're loading a new topic file, set the wait indicator.
if ( bNewSubsystem ) top.StatusFrame.setStatusWait()
// Create new topic object. Must happen before updating subsystem.
this.topic = new helpTopic( URL )
assert( ( typeof( this.topic ) == "object" ), TOPIC_CONSTRUCT )
// Update current subsystem. Must happen before updating Contents tree
// or managing layers.
if ( bNewSubsystem ) this.newSubsystem( makeSimpleFilename( URL ) )
// Enable/disable history buttons.
assert( defined( top.NavFrame.btnBar ), NAV_BAR )
if ( defined( top.NavFrame.btnBar ) ) {
var bEnable
bEnable = ( this.backStack.isEmpty() ? false : true )
top.NavFrame.btnBar.aButtons[ 0 ].enable( bEnable )
bEnable = ( this.forwardStack.isEmpty() ? false : true )
top.NavFrame.btnBar.aButtons[ 1 ].enable( bEnable )
}
// Update Contents tree.
if ( this.currentTool == CONTENTS ) this.contents.updateTree( URL )
// Layers are managed on topic file load (to ensure the layers exist),
// but since an anchor "load" in the current URL generates no load
// event, we need to call manageLayers() here under such conditions.
if ( LAYERED_TOPICS && !this.bNewSubsystem ) this.manageLayers()
}
/*
DESCR: Manages layers if layered topics is turned on.
PARAMS:
RETURNS:
NOTES: This is called from the topic onload handler, to be sure the
document is loaded, or it is called from loadTopic() if the
subsystem has not changed, since such a load is via a named
anchor and does not raise an onload event.
*/
function manageLayers()
{
//trace( "manageLayers()" )
if ( !LAYERED_TOPICS ) return
// Bail if there are no layered topics.
if ( !defined( top.TopicFrame.document.layers[ 0 ] ) ) return
// Hide any currently visible topic.
if ( this.visibleLayerIdx != "" ) {
top.TopicFrame.document.layers[ this.visibleLayerIdx ].hidden = true
}
// Unhide the topic layer.
top.TopicFrame.document.layers[ this.topic.fragmentSpec ].hidden = false
// Stash this index.
this.visibleLayerIdx = this.topic.fragmentSpec
}
/*
DESCR: Creates an always-on-top message box with an OK button.
PARAMS: msgText The message text.
msgCaption The window caption.
RETURNS:
NOTES: The message box is asynchronous, except that the OK button's
window.close() will not execute until the JS in the calling
window executes. Note that parser can't hack whitespace in
third parm of open().
*/
function msg( msgText, msgCaption )
{
//trace( "msg(" + msgText + ")" )
if ( msgCaption == "" ) msgCaption = DEFAULT_MESSAGE_CAPTION
var msgDlg =
window.open( "", "",
"SCROLLBARS=no,WIDTH=350,HEIGHT=200,SCROLLBARS=yes,ALWAYSRAISED=yes,DEPENDENT=yes,TITLEBAR=no,MENUBAR=no,HOTKEYS=no" )
var html
html = "<HEAD><TITLE>" + msgCaption +
"</TITLE></HEAD><BODY BGCOLOR = " + MESSAGE_BGCOLOR + ">"
html += msgText
html += "<BR><BR><BR><BR>"
html += "<CENTER><FORM METHOD = POST>"
html += "<INPUT TYPE = button NAME = 'OK' VALUE = ' " +
OK_BTN_LABEL +
" ' ONCLICK = 'window.close()'></FORM></CENTER></BODY>"
msgDlg.document.write( html )
msgDlg.document.close()
}
/*
DESCR: Creates a secondary content window.
PARAMS: URL The content URL.
name The window name.
features The feature string.
bSystem true if the window should be system-owned (i.e.,
window will not be closed when parent topic
closes, only when the system shuts down);
false, if topic-owned.
bReturnObj true if the window object should be returned.
RETURNS: Optionally, the window object.
NOTES:
*/
/*
function openSecWnd( URL, name, features, bSystem, bReturnObj )
{
//trace( "openSecWnd(" + URL + ")" )
// Create a system- or topic-owned seconadary window.
var newWnd
var bAlreadyExists = false
if ( bSystem ) {
newWnd = window.open( URL, name, features )
// Add window to list only if it is a new window (user may create
// a secondary more than once).
for ( var i = 0; i < this.aSysSecWnds.length; i++ ) {
if ( this.aSysSecWnds[ i ] == newWnd ) {
if ( bReturnObj ) return newWnd
else bAlreadyExists = true
}
}
if ( !bAlreadyExists ) {
this.aSysSecWnds[ this.aSysSecWnds.length ] = newWnd
if ( bReturnObj ) return newWnd
}
}
else {
newWnd = this.topic.addSecondary( URL, name, features )
if ( bReturnObj ) return newWnd
}
}
*/
/*
DESCR: Creates a bad URL type error.
PARAMS: href The offending href.
RETURNS:
NOTES:
*/
function badURLerror( href )
{
this.msg( BAD_HREF_ERR_MSG + "<P>" + href, "" )
}
/*
DESCR: Prints the content in the topic frame.
PARAMS:
RETURNS:
NOTES:
*/
function print()
{
//trace( "print()" )
top.TopicFrame.print()
}
// End class definition: system.
/*
DESCR: Help topic class.
PARAMS: URL The non-nethelp form of the URL.
RETURNS:
NOTES:
*/
function helpTopic( URL )
{
//trace( "helpTopic constructor" )
assert( ( URL.toLowerCase().indexOf( ".htm" ) > -1 ),
TOPIC_URL_VALUE + URL )
this.headerURL
this.URL = URL
this.fragmentSpec = URL.substring( URL.lastIndexOf( "#" ) + 1 )
assert( this.fragmentSpec != "", FRAG_SPEC )
//this.aSecWnds = new Array() // Secondary windows.
this.destruct = destruct
//this.addSecondary = addSecondary
//this.closeSecondaries = closeSecondaries
// Determine header URL by naming convention.
var extPos
extentionPos = this.URL.indexOf( ".htm" )
if ( extentionPos == -1 ) extentionPos = this.URL.indexOf( ".HTM" )
assert( ( extentionPos != -1 ), TOPIC_FILENAME )
this.headerURL = this.URL.substring( 0, extentionPos ) + "Hdr.htm"
// Load URL in the topic frame.
top.TopicFrame.location.replace( this.URL )
}
/*
DESCR: Adds a secondary window.
PARAMS: URL The content URL.
name The window name.
features The feature string.
RETURNS:
NOTES:
*/
/*
function addSecondary( URL, name, features )
{
//trace( "addSecondary()" )
var newWnd = window.open( URL, name, features )
// Add window to list only if it is a new window (user may
// create a secondary more than once).
for ( var i = 0; i < this.aSecWnds.length; i++ ) {
if ( this.aSecWnds[ i ] == newWnd ) return newWnd
}
this.aSecWnds[ this.aSecWnds.length ] = newWnd
return newWnd
}
*/
/*
DESCR: Closes all secondary windows.
PARAMS:
RETURNS:
NOTES:
*/
/*
function closeSecondaries()
{
//trace( "closeSecondaries()" )
for ( var i = 0; i < this.aSecWnds.length; i++ ) {
if ( defined( this.aSecWnds[ i ] ) ) this.aSecWnds[ i ].close()
}
}
*/
/*
DESCR: "Destructor."
PARAMS:
RETURNS:
NOTES:
*/
function destruct()
{
//trace( "helpTopic destruct()" )
// Close any secondary windows owned by current topic.
//this.closeSecondaries()
}
// End class definition: helpTopic.
/*
DESCR: Popup class.
PARAMS:
RETURNS:
NOTES:
*/
// End class definition: popup.