/*        Fabric Display version 1.3

   This JavaScript reads the XML file "fabrics.xml" containing a
   description of some of the fabrics that Norah has in her shop. It
   allows the user to select fabrics by their designer or kind of
   pattern. It shows the selected fabrics in thumbnails and enlarged
   images.

   Updated 11.04.10 to make the number of rows of thumbnails displayed
   depend upon the size of the browser's client area.

   Updated 21.05.10 to make it possible to show a series of fabrics
   intended to be used together. 

   Copyright Comer's Patchwork Atelier © 2009, 2010. All rights reserved.
*/

/* --------------------- Initialisation ----

 This set of functions run when the program is first loaded. They specify
 the actions to be performed on certain events as well as loading the XML
 file containing the data on the fabrics.
*/  

window.onload   = display_series; // This event is reset in the main HTML !
window.onunload = close_popup;
window.onresize = sizes;

var cloth = new Array(); // the array of all the different fabrics

function initial()
// This function is called when the HTML file is first loaded
{
  var objXML = loadXMLDoc( "Stoffe/fabric.xml" );
  cloth = objXML.getElementsByTagName( "cloth" );
  page_displayed = false;
  available_size();
}

function loadXMLDoc( xmlfilename )
// This function loads the XML file of fabrics data with the given name 
{
  var e = new Error();
  var xmlDoc;
  try
  { // Internet Explorer
    xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.async = false;
    xmlDoc.load(xmlfilename);
    return(xmlDoc);
  }
  catch(e)
  { try
    { // Firefox and perhaps others
      xmlDoc = document.implementation.createDocument("","",null);
      xmlDoc.async = false;
      xmlDoc.load(xmlfilename);
      return(xmlDoc);
    }
    catch(e)
    { try
      { // Code for Google Chrome, ...
        var xmlhttp = new window.XMLHttpRequest();
        xmlhttp.open( "GET", xmlfilename, false );
        xmlhttp.send( null );
        xmlDoc = xmlhttp.responseXML.documentElement ;
        return xmlDoc ;
      }
      catch(e)
        { throw(e.message); }
    }
  }
}

// --------------------- Basic Functions ----
    
var columns;       // the number of displayed columns
var rows;          // the number of displayed rows
var page_size = 0; // number of thumbnails per displayed page

function available_size()
// This function sets the page_size, columns and rows global variables
// depending upon the size of the windows's client area.
{
  with ( ( for_series ) ? document.body : document.documentElement )
  {
    columns = Math.max( Math.floor( ( clientWidth - 130 ) / 167 ), 1 );
    rows = Math.max( Math.floor( clientHeight / 175 ), 1 );
  }
  page_size = columns * rows;
}

function get_value( index, tagName )
// This function returns the value of the property of the fabric with
// the given index (in the cloth array) and with the given tagname.
{
  var elements = cloth[index].getElementsByTagName( tagName );
  if( elements.length == 1 )
    return elements[0].childNodes[0].nodeValue;
  return "";
}

function get_attrValue( index, tagName, attrName )
// Return the value of the named attribute of the property of the given cloth.
{
  var elements = cloth[index].getElementsByTagName( tagName );
  if( elements.length == 1 )
    return elements[0].getAttribute( attrName );
  return "";
}

/* --------------------- The first level of selection ----

 These functions are called when one of the category buttons in the HTML document
 is clicked.
*/

var page_heading = ""; // the name of the selected catagory
var search_tag = "";   // the XML tag used to select thumbnails

var prologue =
   "<p class=\"highlight mid mrgn\">Hier k&ouml;nnen Sie Patchworkstoffe aus meiner "
 + "Stoffsammlung schnell und einfach finden.</p>"
 + "<p class=\"mrgn\">Es ist nur ein kleiner Ausschnitt von mehr als 3000 "
 + "Stoffballen internationaler Designer, die Sie in meinem Laden in Friedrichshafen "
 + "am Bodensee sehen k&ouml;nnen.</p>";

var read_me =
   "<table class=\"abcd\"><tr><td class=\"lft\">"
 + "<div class=\"highlight mrgn\">"
 + "<p>So w&auml;hlen Sie einen Stoff aus:</p><ol>"
 + "<li>Klicken Sie auf eine Kategorie.</li>"
 + "<li>Schr&auml;nken Sie die Auswahl ein.</li>"
 + "<li>Bl&auml;ttern Sie durch die Seiten.</li>"
 + "<li>Benutzen Sie den \"Serien\"-Knopf, um weitere Stoffe in derselben "
 + "Stoffserie zu sehen.</li></ol>"
 + "</div></td>"
 + "<td><img src=\"Stoffe/AA170193.jpg\" alt=\"Stoffballen\" title=\"Meine Laden\"></td>"
 + "</tr></table>";

function category( heading, tag )
// This function is called directly by the user clicking on one of the first sets
// of HTML buttons. These buttons supply the parameters governing how the second
// level selection box is filled.
{
  search_tag = tag;
  fill_box();
  // Write a suitable page heading and clear the thumbnail area
  page_heading = heading;
  document.getElementById( "page_title" ).innerHTML = page_heading;
  document.getElementById( "prologue" ).innerHTML = prologue + read_me;
  document.getElementById( "thumbnails" ).innerHTML = "";
  document.getElementById( "pnum" ).innerHTML = "0 von 0";
  page_displayed = false;
}

function fill_box()
// fillbox() fills the second level selection box with the keywords appropriate
// to the selected category.
{
  // Get the strings displayed in the second level box
  var items = new Array(); // an array of items
  for ( var i = 0 ; i < cloth.length ; i++ ) // for each fabric
  {
    var prop = get_value( i, search_tag );
    if ( prop == "" ) continue;
    // The fabric has the sought property
    var keys = prop.split( "|" );
    for ( var k = 0 ; k < keys.length ; k++ ) // for each key
    {
      // search the strings found so far and add the next key when it is distinct
      var found = false;
      for ( var d = 0 ; d < items.length ; d++ ) // for each item
      {
        if ( keys[ k ] == items[ d ] ) { found = true ; break ; }
      }
      if ( ! found ) items[ items.length ] = keys[ k ];
    }
  }
  // Sort the items alphabetically and append the "all" keyword
  items.sort();
  items[ items.length ] = all;

  // Fill the selection box
  var content = "<p id=\"hilite\">Bitte wählen Sie aus:</p>";
  content += "<select id=\"sel2\" onchange=\"level2(this)\" size=\"6\">";
  for ( var i = 0 ; i < items.length ; i++ )
    content += "<option>" + items[ i ] + "</option>";
  content += "</select>";

  // Write the HTML for the second level selection box and deselect it.
  document.getElementById( "f2" ).innerHTML = content;
  document.forms.f2.sel2.selectedIndex = -1;
  set_high_light( "black" );
}

function set_high_light( colour )
// This function changes the colour of the text introducing the second
// level selection box.
{
  var hilite = document.getElementById( "hilite" );
  hilite.style.color = colour;
}

/* --------------------- The second level of selection ----

 These functions are called as a result of a selection being made in the second
 selection box.
*/

var all = "Alle Stoffe" ; // the "all items" keyword
var chosen = new Array(); // the array of fabric indices chosen by the user
var selected = "";        // the keyword selected in the secondary selection
var for_series = false;   // True if the displayed thumbnails are part of a series. 

var page_displayed;       // true when a page is being or about to be displayed

var advert = "<p>Ich habe &uuml;ber 3000 Stoffballen internationaler Designer "
  + "in meinem Laden und ein gro&szlig;es Sortiment marmorierter Stoffe ab "
  + "&euro;&nbsp;10,95. Viele weitere Stoffe sind als \"Fat-Quarters\" erh&auml;ltlich.</p>"
  + "<p class=\"mid\">Sie k&ouml;nnen Stoffe per <a href=\"index.htm#contact\">"
  + "Telefon</a> oder per <a href=\"mailto:info@patchwork-fn.de\">eMail</a>"
  + " bestellen.</p>";

var disclaimer = "<p class=\"remarks\">Alle Preise inkl. MwSt. Preis&auml;nderungen"
  + " und Irrt&uuml;mer vorbehalten.<br />Comer\'s Patchwork Atelier, H&uuml;nistr. 3,"
  + " 88046 Friedrichshafen, Deutschland. Tel: (49) 7541 31335</p>";

var page_layout = new Object(); // This object governs the format of the thumbnails

function level2( secondary )
// This function is called when the user makes a selection from the second level box.
// It fills the "chosen" array with the indices of the selected fabrics and sets other
// elements in the displayed page. 
{
  page_layout.hyperlink     = true; // show the hyperlink to the enlarged images
  page_layout.series_button = true; // show the series button
  page_layout.show_designer = true; // show the designer's name

  // Get the name of the item selected by the user
  selected = secondary.options[ secondary.selectedIndex ].childNodes[ 0 ].nodeValue;

  // Save the indices of the chosen fabrics
  chosen.length = 0;
  for ( var index = 0; index < cloth.length ; index++ )
  {
    if (( selected == all ) || 
        ( get_value( index, search_tag ).indexOf( selected ) != -1 ))
        // N.B. This code assumes that no key is a substring of another !
    { chosen[ chosen.length ] = index; }
  }

  document.getElementById( "page_title" ).innerHTML = 
    page_heading + ": " + selected;
  document.getElementById( "prologue" ).innerHTML = "";

  available_size();
  page_displayed = true;
  page_control("first");
}

function show_series()
// This function performs a similar role to level2() but for the "Serie" sub-window.
{
  page_layout.hyperlink     = true;  // show the hyperlink to the enlarged images
  page_layout.series_button = false; // omit the series button
  page_layout.show_designer = false; // omit the designer's name

  // Save the indices of the chosen fabrics in the chosen array.
  chosen.length = 0 ;
  for ( var index = 0; index < cloth.length ; index++ )
  {
    if ( get_value( index, "ser" ) == series_name )
      chosen[ chosen.length ] = index ;
  }
  var page_title = "Stoff Serie : " + get_value( chosen[ 0 ], "des" );
  document.getElementById( "page_title" ).innerHTML = page_title;
  document.title = page_title;

  available_size();
  page_displayed = true ;
  page_control("first") ;
}


function display_page()
// display_page() fills the HTML window with the thumbnail pictures of the various
// fabrics and displays the page number.
{
  if ( ! page_displayed ) return ;
  var count = 0 ;
  var content = "<table id=\"table\" border=\"0\" class=\"pics\">" ;
  for ( var i = 0 ; i < page_size ; i++ )
  {
    var next = displayed_page * page_size + i ;
    if ( next >= chosen.length ) break ;
    if ( count % columns == 0 ) content += "<tr>" ;
    content += make_td( chosen[ next ], page_layout ) ;
    if ( count % columns == columns - 1 ) content += "</tr>" ;
    count++;
  }
  if ( count % columns != columns - 1 ) content += "</tr>" ;
  content += "</table>" ;
  content += advert + disclaimer ;

  // Write the new contents to the HTML document with thumbnail details
  document.getElementById( "thumbnails" ).innerHTML = content ;
  document.getElementById( "pnum" ).innerHTML =
     ( displayed_page + 1 ) + " von " + ( last_page() + 1 );

  if ( ! for_series )
  {
    var hilite = document.getElementById( "hilite" ) ;
    hilite.innerHTML = "Auswahl" ;
    set_high_light( "#FFFF80" );
  }
}

function make_td( index, layout )
// make_td() creates and returns the <td> element corresponding to the cloth
// with the given index number. The layout of the thumbnails on the page is
// governed by the various fields of the layout object.
{
  var td = "<td valign=\"top\">" ;

  var code = get_value( index, "code" ); // The fabric's reference number

  if( layout.hyperlink )
    td += "<a href=\"javascript:popup(" + index + ")\"" +
          " title=\"Klicken Sie hier, um das Bild zu vergr&ouml;&szlig;ern\" />" ;

  td += "<img src=\"Stoffe/" + get_value( index, "dir" ) +
            "/S/" + code + ".jpg\" />" ;

  if( layout.hyperlink ) td += "</a>" ;

  td += "<br />&euro; " + get_value( index, "price" ) ;
  switch( get_attrValue( index, "price", "per" ) )
  {
    case "m"   : td += " pro Meter" ; break ;
    case "st"  : td += " pro Streifen" ; break;
    case "pan" : td += " pro Paneel" ; break;
    case "50"  : td += " pro 50 cm" ;
  }

  // Insert a button if the fabric is part of a series
  if (( get_value( index, "ser" ) != "" ) && ( layout.series_button ))
  {
     td += "<form id=\"Mehr\" method=\"post\" action=\"\">" +
           code + " " +
           "<button class=\"ser\" name=\"tuv\" type=\"button\" " +
           "title=\"Alle Stoffe in die Serie zeigen\" " +
           "onclick=\"series(\'" + index +
           "\')\">Serie</button></form>" ;
  }
  else
    td += "<br />" + code + "<br />" ;

  if ( layout.show_designer )
  {
    var designer = get_value( index, "des" ) ;
    if ( designer != "" ) td += designer + "<br />";
  }

  var comment = get_value( index, "com" ) ;
  if ( comment != "" ) td += comment ;

  td += "</td>" ;
  return td ;
}

function sizes()
// sizes() is called when the pop up window is resized. It recomputes the
// number of rows and columns of thumbnails that can be displayed in the available
// space. It redisplays the set of thumbnails if necessary.
{
  if ( page_displayed )
  {
    var index_of_first = displayed_page * page_size + 1 ;
    available_size() ;
    displayed_page = Math.floor(( index_of_first - 1 ) / page_size ) ;
    display_page() ;
  }
}

/* --------------------- Thumbnail page selection ----

 These functions are called by the buttons controlling the page of thumbnails
 the user wishes to see. The indices of the chosen fabrics are held in the
 chosen array.
*/

var displayed_page = 0;   // the number of the last page displayed

function last_page()
// last_page() returns the number of the last page.
{
   return Math.floor( ( chosen.length - 1 ) / page_size ) ;
}

function page_control( identifier )
// This page is called when a page button is clicked. It sets the parameter.
{
  switch( identifier )
  {
    case "first" : displayed_page = 0; break;
    case "prior" : if ( displayed_page > 0 ) displayed_page--; break;
    case "next"  : if ( displayed_page < last_page() ) displayed_page++; break;
    case "last"  : displayed_page = last_page(); break;
  }
  display_page();
}

/* --------------------- Display an enlarged image ----

 The user may click on one of the displayed thumbnails to enlarge it in a
 separate pop up window.
*/

var base_height = 375;
var popTop = screen.height; // The top of the next pop-up window

var popup_width = 500 ;   // the initial width of a pop-up page
var popups = new Array(); // the array of pop up windows

function popup( index )
// popup() creates and fills the pop-up window for the given fabric.
// The parameter value is set by make_td().
{
  var code = get_value( index, "code" ) ;
  var folder = get_value( index, "dir" );
  var popup_height = popup_width / 4 * 3 ;
  var pleft = screen.width - popup_width - 10 ;
  // Make sure that the pop-up doesn't cover the previous one completely.
  ( popTop >= screen.height - base_height - 130 ) ? popTop = 20 : popTop += 30;
  third = "top=" + popTop + ",left=" + pleft + ",width=" + popup_width
            + ",height=" + popup_height + ",resizable,status=\"no\"" ;
  var popup = window.open( "", "", third );
  with( popup.document )
  {
    open() ;
    write( "<html><head>" ) ;
    write( "<title>Fabric " + code + "</title>" ) ;
    write( "</head><body style=\"margin: 0px\">" ) ;

    // Cope with some images files having a different naming standard
    if ( code.charAt( code.length - 1 ) == "S" )
      code = code.substr( 0, 8 ) + "L" ;
    write( "<img height=\"100%\" src=\"Stoffe/" + 
            folder + "/L/" + code + ".jpg\""  +
            " title=\"Sie k&ouml;nnen die Gr&ouml;&szlig;e des Bildes ver&auml;ndern\" />" ) ;

    write( "</body></html>" ) ;
    close() ;
  }
  save_popup( popup ) ;
}

function save_popup( popup )
{
  // Save the reference to the pop up window so that it can be closed later
  var saved = false ;
  for ( var k = 0 ; k < popups.length ; k++ )
  {
    if ( popups[ k ].closed )
      { popups[ k ] = popup ; saved = true ; break ; }
  }
  if ( ! saved ) popups[ popups.length ] = popup ;
}


function close_popup()
// This function is called when the opener's HTML window is closed via the
// "onunload" event. It closes all the related pop-up windows that are still open
// including the one used for printing.
{
  for ( var i = 0 ; i < popups.length ; i++ ) 
  {
    if ( ! popups[ i ].closed ) popups[ i ].close() ;
  }
  if (( print_page != null ) && ( ! print_page.closed )) print_page.close() ;
}

/* --------------------- The pop up print window ----

 The user may print the complete set of thumbnails she has selected using the
 "print" button.
*/

var print_page = null;    // the pop up window associated with "print"

var print_layout = new Object();
  // This object controls the layout of a page of thumbnails in an A4 layout
  print_layout.hyperlink     = false; // no hyperlinks to enlarged images
  print_layout.series_button = false; // no series bttin
  print_layout.show_designer = true;  // show the designer's name if known

function prepare_print_page()
// prepare_print_page() prepares a pop up page suitable for printing on
// A4 paper, i.e. with rows of four columns.
{
  if (( print_page != null ) && ( ! print_page.closed )) print_page.close() ;
  if ( ! page_displayed ) return ;
  print_page = window.open( "", "", "top=20,left=40,width=710,height=500,scrollbars" );

  with( print_page.document )
  {
    open() ;
    write( "<html><head>" ) ;
    write( "<title>Comer\'s Patchwork Atelier: " + page_heading + " -- "
           + selected + "</title>" ) ;
    write( "<link rel=\"stylesheet\" href=\"npa2.css\" type=\"text/css\">" );
    write( "</head><body><form>" ) ;
    write( "<button name=\"pr\" type=\"button\" onclick=\"window.print()\">" +
           "Drucken</button>" ) ;
    write( "<button name=\"cl\" type=\"button\" onclick=\"window.close()\">" +
           "Schlie&szlig;en</button>" ) ;
    write( "</form><div>" ) ;
    write( "<h1>Comer\'s Patchwork Atelier: " + page_heading + " -- "
           + selected + "</h1>" ) ;
    write( format_print_page() + "</div></body></html>" ) ;
    close() ;
  }
}

function format_print_page()
// format_print_page() prepares the table of thumbnails for inclusion in
// this page.
{
  var count = 0 ;
  var content = "<table id=\"table\" border=\"0\" class=\"pics\">" ;
  for ( var i = 0 ; i < chosen.length ; i++ )
  {
    if ( count % 4 == 0 ) content += "<tr>" ;
    content += make_td( chosen[ i ], print_layout ) ;
    if ( count % 4 == 3 ) content += "</tr>" ;
    count++;
  }
  if ( count % 4 != 3 ) content += "</tr>" ;
  content += "</table>" ;
  content += advert + disclaimer ;
  return content;
}

// --------------------- Load the series window ----

function display_series()
// This function is called by the "onload" event in the sub-window displaying the
// thumbnails belonging to a series.
{
  // Load the XML database, pick up the name of the series and display it
  for_series = true;
  initial();
  show_series();
}

function series( index )
// This function is invoked when the user clicks on the Serie button associated
// with a particular thumbnail. The function passes the name of the series to be
// displayed by writing it into the HTML dynamically. It would be better to pass
// the name via a cookie but I cannot get Chrome to support cookies. And if I
// have difficulties, I cannot expect my customers to be able or willing to do it either.
{
 var name = get_value( index, "ser" );
 var text = "<html><head>\n<title>Serie</title>\n"
 + "<meta http-equiv=\"Content-type\" content=\"text/html; charset=ISO-8859-1\">\n"
 + "<link rel=\"stylesheet\" href=\"npa3.css\" type=\"text/css\">\n"
 + "<script type=\"text/javascript\" src=\"stoffe/fabric.js\"></script>\n"
 + "<script type=\"text/javascript\">series_name=\"" + name + "\";</script>\n"
 + "</head>\n<body>\n<div id=\"index\" align=\"right\">\n"
 + "<p>Comer\'s<br>Patchwork<br>Atelier</p>\n"
 + "<form id=\"f9\" method=\"post\" action=\"\">\n"
 + "<fieldset style=\"text-align: center\">\n"
 + "<legend title=\"Schritt 3\">Seiten</legend>\n"
 + "<span id=\"pnum\">0 von 0</span><br>\n"
 + "<button name=\"b1\" type=\"button\" onclick=\"page_control(\'first\')\" "
 + "title=\"Erste Seite\">&lt;&lt;</button>\n"
 + "<button name=\"b2\" type=\"button\" onclick=\"page_control(\'prior\')\" "
 + "title=\"Vorherige Seite\">&lt;</button>\n"
 + "<button name=\"b3\" type=\"button\" onclick=\"page_control(\'next\')\" "
 + "title=\"N&auml;chste Seite\">&gt;</button>\n"
 + "<button name=\"b4\" type=\"button\" onclick=\"page_control(\'last\')\" "
 + "title=\"Letzte Seite\">&gt;&gt;</button><br>\n"
 + "<button name=\"pr\" type=\"button\" onclick=\"prepare_print_page()\" "
 + "title=\"Drucken in A4 Format\">Drucken ...</button>\n</fieldset></form>\n"
 + "<div align=\"center\">\n<form method=\"post\" action=\"\">\n"
 + "<button name=\"cl\" type=\"button\" onclick=\"window.close()\">"
 + "Serie<br>schlie&szlig;en\n</button>\n"
 + "</form></div></div>\n"
 + "<div id=\"head\">\n<h1 id=\"page_title\">Error</h1>\n<table><tr>\n"
 + "<td><a href=\"index.htm\">Home</a></td>\n"
 + "<td id=\"picked\"><a href=\"Stoffe.htm\">Stoffe</a></td>\n"
 + "<td><a href=\"Zubehoer.htm\">Zubehör</a></td>\n"
 + "<td><a href=\"Veranstaltung.htm\">Veranstaltungen</a></td>\n"
 + "<td><a href=\"Map.htm\">Anfahrt</a></td>\n</tr></table></div>\n"
 + "<div id=\"content\">\n<div id=\"thumbnails\"></div></div>\n"
 + "</body></html>";

 var group_page = window.open( "", "", "toolbar=yes,resizable=yes,scrollbars=yes" );
 with( group_page.document )
 {
   open();
   write ( text );
   close();
 }
 save_popup( group_page );
}

// --------------------- End of Code ----
