// glOpen.js
// (c) 2002 Instituto Lingüístico de Verano, A.C.
// Revised: Mon Apr  1 15:29:04 MST 2002
// by Albert Bickford

/*
For links into the glossary to individual entries, open a popup window for a link
if the browser supports scripting.
However, do it in a way that non-scripting browsers will still follow
the link normally.
*/

// **********************************************************

// Initialization of the script (all files that link to the glossary entries or diagrams)
// This code is run as soon as the script is loaded.

// Determine browser and version
// Currently we're only trying to support version 4 & above.
var nName = navigator.appName.toLowerCase();
var nVersMajor = parseInt(navigator.appVersion);
var isIE = (nName.indexOf('microsoft')!=-1);
var isIE3 = (isIE && (nVersMajor == 3));
var isIE4up = (isIE && (nVersMajor >= 4));
var isNS = (nName.indexOf('netscape')!=-1);
var isNS3 = (isNS && (nVersMajor == 3));
var isNS4up = (isNS && (nVersMajor >= 4));
var isNS6up = (isNS && (nVersMajor >= 5));
var is4up = (isIE4up || isNS4up);
/*
alert( "Browser name: " + nName + "; " + 
       "Browser version: " + nVersMajor + "; " +
       "Browser flags: "+isIE+" "+isIE3+" "+isIE4up+"; "+
                         isNS+" "+isNS3+" "+isNS4up+" "+isNS6up+"; "+
                         is4up );
*/

// alert("Ready to define glInit");

// **********************************************************

// glInit()
// Initialize each page that is part of the glossary system.
// Called primarily by <body onload=...>, which needs to be in each HTML file that uses
// the system.  Also called once below, when opening a document in an already used window.
function glInit(w) {
  if (!is4up) return;
  // alert("In glInit");

  // If this file is the first one to be opened in the glossary system,
  // that is, if it was not opened and given a name by one of the functions below,
  // identify its window as the main entry point to the system.
  // Any links that point outside the glossary files will be opened
  // in this window, which is presumably large enough for ordinary browsing.  
  // If the window already has a name from some other source,
  // don't disturb it (especially because in that case it probably is a frame
  // in a frameset).  The worst that will happen is that it won't be
  // re-used if the user jumps outside the glossary system,
  // and one additional window will be opened.
  if (!w.name) {
    w.name = "glMain";
  }
  w.status = w.defaultstatus = w.name // for DEBUGging

  // Maybe also, if this window already has a gl name, find out if it's opener
  // should become glMain (even if it's not part of the glossary, as long as it
  // is running this script).  In theory, that should have happened when the
  // opener ran this script, but that window may have a name from some other source.

  // make sure I'm visible (e.g. if I'm being opened in a window that is already
  // opened but buried).
  w.focus();
  
  // Special treatment for glossary (glEntry) windows, 
  // to call user's attention to subentries.
  // This needs to be done here for Netscape to work at all, and also in IE if user
  // refreshes a window.
  glSubentry(w);
  
  // May need to develop the following code for Nav. IE doesn't need it.
  // If I am a glossary entry window and I have a bookmark specified...
  // if ( self.name=="glEntry" ) {
    // alert( "I am a glossary entry" );
  // }

}

// **********************************************************

// glEntry()
// Open a relatively small window for displaying a single glossary entry
function glEntry(link) {

  if (!is4up) return;
  // alert( "In glEntry; link is: " + link);
  if (isNS3) {
    // Netscape 3 doesn't recognize the onclick attribute in an image map.  This
    // essentially means that we can't jump from the glDiag windows (which have a lot
    // of image maps) to glEntry, and thus it would be better not to open
    // a separate glEntry window at all.  So, if we ever support NS3,
    // maybe open all the glossary entries in glDiag for NS3.
    // glDiag(link);
  } else {
    glOpen( "glEntry", link, 400, 250, 0, "left" );
    // alert( "Back in glEntry" );
  }
}

// **********************************************************

// glSubentry()
// Special code used to call a user's attention to a subentry.
// Arg:
//   w: a window which contains one or more glossary entries
// Should be called whenever a window is a glossary entry,
// in case there is a subentry requested, and to erase highlighting
// on any previous subentries.
function glSubentry(w) {
  if (!is4up) return;
  if (isNS) { idCollection = w.document.layers; }
    // NS 4 doesn't recognized div tags with id as layers,
    // so the highlighting doesn't happen.  This seems to be harmless,
    // the highlighting code is skipped when the div's can't be found.
    // Need to test with newer versions of Netscape: 4.8x and 6.x.
  if (isIE) { idCollection = w.document.all; }

  // if there is a highlighted subentry from a previous appearance of the file in this window...
  if (idCollection["glHighlight"] ) { 
    oldHL = idCollection["glHighlight"] 
    // ... unhighlight it, recovering original id, if available (which it should always be).
    if ( oldHL.formerid ) {
      oldHL.id=oldHL.formerid; 
    } else { 
      oldHL.id="" ; 
    }
  }
  
  // The anchor name uses a _ in the production version, but a dash in 
  // the development version.  The id always uses a dash.
  anchorName = w.location.hash;
  id = anchorName.replace( "_", "-" );  id = id.replace( "#", "" ); 
  // alert( "id: " + id + "; anchorName: " + anchorName );

  // If the current target is a subentry within an entry...
  if ( id.search("^Defn.*-") > -1 ) { // don't just test for a dash, because it can occur in anchors that aren't for glossary entries
    // ... scroll the window slightly backward, 
    //     so user can see that this is part of a larger entry.
    // Bug: in IE, when a window is refreshed, the new scroll is done on top of the old one.
    // There seems to be no way to prevent this, except not to scroll at all.
    // (Also happens when a link with the "-" form is used when the window
    // is already open at the div tag with that id, but this shouldn't happen 
    // in the production version, which will only use the "_" form with <a> tags.)
    // Disabled 2001-01-13, to see if we really need it.
    // w.scrollBy(0, -30);
    // ... Also highlight the subentry (identified by a div tag), if we can find it.
    if (idCollection[id]) {
      subentry = idCollection[id]
      // alert( "ready to highlight" + id );
      subentry.formerid = id; // remember what the id is supposed to be, in case we highlight something else later
      subentry.id = "glHighlight";
      // It would be nice to dim the other entries, but I can't seem to find
      // a way that will work to change the color of the text outside the entry.
      // That is, ideally, the "highlight" should be the same color as what people
      // normally read, and the rest of the text in the file should be dimmed.
    }
  }
}
      
// **********************************************************

// glDiag()
// Open a medium-sized window for displaying a diagram.
function glDiag(link) {
  if (!is4up) return;
  //alert("In glDiag");

  // Aim to keep it about 2/3 the total screen size and in a portrait orientation.
  // Make it at least 550 wide
  // so the head diagrams and phonetic charts can be fully visible, 
  // (especially since we can't reliable allow the user to resize windows under NS4).
  // The widest diagram (vowel chart) is about 520.
  // 450 is too large for 640x480, but it is further limited in glOpen().
  w = 550; h = 450;
  // with newer browsers, we can fine-tune it to match available space.
  if( is4up ) { 
    with (Math) {
      w = max(floor(window.screen.width*.5),w);
      h = max(floor(window.screen.height*.8),h);
    }
  }
  // alert("glDiag requesting dimensions of " + w + "x" + h);
  glOpen( "glDiag", link, w, h, 0, "right" );
}

// **********************************************************

// glOutside()
// When linking to a page outside the glossary,
// don't open it in one of the popup windows for entries or diagrams.
// Rather, open it in the window that served as the entry point
// to the glossary system (which is presumably a full-sized window),
// if that window is still open; otherwise open a new window.
function glOutside(link) {
  if (!is4up) return;
  // If the glMain window has been closed and needs to be reopened,
  // make it the default size, so specify width and height as zero.
  // I used to make it as large as possible, but that seemed to cause
  // Netscape 4 to re-size an existing window and make it non-resizable!
  glOpen( "glMain", link, 0, 0, 1, "default" );
}

// **********************************************************

// glOpen()
// The core function that does all the hard work:
// Open a named window with a specified name and properties.
// Use the url of the specified link.
// If w (width) and/or h (height) are zero, use default size/location.
// n should be 0/no or 1/yes; it indicates if all the normal toolbars, etc. should be present.
// If align is "right", position window towards right of screen, if possible.
// There are separate techniques for NS and IE scattered through this procedure.
function glOpen( glName, link, w, h, n, align ) {

  // *** Browser check
  if (!is4up) return;
  
  // *** Identify the link ******************************
  // The link can be retrieved by IE from the HTML code, as follows:
  // link = self.event.srcElement;
  // But NS doesn't seem to be able to do this.  So, we'll rely on passing the
  // link in the function calls, and not try anything fancy.
  // However, we should do some error checking.  
  // I haven't yet tested whether this code actually works, since so far all my
  // links have passed themselves properly.
  if (!link) {
    // alert("Can't find link");
    return; // Let the original link control the behavior.
  }
  // alert( "Clicked on link to "+link.href+"; from window: " + self.name );

  // *** Compute window size and location ******************************
  // If w or h are 0, they are not changed by the code below.
  //   This means to open the window at the default size and location
  //   (without specifying them from here).  In this case, too, adjustments to l and t
  //   are ignored later.
  // If w or h are between 1 & 100, the browser should automatically reset them
  //   to a minimum of 100, so we don't have to worry about that possibility here.
  if ( is4up ) {
    with (Math) {
      wsw=window.screen.width;
      wsh=window.screen.height;
      // alert( "dimensions requested: w:"+w+"   h:"+h);
      // limit size of window to a portion of screen width and height 
      // (allowing for menus and toolbars).
      w = min( w, floor(wsw*.9));  
      if (isNS6up) { w = max( w, 500 ) } /* NS6 hides the scrollbar if screen width is less than  
                                            min. width of the navigation toolbar.
                                            The figure of 500 is for the modern (default) skin
                                            with all buttons displayed. */
      h = min( h, wsh-160 ); // need about 160 (!) pixels for all the toolbars that modern browsers use, regardless of screen height
      // set left and top so that the smaller windows are farther left and higher,
      // so they don't get covered up by the bigger ones.
      // (This is less necessary now that we're using left/right justification of windows,
      // but it may be useful in the future.)
      l = floor(.1*w*w/wsw);
      t = floor(.1*h*h/wsh);
      // On small screens, make offsets even smaller
      if ( wsw < 700 ) {
        l = floor( .5*l*w/wsw );
        t = floor( .5*t*h/wsh );
      }
    }
    // Compensate for Navigator 4's inability to allow user to reposition window
    // by opening certain windows right-justified.
    // This is a nice feature for IE, too, but we have to guess at
    // border width to do it, since JScript lacks the properties to compute it accurately.
    // alert( "Computing left/right justification; current l is " + l );
    if ( align=="right" ) {
      // Determine how much to allow for window borders
      if ( isNS ) {
        wborder = Math.min(self.outerWidth - self.innerWidth, 20);
        // if the sidebar is open in NS6, its width gets included
        // in wborder, so in that case, just guess.
      } else {
        // for IE, guess, but make a conservative (high) estimate, 
        // to avoid putting the window off the screen.
        wborder = 20;
      }
      // Determine size of entire new window (with borders)
      wtot = w + wborder;
      // Determine total free space outside the new window
      wfree = wsw - wtot;
      // Swap left and right
      l = wfree - l;
      /* alert( "w: " + w +
             ";  wborder: " + wborder +
             ";  wtot: " + wtot +
             ";  wsw: " + wsw +
             ";  wfree: " + wfree +
             ";  l: " + l );
             */
    }
    if ( align=="left" || align=="right" ) {
      // If we're using left or right justification, then we don't need to fiddle
      // with the top free space.  It looks nicer if it doesn't vary between windows.
      t = Math.floor(.02*wsh);
    }
  } else {
    // Older browsers don't recognize the width property of the screen object,
    // so leave w and h alone (without trying to correct for screen size)
    // and make a rough guess at l and t.  This could be done better by
    // copying code from above, but is probably not worth the bother.
    l = Math.floor(.1*w); 
    t = Math.floor(.1*h);
  }
  // alert( "w: " + w + " l: " + l + ";     h: " + h + " t: " + t );

  // *** Construct option string for opening the new window
  // options = "scrollbars=yes,toolbar=yes,resizable=" ;
  options = "scrollbars=yes,toolbar=yes,resizable=" ;
  if (isNS && !isNS6up) {
    // Versions of Netscape through 4.x reset the window size and location every time it opens,
    // so don't delude the user into thinking they can resize it.
    // (I tried once to get Netscape 4 to open the window first, without size specified,
    // then to resize it if it hadn't been opened before.  Nothing seemed to work
    // quite right--either there were exceptions that crashed Netscape or the timing worked
    // out wrong so that the window was resized after the document was located, thus
    // messing up what entry was being pointed to.  So, I gave up.)
    options += "no";
  } else {
    options += "yes";
  }
  // n is the function argument that indicates whether the normal window elements
  // should be present; it has values 0/no or 1/yes.
  n = 1; // for debugging only
  options += ",status="+n+",location="+n+",menubar="+n ;
  // if w and h are 0, that means to use default size/location.
  if (w>0) options += ",width="+w+",left="+l ;  
  if (h>0) options += ",height="+h+",top="+t ;
  // alert( "glOpen options are: " + options );

  // *** Open the new window (or reactivate it)
  tWin = window.open( "", glName, options);

  // *** Make sure the new window is on top.
  // The following command sometimes seems to cause errors
  // if it is issued too soon after a URL is opened in a window.
  // So, let's issue it before opening the URL.
  tWin.focus();

  // *** Open the document in the new window.
  // The two browsers require different approaches to actually
  // opening the new file in the target window.
  if (isIE) {

    // For IE, put the target file in the window using Javascript
    // rather than the original HTML code.
    tWin.location = link.href;
    window.event.returnValue = false;
    // The Netscape technique of changing the target attribute seems to be ignored in IE;
    // apparently we can't change the HTML target attribute once the event is in progress.
    
    // force the window to reinitialize if the document is not new to it, 
    // so any subentries get highlighted properly
    // alert("Ready to call glInit()");
    glInit(tWin); 

  } else { // i.e., if Netscape

    // For Netscape, tell the original link (in the HTML) to use the desired window.
    link.target = glName;
    // The IE technique of using Javascript doesn't seem to work in Netscape, because
    // I can't find a way to issue a return value of false 
    // to stop the original HTML link from firing.
    
    // BUG: This method does not cause the window to reinitialize when the new link
    // is in the document that is already open.  As a result, glSubentry doesn't 
    // always get called, so the backscrolling and highlighting doesn't happen.
    // Probably this is harmless, as it wouldn't be often that a user would 
    // jump to two senses of the same entry one after the other.
    // And, for Netscape 4.0x, the highlighting doesn't happen anyway.

  }

  // alert( "New window should be open and on top." );

}

// **********************************************************
// alert("entire script read and processed.");

