/*        Patterns Display Version 1.2.1

   This JavaScript reads the XML file "patterns.xml" containing a
   description of some of the patterns that Norah has in her shop. It
   allows the user to select patterns by their designer or by other
   crtieria. It shows the selected pattern in thumbnails and enlarged
   images.

   Update 11.04.10 to make the number of displayed rows of thumbnails
   depend upon the size of the browser's client area.

   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 about the patterns.
  * initial() is called when the HTML document is first loaded
  * loadXMLDoc(file_name) actually loads the XML file of pattern data 
*/  

window.onload   = initial;      // called when the HTML document is loaded
window.onunload = close_popup ; // called when the HTML document is unloaded
window.onresize = sizes;        // called when the browser window is resized

var cloth = new Array();        // the array of different patterns

function initial()
{
  var objXML = loadXMLDoc( "Anleitung/patterns.xml" ) ;
  cloth = objXML.getElementsByTagName( "anleitung" ) ;
  page_displayed = false;
  available_size();
}

function loadXMLDoc( xmlfilename )
{
  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, Mozilla, Opera, 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 ----

 These functions are used in several places
  * available_size() sets the page_size, columns and rows global variables
    depending upon the size of the browser's inner window
  * "get_value" returns the value of the property of the pattern with the
    given index (in the cloth array) and the given tagname.
  * "get_atrrValue" returns the named attribute of the property of the
    given pattern.
*/
    
var columns ;      // the number of displayed columns
var rows ;         // the number of rows displayed per page
var page_size = 0; // number of thumbnails per displayed page

function available_size()
{
  var width = document.documentElement.clientWidth ;
  var height = document.documentElement.clientHeight ;
  columns = Math.max( Math.floor( ( width - 130 ) / 167 ), 1 ) ;
  rows = Math.max( Math.floor( height / 230 ), 1 ) ;
  page_size = columns * rows ;  
}

function get_value( index, tagName )
{
  var elements = cloth[index].getElementsByTagName( tagName ) ;
  if( elements.length == 1 )
    return elements[0].childNodes[0].nodeValue ;
  return "" ;
}

function get_attrValue( index, tagName, attrName )
{
  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.
  * category( heading, tag ) specifies the selected category (heading) and the name
    of the tag (tag) whose values fill the second level selection box.
  * fillbox() fills the second level selection box with the keywords appropriate to
    the selected category.
  * set_high_light(colour) changes the colour of the text introducing the second
    level selection box.
*/

var page_heading = "";    // the name of the selected catagory
var search_tag = "";      // the XML tag used to select thumbnails

var p1 = "<p class=\"highlight mid mrgn\">Eine guter Patchworkladen hat viele "
 + "Anleitungen zum inspirieren. Meiner auch!</p>";

var p2 = "<table class=\"abcd\"><tr><td class=\"lft\">" ;

var p3 = "<p class=\"highlight mrgn\">Hier k&ouml;nnen Sie Anleitungen aus meiner "
 + "Sammlung schnell und einfach finden.</p>" ;

var p4 = "<div class=\"highlight mrgn\">"
 + "<p>So w&auml;hlen Sie eine Anleitung 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></ol></div>" ;

var p5 = "</td><td><img src=\"Anleitung/P1210001.jpg\"></td></tr></table>" ;

function category( heading, tag )
{
  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 = p1 + p2 + p3 + p4 + p5 ;
  document.getElementById( "thumbnails" ).innerHTML = "" ;
  document.getElementById( "pnum" ).innerHTML = "0 von 0" ;
  page_displayed = false ;
}

function fill_box()
{
  // Get the items from the XML document
  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 ;
    var keys = prop.split( "|" ) ;
    for ( var k = 0 ; k < keys.length ; k++ ) // for each key
    {
      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>" ;
  // content += "</fieldset>" ;

  // 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 )
{
  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.
  * level2(secondary) is called from the HTML document. It determines which
    patterns the user wishes to see and displays the first page of them.
  * display_page() fills the browser's inner window with the thumbnail pictures
    of the various patternss and displays the page number.
  * make_td(index,enlarge) creates and returns the <td> element corresponding
    to the pattern with the given index number. If enlarge is true, the image is
    enclosed in a hyperlink to create an enlarged image.
  * sizes() is called when the pop up window is resized. It recomputes the
    number of columns of thumbnails that can be displayed in the available
    space. It redisplays the set of thumbnails if necessary.
*/

var all = "Alle" ;        // the "all items" keyword
var chosen = new Array(); // the array of fabrics selected by the user
var selected = "" ;       // the keyword selected in the secondary selection

var page_displayed;       // true when a page is being displayed

var advert = "<p>Eine umfangreiche Auswahl an Stoffen finden Sie in meinem "
  + "Laden. Viele weitere Stoffe sind als \"Fat-Quarters\" erhältlich.<p>"
  + "<p class=\"mid\">Sie können Anleitungen 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änderungen"
  + " und Irrtümer vorbehalten.<br />Comer\'s Patchwork Atelier, Hünistr. 3,"
  + " 88046 Friedrichshafen, Deutschland. Tel: (49) 7541 31335</p>" ;

function level2( secondary )
{
  // Get the name of the item selected by the user
  selected = secondary.options[ secondary.selectedIndex ].childNodes[ 0 ].nodeValue ;

  // Save the indices of the chosen patterns
  chosen.length = 0 ;
  for ( var index = 0; index < cloth.length ; index++ )
  {
    if( selected == all )
    { // select all entries
      chosen[ chosen.length ] = index ;
      continue ;
    }
    var keys = get_value( index, search_tag ) ; // set of keys available
    var startpos = keys.indexOf( selected ) ;
    if ( startpos == -1 )
      continue ; // required key not in the set
    var beyond = startpos + selected.length ; // first char beyond match
    if(( beyond >= keys.length ) || ( keys[ beyond ] == "|" ))
      // required key is not a subset of another one
      chosen[ chosen.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 ;
  first_btn() ;
}

function display_page()
{
  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 ], true ) ;
    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 );

  document.getElementById( "hilite" ).innerHTML = "Auswahl" ;

  set_high_light( "#FFFF80" );
}

function make_td( index, enlarge )
{
  var td = "<td valign=\"top\">" ;

  var image = get_value( index, "image" );

  if( enlarge )
    td += "<a href=\"javascript:popup(" + index + ")\"" +
          " title=\"Klicken Sie hier, um das Bild zu vergr&ouml;&szlig;ern\" />" ;

  td += "<img src=\"Anleitung/" + get_value( index, "dir" ) +
            "/S/" + image + ".jpg\" />" ;

  if( enlarge ) td += "</a>" ;

  td += "<br />&euro; " + get_value( index, "price" ) ;
  var kind = get_attrValue( index, "price", "per" ) ;
  if ( kind == "m" ) td += " pro Meter" ;
  else if ( kind == "st" ) td += " pro Streifen" ;
       else if ( kind == "pan" ) td += " pro Paneel" ;
            else if ( kind == "50" ) td += " pro 50 cm" ;

  var name = get_value( index, "name" );
  if( name != "" ) td += "<br><b>" + name + "</b>" ; 

  var ref = get_value( index, "ref" ) ;
  if (  ref == "" ) ref = image ;
  td += "<br />" + ref ;

  var designer = get_value( index, "des" ) ;
  if ( designer != "" )
     td += "<br />" + designer ;

  var comment = get_value( index, "com" ) ;
  if ( comment != "" )
     td += "<br />" + comment ;

  td += "</td>" ;

  return td ;
}

function sizes()
{
  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 patterns are held in the
 chosen array.
  * last_page() returns the number of the last page.
  * first_btn() displays the first page of the chosen patterns
  * previous_btn() displays the page before the one being displayed currently
  * next_btn() displays the page after the one being displayed currently
  * last_btn() displays the last page of the chosen fabrics
*/

var displayed_page = 0;   // the number of the last page displayed

function last_page()
{
   return Math.floor( ( chosen.length - 1 ) / page_size ) ;
}

function first_btn()
{
  displayed_page = 0 ;
  display_page();
}

function previous_btn()
{
  if ( displayed_page > 0 ) displayed_page-- ;
  display_page();
}

function next_btn()
{
  if ( displayed_page < last_page() ) displayed_page++ ;
  display_page();
}

function last_btn()
{
  displayed_page = last_page() ;
  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.
  * popup(index) creates and fills the pop up window for the given pattern.
  * close_popup() is called when the internet page is unloaded. It closes all
    pop up windows that are still open including the one used for printing.
*/

var base_height = 500 ;      // the default height of a pop up window
var popups = new Array();    // the array of pop up windows
var popTop = screen.height ; // The top of the next pop up window.

function popup( index )
{
  var image = get_value( index, "image" ) ;
  var folder = get_value( index, "dir" );
  // Scale the width of the pop-up to fit the image exactly given its base height
  var iwidth = get_attrValue( index, "image", "w" ) ;
  var iheight = get_attrValue( index, "image", "h" ) ;
  if ( iwidth == null || iheight == null )
    { iwidth = base_height * 0.75 ; iheight = base_height ; }
  var scaled_width = iwidth * ( base_height / iheight ) ;
  // Offset the top of the pop up.
  ( popTop >= screen.height - base_height - 130 ) ? popTop = 20 : popTop += 30 ;

  // Create and open the new pop up window
  var pleft = screen.width - scaled_width - 10 ;
  third = "top=" + popTop + ",left=" + pleft + ",width=" + scaled_width +
          ",height=" + base_height + ",resizable,status=no" ;
  var popup = window.open( "", "", third );

  with( popup.document )
  {
    open() ;
    write( "<html><head>" ) ;
    write( "<title>" + get_value( index, "name" ) + "</title>" ) ;
    write( "</head><body style=\"margin: 0px\">" ) ;
    // Cope with some images files having a different naming standard
    if ( image.charAt( image.length - 1 ) == "S" )
      image = image.substr( 0, 8 ) + "L" ;
    write( "<img height=\"100%\" src=\"Anleitung/" + 
            folder + "/L/" + image + ".jpg\""  +
            " title=\"Sie k&ouml;nnen die Gr&ouml;&szlig;e des Bildes ver&auml;ndern\" />" ) ;
    write( "</body></html>" ) ;
    close() ;
  }

  // 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()
{
  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.
  * prepare_print_page() prepares a pop up page suitable for printing on
    A4 paper, i.e. with rows of four columns.
  * format_print_page() prepares the table of thumbnails for inclusion in
    this page.
*/

var print_page = null;    // the pop up window associated with "print"

function prepare_print_page()
{
  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()
{
  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 ], false ) ;
    if ( count % 4 == 3 ) content += "</tr>" ;
    count++;
  }
  if ( count % 4 != 3 ) content += "</tr>" ;
  content += "</table>" ;
  content += advert + disclaimer ;
  return content;
}

// --------------------- End of Code ----
