Go to:  Site entry | Site contents | Site index | Internet | JavaScript | Text bottom

Picture  Display  and  Navigation  (Picture  Album  Support)

PICTURE JavaScript is designed as a recursive HTML page that displays a picture to be viewed, and provides means (thumbnails, buttons, and keys) for proximity navigation through the picture album.

Click this link to have a look at simple example of picture album.  Click [Help] button in thumbnail window, and press [H] key in full-size picture display window (generated by PICTURE JavaScript) to get navigation help.  Here is picture album proximity navigation help:

Picture Help Pop-up

A single copy of PICTURE.HTM can work with all picture albums; it makes sense to keep it either at the root of directory structure, or in a separate directory (I keep it at the root of my web site).

Initial references to PICTURE JavaScript get imbedded by THUMBLST JavaScript into thumbnail list table.  Successive references to PICTURE.HTM get generated recursively by PICTURE itself (imbedded into full size picture view table).

The latest modifications of PICTURE JavaScript (12/2007) provided for picture centering (both horizontally and vertically) to make it look better on the newer bigger, and especially wider screens.

<!-- Picture Display with Proximity Navigation       08/24/200112/23/2007 -->
<!-- ---------------------------------------------------------- 10/03/2007 -->
<!-- www.davar.net/PICTURE.HTM                                             -->
<!-- Copyright (C) 20012007 by Vladimir Veytsel                           -->

<!-- Spaces in picture description are substituted for %20 to please the   -->
<!-- Apache server that doesn't tolerate spaces in the URL.  URL is used   -->
<!-- here to pass parameters to PICTURE.HTM from THUMBLST.JS (initially)   -->
<!-- and from itself (recursively for proximity navigation).               -->

<!-- Vertical split bar "|" is used as parameter delimiter for referencing -->
<!-- PICTURE.HTM that displays the full-size picture.  To avoid possible   -->
<!-- problems "|" is substituted for "!" in every picture description.     -->

<!-- To check URL parameter structure do [View]-[Show]-[Location Toolbar]  -->

  <LINK REL="shortcut icon" HREF="favicon.ico" TYPE="image/vnd.microsoft.icon">
  <META HTTP-EQUIV="Content-Type" CONTENT="Text/HTML; CharSet=ISO-88591">
  <META NAME      = Description
        CONTENT   ="Page: Picture Display Window.
                    Site: Davar Web Site,
                          Computer Science, Programming, Mainframe, Client/Server, PC, Internet,
                          Mathematics, Go, Zen, Quotations, Extracts, Humor, Russian.">
  <META NAME      = Keywords
        CONTENT   ="Davar Web Site, Picture display, Picture album, Picture gallery">
  <META NAME      = Author CONTENT="Vladimir Veytsel">

      Parm=location.search.substr(1)  // Get URL parameters
      Parameter=Parm.split("|")       // Parse parameters into an array

      Pict_Ind=Number(Parameter[0])   // Picture index within picture list
      Dn_Dir  =       Parameter[1]    // Down direct (relative to PICTURE.HTM)
                                      // that contains *.JS file, thumbnail dir
                                      // and picture dir (empty - current dir;
                                      // when specified should end with "/")
      Pict_Lst=       Parameter[2]    // *.JS file with picture list (in Dn_Dir)
      Thum_Dir=       Parameter[3]    // Direct with thumbnail JPGs  (in Dn_Dir)
      Pict_Dir=       Parameter[4]    // Direct with   picture JPGs  (in Dn_Dir)
      Title   =       Parameter[5].replace(/%20/g," ")  // Restore spaces

      document.write("<TITLE>#"+Pict_Ind+" - "+Title.replace(/\/'/g,"'").replace(/  /g,"  ")+"</TITLE>")

//    Preload images to the page - this turns out to be essential
//    for setting Status value along with highlighting buttons
//    with onMouseOver/onMouseOut event handlers that swap images.
//    (Names are insignificant - choose any descriptive enough)

      But_Fst_Act = new Image(13,13); But_Fst_Act.src="BUT-FSTA.GIF"
      But_Fst_Sel = new Image(13,13); But_Fst_Sel.src="BUT-FSTS.GIF"

      But_2Bk_Act = new Image(13,13); But_2Bk_Act.src="BUT-2BKA.GIF"
      But_2Bk_Sel = new Image(13,13); But_2Bk_Sel.src="BUT-2BKS.GIF"

      But_1Bk_Act = new Image(13,13); But_1Bk_Act.src="BUT-1BKA.GIF"
      But_1Bk_Sel = new Image(13,13); But_1Bk_Sel.src="BUT-1BKS.GIF"

      But_Stp_Act = new Image(13,13); But_Stp_Act.src="BUT-STPA.GIF"
      But_Stp_Sel = new Image(13,13); But_Stp_Sel.src="BUT-STPS.GIF"

      But_1Ah_Act = new Image(13,13); But_1Ah_Act.src="BUT-1AHA.GIF"
      But_1Ah_Sel = new Image(13,13); But_1Ah_Sel.src="BUT-1AHS.GIF"

      But_2Ah_Act = new Image(13,13); But_2Ah_Act.src="BUT-2AHA.GIF"
      But_2Ah_Sel = new Image(13,13); But_2Ah_Sel.src="BUT-2AHS.GIF"

      But_Lst_Act = new Image(13,13); But_Lst_Act.src="BUT-LSTA.GIF"
      But_Lst_Sel = new Image(13,13); But_Lst_Sel.src="BUT-LSTS.GIF"

      function Proc_Key(ev)
               {if (ev)  // Netscape
                if (Key!=0)  // Keys with zero ASCII value are ignored this is
                             // (essential to keep standard window functionality)
                   if (Key==13)  // [Enter] key was pressed
                      switch (String.fromCharCode(Key))
                             {case "F":  // Move to the First picture in the picture list
                              case "f":
                              case "{":
                              case "[":
                              case "B":  // Move two pictures Back
                              case "b":
                              case "<":
                              case ",":
                              case "P":  // Move to the Previous picture
                              case "p":
                              case "_":
                              case "-":
                              case "R":  // Return to the picture list (thumbnails)
                              case "r":
                              case ":":
                              case ";":
                              case "N":  // Move to the Next picture
                              case "n":
                              case "+":
                              case "=":
                              case "A":  // Move two pictures Ahead
                              case "a":
                              case ">":
                              case ".":
                              case "L":  // Move to the Last picture in the picture list
                              case "l":
                              case "}":
                              case "]":
                                   alert(// Comment out next two lines after debugging
//                                        "*** Key pressed - ASCII: "+Key
//                                       +"  Character: \""+String.fromCharCode(Key)+"\" ***\n\n"+
                                          "Click the big picture to return to picture list,  or click one of the thumbnails            "
                                         +"\n(or buttons) for circular proximity navigation.  As you move mouse cursor,"
                                         +"\nwatch the Status Bar at the bottom of the window  - text in it depends on"
                                         +"\nthe cursor position, and  either describes  selected object,  or prompts for"
                                         +"\na possible  action."
                                         +"\n\nTo avoid  confusion  don't  use  Windows Task Bar  to switch  between"
                                         +"\nthumbnail list and full-size picture windows."
                                         +"\n\nYou may press the following keys for proximity navigation in this window"
                                         +"\n(values shown below label keys to be pressed; entry is case-insensitive):"
                                         +"\n\n'F'  or  '['\t- Move to the First picture in the picture list"
                                         +"\n'B'  or  '<'\t- Move two pictures Back"
                                         +"\n'P'  or  '-'\t- Move to the Previous picture"
                                         +"\n'R'  or  ':'\t- Return to the picture list (thumbnails)"
                                         +"\n'N'  or  '+'\t- Move to the Next picture (or press [Enter] key)"
                                         +"\n'A'  or  '>'\t- Move two pictures Ahead"
                                         +"\n'L'  or  ']'\t- Move to the Last picture in the picture list"
                                         +"\n\n'H'  or  '?'\t- Display navigation help (this window)"
                                         +"\n\nBlinking of thumbnail number indicates that this picture is beyond upper"
                                         +"\nor lower list border (circular navigation is invoked)."
                                         +"\n\nTo save the picture  point to it with the mouse cursor,  click right mouse"
                                         +"\nbutton, and then proceed with  'Save Image As'  from the pop-up menu."
                                         +"\n\nPress any other symbolic key (character, digit or symbol) to display help."

      // Needed only for Microsoft IE and Netscape 4.x;
      // Causes event duplication in Netscape 7.x and Mozilla.
      if (( navigator.appName=="Microsoft Internet Explorer")||

      // Needed for Netscape 4.8; maybe for some other older browsers too...
      if ((navigator.appName=="Netscape")&&

      // For new browsers - checked with Firefox 2.0, Netscape 7.2, IE 6.0
      if (document.addEventListener)

    document.write("<BODY BACKGROUND='PAPER00",N,".JPG' BGCOLOR=White TEXT=Black LINK=Black ALINK=Black VLINK=Black>")
    document.write("<SCRIPT LANGUAGE=JavaScript SRC='",Dn_Dir,Pict_Lst,".JS'></SCRIPT>")

<FONT FACE="Times New Roman" SIZE=3>
        <TD ALIGN=Center>
          Essential functionality of this page<BR>
          depends on availability of JavaScript.<BR>
          Your JavaScript is either disabled,<BR>
          or not supported by your browser.</TD>
        <TD ALIGN=Center>
          Please <A HREF="../../ABOUT.HTM#JavaScript"><FONT COLOR=Red><BLINK><B>enable</B></BLINK></FONT></A> JavaScript<BR>
          and [<FONT COLOR=Red>Reload</FONT>] this page,<BR>
          or use [<FONT COLOR=Red>Back</FONT>] to <FONT COLOR=Red>exit</FONT>.</TD>
      Ind    = new Array(4)  // Index meaning:
      Numb   = new Array(4)  // 0 - Two back
      Pict   = new Array(4)  // 1 - One back
      Descr  = new Array(4)  // 2 - One ahead
      Target = new Array(4)  // 3 - Two ahead

      Button  = new Array(7)  // Full button image description (IMG tag)
      Pas_But = new Array(7)  // "xxxx" part of BUT-xxxx.GIF file name

      Pas_But[0]="FSTP"  // Passive buttons' "xxxx" values
      Pas_But[1]="2BKP"  // of the "BUT-xxxx.GIG" file name

      for (i=0;i<7;i++)  // Initialize button bar with passive button values
          Button[i]="<IMG SRC='BUT-"+Pas_But[i]+".GIF' ALT='Passive button'>"

      Curr_Pict =Picture[Pict_Ind].substr(0,8)+" "
      Curr_Pict =Curr_Pict.substr(0,Curr_Pict.indexOf(" "))


      if (Ind[0]<1)
      Target[0]="previous to the previous picture"

      if (Ind[1]<1)
      Target[1]="previous picture from the picture list"

      if (Ind[2]>Pict_Total)
      Target[2]="next picture from the picture list"

      if (Ind[3]>Pict_Total)
      Target[3]="next to the next picture"

      Descr_Last =Picture[Pict_Total].substr(9).replace(/\\\'/g,"'").replace(/\|/g,"!")

      for (i=0;i<4;i++)
           Pict[i]=Picture[Ind[i]].substr(0,8)+" "
           Pict[i]=Pict[i].substr(0,Pict[i].indexOf(" "))
           if (Ind[i]==1)
              Target[i]="first picture from the picture list"
           if (Ind[i]==2)
              Target[i]="second picture from the picture list"
           if (Ind[i]==Pict_Total)
              Target[i]="last picture from the picture list"
           if (Ind[i]==Pict_Total-1)
              Target[i]="second last picture from picture list"

      defaultStatus="Click left mouse button on the big picture to return to picture list (or click [x] at top-right)"

//    HREF values for PICTURE.HTM navigational recursive self-calls

      First_HREF    ="PICTURE.HTM?"+1+"|"+Dn_Dir+"|"+Pict_Lst+"|"+Thum_Dir+"|"+Pict_Dir+"|"+Descr_First.replace(/ /g,"%20")
      Two_Back_HREF ="PICTURE.HTM?"+Ind[0]+"|"+Dn_Dir+"|"+Pict_Lst+"|"+Thum_Dir+"|"+Pict_Dir+"|"+Descr[0].replace(/ /g,"%20")
      One_Back_HREF ="PICTURE.HTM?"+Ind[1]+"|"+Dn_Dir+"|"+Pict_Lst+"|"+Thum_Dir+"|"+Pict_Dir+"|"+Descr[1].replace(/ /g,"%20")
      One_Ahead_HREF="PICTURE.HTM?"+Ind[2]+"|"+Dn_Dir+"|"+Pict_Lst+"|"+Thum_Dir+"|"+Pict_Dir+"|"+Descr[2].replace(/ /g,"%20")
      Two_Ahead_HREF="PICTURE.HTM?"+Ind[3]+"|"+Dn_Dir+"|"+Pict_Lst+"|"+Thum_Dir+"|"+Pict_Dir+"|"+Descr[3].replace(/ /g,"%20")
      Last_HREF     ="PICTURE.HTM?"+Pict_Total+"|"+Dn_Dir+"|"+Pict_Lst+"|"+Thum_Dir+"|"+Pict_Dir+"|"+Descr_Last.replace(/ /g,"%20")

      if (Pict_Ind==1)  // "First" full button image description (IMG tag)
         Button[0]="<IMG SRC='BUT-FSTP.GIF' WIDTH=13 HEIGHT=13 BORDER=0'></A>"
         Button[0]="<A HREF="+First_HREF+" "
                  +"onMouseOver=\"document.But_Fst.src='BUT-FSTS.GIF'; window.status='Click left mouse button here to move to the first picture (on picture list)'; return true\""
                  +" onMouseOut=\"document.But_Fst.src='BUT-FSTA.GIF'; window.status=''; return true\">"
                  +"<IMG NAME='But_Fst' SRC='BUT-FSTA.GIF' WIDTH=13 HEIGHT=13 BORDER=0 ALT='Move to the first picture'></A>"

      if (Pict_Ind==Pict_Total)  // "Last" full button image description (IMG tag)
         Button[6]="<IMG SRC='BUT-LSTP.GIF' WIDTH=13 HEIGHT=13 BORDER=0'></A>"
         Button[6]="<A HREF="+Last_HREF+" "
                  +"onMouseOver=\"document.But_Lst.src='BUT-LSTS.GIF'; window.status='Click left mouse button here to move to the last picture (on picture list)'; return true\""
                  +" onMouseOut=\"document.But_Lst.src='BUT-LSTA.GIF'; window.status=''; return true\">"
                  +"<IMG NAME='But_Lst' SRC='BUT-LSTA.GIF' WIDTH=13 HEIGHT=13 BORDER=0 NAME='But_Lst' ALT='Move to the last picture'></A>"

//    Standard description heads for proximity navigation thumbnails and buttons

      Two_Back ="<A HREF="+Two_Back_HREF+" "
               +"onMouseOver=\"document.But_2Bk.src='BUT-2BKS.GIF'; window.status='Click left mouse button here to move two pictures back ("+Target[0]+")'; return true\""
               +" onMouseOut=\"document.But_2Bk.src='BUT-2BKA.GIF'; window.status=''; return true\">"

      One_Back ="<A HREF="+One_Back_HREF+" "
               +"onMouseOver=\"document.But_1Bk.src='BUT-1BKS.GIF'; window.status='Click left mouse button here to move one picture back ("+Target[1]+")'; return true\""
               +" onMouseOut=\"document.But_1Bk.src='BUT-1BKA.GIF'; window.status=''; return true\">"

      Return   ="<A HREF='javascript:void(window.close())' "
               +"onMouseOver=\"document.But_Stp.src='BUT-STPS.GIF'; window.status='Click left mouse button here to return to picture list (or click [x] at window top-right corner)'; return true\""
               +" onMouseOut=\"document.But_Stp.src='BUT-STPA.GIF'; window.status=''; return true\">"

      One_Ahead="<A HREF="+One_Ahead_HREF+" "
               +"onMouseOver=\"document.But_1Ah.src='BUT-1AHS.GIF'; window.status='Click left mouse button here to move one picture ahead ("+Target[2]+")'; return true\""
               +" onMouseOut=\"document.But_1Ah.src='BUT-1AHA.GIF'; window.status=''; return true\">"

      Two_Ahead="<A HREF="+Two_Ahead_HREF+" "
               +"onMouseOver=\"document.But_2Ah.src='BUT-2AHS.GIF'; window.status='Click left mouse button here to move two pictures ahead ("+Target[3]+")'; return true\""
               +" onMouseOut=\"document.But_2Ah.src='BUT-2AHA.GIF'; window.status=''; return true\">"

//    Adjusted description tails for proximity navigation thumbnails and buttons

      Thumb_Two_Back =""
      Thumb_One_Back =""

      if ((Pict_Total >4)||  // Move two pictures back
          (Pict_Total==4)&&(Pict_Ind >2)||
                        +"<IMG SRC='"+Dn_Dir+Thum_Dir+"/"+Pict[0]+".JPG' ALT=\"#"+Ind[0]+"("+Pict_Total+") - "+Descr[0]+"\" BORDER=1></A><BR>"
                        +"<FONT SIZE=2><FONT COLOR=Purple>Two</FONT> <FONT COLOR=Red>back</FONT> to #"+Numb[0]+"</FONT>"
                   +"<IMG NAME='But_2Bk' SRC='BUT-2BKA.GIF' WIDTH=13 HEIGHT=13 BORDER=0 ALT='Move two pictures back'></A>"
      if ((Pict_Total >3)||  // Move one picture back
                        +"<IMG SRC='"+Dn_Dir+Thum_Dir+"/"+Pict[1]+".JPG' ALT=\"#"+Ind[1]+"("+Pict_Total+") - "+Descr[1]+"\" BORDER=1></A><BR>"
                        +"<FONT SIZE=2><FONT COLOR=Green>One</FONT> <FONT COLOR=Red>back</FONT> to #"+Numb[1]+"</FONT>"
                   +"<IMG NAME='But_1Bk' SRC='BUT-1BKA.GIF' WIDTH=13 HEIGHT=13 BORDER=0 ALT='Move one picture back'></A>"

      Button[3]=Return  // Always present when button bar is shown
               +"<IMG NAME='But_Stp' SRC='BUT-STPA.GIF' WIDTH=13 HEIGHT=13 BORDER=0 ALT='Return to the picture list'></A>"

      if ((Pict_Total >3)||  // Move one picture ahead
         {Thumb_One_Ahead="<FONT SIZE=2><FONT COLOR=Green>One</FONT> <FONT COLOR=Blue>ahead</FONT> to #"+Numb[2]+"</FONT><BR>"
                         +"<IMG SRC='"+Dn_Dir+Thum_Dir+"/"+Pict[2]+".JPG' ALT=\"#"+Ind[2]+"("+Pict_Total+") - "+Descr[2]+"\" BORDER=1></A>"
                   +"<IMG NAME='But_1Ah' SRC='BUT-1AHA.GIF' WIDTH=13 HEIGHT=13 BORDER=0 ALT='Move one picture ahead'></A>"
      if ((Pict_Total >4)||  // Move two pictures ahead
          (Pict_Total==4)&&(Pict_Ind <3)||
         {Thumb_Two_Ahead="<FONT SIZE=2><FONT COLOR=Purple>Two</FONT> <FONT COLOR=Blue>ahead</FONT> to #"+Numb[3]+"</FONT><BR>"
                         +"<IMG SRC='"+Dn_Dir+Thum_Dir+"/"+Pict[3]+".JPG' ALT=\"#"+Ind[3]+"("+Pict_Total+") - "+Descr[3]+"\" BORDER=1></A>"
                   +"<IMG NAME='But_2Ah' SRC='BUT-2AHA.GIF' WIDTH=13 HEIGHT=13 BORDER=0 ALT='Move two pictures ahead'></A>"

//    Generate image presentation page with proximity navigation (as a table)
//    For debugging      set BORDER=1 to see table structure

//    Vertical centering for a big screen (moved a bit up to offset visual disbalance between bottm bar and top bars)
      if (window.innerHeight>600)
          T=T+"<TR><TD HEIGHT="+(window.innerHeight-500)/2+"></TD></TR>"
//    Vertical centering for regular screen - for Netscape only
//    if (navigator.appName=="Netscape")  // Doesn't distinguish Firefox from Netscape
      if ((navigator.userAgent.indexOf("MSIE"   )==-1)&&
         T=T+"<TR><TD HEIGHT=7></TD></TR>"

      T=T+"<TR><TD ROWSPAN=6 WIDTH=640 HEIGHT=480 ALIGN=Center VALIGN=Center>"
         +"<IMG SRC='"+Dn_Dir+Pict_Dir+"/"+Curr_Pict+".JPG' ALT=\"#"+Pict_Ind+"("+Pict_Total+") - "+Pict_Descr+"\" BORDER=1></A></TD>"
//    Generate thumbnails for proximity navigation
      T=T+"<TD ROWSPAN=6>    </TD>"
         +"<TR><TD COLSPAN=8 WIDTH=120 HEIGHT=116 ALIGN=Center VALIGN=Top>"
         +"<TR><TD COLSPAN=8 WIDTH=120 HEIGHT=116 ALIGN=Center VALIGN=Top>"
      for (i=0;i<7;i++)
          T=T+"<TD WIDTH=17 HEIGHT=17 ALIGN=Center VALIGN=Center>"+Button[i]+"</TD>"
      T=T+"<TD WIDTH=1 HEIGHT=16></TD></TR>"  // Extra pixel for adjustment
         +"<TR><TD COLSPAN=8 WIDTH=120 HEIGHT=116 ALIGN=Center VALIGN=Bottom>"
         +"<TR><TD COLSPAN=8 WIDTH=120 HEIGHT=116 ALIGN=Center VALIGN=Bottom>"

Below there's a table of navigation buttons (designed for me by my daughter Natalia).  Navigation buttons' *.GIF files should be in the same directory with PICTURE.HTM.

File Name Button Button Action Button State
BUT-FSTA FirST picture Active can be selected
BUT-FSTS FirST picture Selected by mouse
BUT-FSTP FirST picture Passive can't be selected
BUT-2BKA 2 pictures BacK Active can be selected
BUT-2BKS 2 pictures BacK Selected by mouse
BUT-2BKP 2 pictures BacK Passive can't be selected
BUT-1BKA 1 picture BacK Active can be selected
BUT-1BKS 1 picture BacK Selected by mouse
BUT-1BKP 1 picture BacK Passive can't be selected
BUT-STPA SToP return to thumbnails Active can be selected
BUT-STPS SToP return to thumbnails Selected by mouse
BUT-1AHA 1 picture AHead Active can be selected
BUT-1AHS 1 picture AHead Selected by mouse
BUT-1AHP 1 picture AHead Passive can't be selected
BUT-2AHA 2 pictures AHead Active can be selected
BUT-2AHS 2 pictures AHead Selected by mouse
BUT-2AHP 1 pictures AHead Passive can't be selected
BUT-LSTA LaST picture Active can be selected
BUT-LSTS LaST picture Selected by mouse
BUT-LSTP LaST picture Passive can't be selected

Note:  Stop button can never be "Passive" it's always possible to return back from picture display to thumbnail list.

A comment concerning the choice of the proximity navigation keys is required as an answer to an inevitable question: why letters and symbols have been chosen for that instead of standard navigation keys?  The answer is that in fact I couldn't withstand a temptation to give standard navigation keys a try (an unsuccessful one), and I had even have saved an image of it.

Old Help Pop-up

There were, however, serious technical difficulties with this approach.  After spending some time in attempts to resolve them I've realized that my application, which was entirely dependent on a browser for its functioning shouldn't try to compete with browser for the keys that browser uses itself as control keys.  Such application won't be stable across different browsers, and even across different versions of the same browser.  With this in mind I've chosen letters and symbols that are still mnemonic, while not interfering in any way with a browser controls.

Picture Help Pop-up

Usage of PICTURE JavaScript is described separately in the Picture Album Support System presentation page.  You'll find there several representative examples of picture albums along with detailed instructions how to use this system for your own picture albums.

View [and save] PICTURE.TXT text
(Use [Back] button or [Alt]+[CL] to return here from text view)
To make text executable rename it to *.JS
and make a global change of "&lt;" into "<" signs.
Copyright © 20012007 by
Go to:  Site entry | Site contents | Site index | Internet | JavaScript | Text top