/* Copyright (c) 2007, Bureau van Dijk Electronic Publishing. All rights reserved. */


//
// SBO namespace
//

var SBO = new function()
{
  //
  // method SBO.Extend
  //

  this.Extend = function(sub, base) 
  {
     function inst() {}
     inst.prototype = base.prototype;
     sub.prototype = new inst();
     sub.prototype.constructor = sub;
  }

}


//
// SBO.Config namespace
//


SBO.Config = new function()
{
  //
  // SBO.Config properties
  //
  
  this.Host = null;
  this.Url = null;
  
  this.XmlApi = null;


  //
  // method SBO.Config.Init
  //
  
  this.Init = function()
  {
    var sbo = document.getElementById("SBO");
    var url = sbo ? sbo.src : "";
    
    if(url.indexOf("http") != 0)
    {
      this.Host = "http://safari5.bvdep.com";
      this.Url = this.Host + "/SBO/";
    }
    else
    {
      var hostIdx = url.indexOf("//") + 2;
        
      var pathIdx = url.indexOf("/", hostIdx);
      var fullPathIdx = url.lastIndexOf("/");
      
      this.Host = url.slice(0, pathIdx);
      this.Url = url.slice(0, fullPathIdx);
    }
      
    this.XmlApi = this.Host + "/xmlapi?Date=" + new Date().valueOf() + "&output=js&displaygrbooks=1&htmldescription=1&authors=1";
    
    var ua = navigator.userAgent;
    
    this.IsIE6 = ua && ua.indexOf("MSIE 6.0") > 0;
  }
  
  this.Init();
}



//
// namespace SBO.StringUtils
//

SBO.StringUtils = new function()
{
  //
  // method SBO.StringUtils.Replace
  //

  this.Replace = function(s)
  {
    for(var i = 1, n = arguments.length; i < n; i++)
      s = s.replace(new RegExp("\\{" + (i - 1) + "\\}"), arguments[i]);

    return s;
  }
}


//
// namespace SBO.DomUtils
//

SBO.DomUtils = new function()
{
  //
  // SBO.DomUtils properties
  //
  
  this.HtmlHead = null;


  //
  // method SBO.DomUtils.Init
  //

  this.Init = function()
  {
    var htmlHead = document.getElementsByTagName("head");
    if(!htmlHead)
    {
      alert("this document has lost its head!");
      return;
    }
     
    this.HtmlHead = htmlHead[0];

    var htmlLink = document.createElement("link"); 

    htmlLink.rel = "stylesheet";
    htmlLink.type = "text/css";
    htmlLink.href = SBO.Config.Url + "/SBO.css";   
      
    this.HtmlHead.appendChild(htmlLink);
  }
 
 
  //
  // method SBO.DomUtils.GetXY
  //

  this.GetXY = function(obj)
  {
    var x = 0;
    var y = 0;
    
    for(var o = obj; o; o = o.offsetParent)
    {
        x += o.offsetLeft;
        y += o.offsetTop;
    } 

    for(var o = obj; o; o = o.parentNode)
    {
        x -= o.scrollLeft ? o.scrollLeft : 0;
        y -= o.scrollTop ? o.scrollTop : 0;
    } 

    return [x, y];
  }
  

  //
  // method SBO.DomUtils.GetX
  //
  
  this.GetX = function(obj)
  {
    return this.GetXY(obj)[0];
  }
  

  //
  // method SBO.DomUtils.GetY
  //

  this.GetY = function(obj)
  {
    return this.GetXY(obj)[1];
  }
  
  
  //
  // method SBO.DomUtils.SetXY
  //
  
  this.SetXY = function(obj, x, y)
  {
    obj.style.left = x + "px";
    obj.style.top = y + "px";
  }
  
  
  this.Init();
}


//
// namespace SBO.Ajax
//

SBO.Ajax = new function()
{
  //
  // method SBO.Ajax.ShowSpinningIcon
  //
  
  this.ShowSpinningIcon = function(obj)
  {
    var img = document.getElementById("SBOAjaxSpinningIcon");
    
    if(!img)
    {
      img = document.createElement("img");
      img.style.display = "none";
      img.style.position = "absolute";
      img.style.zIndex = 10;
      img.src = SBO.Config.Url + "/loading.gif";
      img.id = "SBOAjaxSpinningIcon";
     
      document.body.appendChild(img); 
    }
    
    SBO.DomUtils.SetXY(img, SBO.DomUtils.GetX(obj) + obj.offsetWidth / 2, SBO.DomUtils.GetY(obj) + obj.offsetHeight / 2);
    
    img.style.display = "";
  }
  

  //
  // method SBO.Ajax.HideSpinningIcon
  //
  
  this.HideSpinningIcon = function()
  {
    var img = document.getElementById("SBOAjaxSpinningIcon");
    
    if(img)
      img.style.display = "none";
  }
  
  
  //
  // method SBO.Ajax.ConvertObjectToArray
  //
  
  this.ConvertObjectToArray = function(obj1, obj2)
  {
    var array = obj1[obj2];
    
    if(array && !array.length)
    {
      var temp = new Array();
      temp[0] = array;
      obj1[obj2] = temp;
    }
  
  }
  
  //
  // method SBO.Ajax.Call
  //
  
  this.Call = function(obj, url, callback)
  {
    this.ShowSpinningIcon(obj);
    
    this.CallBack = callback;
   
    var htmlScript = document.getElementById("SBOAjaxCall");
    if(htmlScript)
        SBO.DomUtils.HtmlHead.removeChild(htmlScript);

    htmlScript = document.createElement("script"); 
    htmlScript.id = "SBOAjaxCall";
    htmlScript.charset = "utf-8";
    htmlScript.src = url;
    
    SBO.DomUtils.HtmlHead.appendChild(htmlScript);
  }
  
  
  //
  // method SBO.Ajax.ObjectReady
  //
  
  this.ObjectReady = function(obj)
  {
    eval(this.CallBack + "(obj)");
    
    this.HideSpinningIcon();
  }


  //
  // namespace SBO.Ajax.PanelUtils
  //
  
  this.PanelUtils = new function() 
  {
    //
    // method SBO.Ajax.PanelUtils.BuildInnerPanelHtml
    //
    
    this.BuildInnerPanelHtml = function(html, id, style, i, className)
    {
      if(SBO.Config.IsIE6)
        return '' + 
          '<div ' +  (id ? ' id="' + id + '"' : '') + (style ? ' style="' + style + '"' : '') + (i == 1 ? (' class="SBOInnerPanel' + (className ? ' ' + className : '')) + '"' : '') + '>' + 
	          '<div ' +  (id ? ' id="' + id + 'Content' + '"' : '') + ' class="SBOInnerPanelContent SBOInnerPanelContent' + i + '">' + 
	            html +
	          '</div>' +
          '</div>';
      
      return '' + 
        '<div ' +  (id ? ' id="' + id + '"' : '') + (style ? ' style="' + style + '"' : '') + (i == 1 ? (' class="SBOInnerPanel' + (className ? ' ' + className : '')) + '"' : '') + '>' + 
          '<div class="SBOInnerPanelTopLeft SBOInnerPanelImage' + i + '"></div><div class="SBOInnerPanelTopRight SBOInnerPanelImage' + i + '"></div>' + 
	        '<div ' +  (id ? ' id="' + id + 'Content' + '"' : '') + ' class="SBOInnerPanelContent SBOInnerPanelContent' + i + '">' + 
	          html +
	        '</div>' +
          '<div class="SBOInnerPanelBottomLeft SBOInnerPanelImage' + i +'"></div><div class="SBOInnerPanelBottomRight SBOInnerPanelImage' + i +'"></div>' + 
        '</div>';
    }


    this.BuildTableHtml = function(col1, col2)
    {
      return '' + 
        '<table width="100%"cellspacing="0" cellpadding="0">' + 
          '<tr>' + 
            '<td width="100%">' + 
              col1 + 
            '</td>' + 
            '<td nowrap="1">' + 
              col2 + 
            '</td>' + 
          '</tr>' + 
        '</table>';
    }
  }
  

  
  //
  // namespace SBO.Ajax.Panel
  //
  
  this.Panel = new function() 
  {
  }
  
  
  
}  
    

//
// class SBO.Ajax.Panel
//

SBO.Ajax.Panel = function(containerId, movable, resizable)
{
  this.ContainerId = containerId;
  this.Movable = movable;
  this.Resizable = resizable;
}


//
// method SBO.Ajax.Panel.Init
//

SBO.Ajax.Panel.prototype.Init = function()
{
  var container = document.getElementById(this.ContainerId);
  
  if(container)
    this.Container = container;
  else
  {
    this.Container = document.createElement("div");
    this.Container.id = this.ContainerId;
  }
  
  this.Container.style.display = "none";
  this.Container.className = "SBOFont SBOPanel";
  
  if(this.Movable)
    this.Container.onmousedown = PanelOnMouseDown;

  if(!container)      
    document.body.appendChild(this.Container);
  

  this.Container.SBOAjaxPanel = this;
  
  this.PanelTopHtml = '' + 
    '<div class="SBOPanelTop' + (this.Movable ? ' SBOMovable' : '') + '">' +
       SBO.Ajax.PanelUtils.BuildTableHtml
       (
          (this.Movable ? '<img class="SBOMoveIcon" border="0" src="' + SBO.Config.Url + '/grab.gif"></img>' : '&nbsp;'),
          
          '<a title="Close" href="#" onclick="document.getElementById(\'' + this.ContainerId + '\').SBOAjaxPanel.Hide(); return false;">' + 
            '<img border="0" src="' + SBO.Config.Url + '/close.gif"></img>' + 
          '</a>'
       ) + 
    '</div>';
    
  if(!this.Movable && !this.Resizable)
    this.PanelBottomHtml = "";
  else
    this.PanelBottomHtml = '' + 
      '<div class="SBOPanelBottom' + (this.Movable ? ' SBOMovable' : '') + '">' +
         SBO.Ajax.PanelUtils.BuildTableHtml
         (
            (this.Movable ? '<img class="SBOMoveIcon" border="0" src="' + SBO.Config.Url + '/grab.gif"></img>' : '&nbsp;'),
            (this.Resizable ? '&nbsp;' : '&nbsp;')
         ) + 
      '</div>';
    
  
}


//
// method SBO.Ajax.Panel.SetXY
//

SBO.Ajax.Panel.prototype.SetXY = function(x, y)
{
  SBO.DomUtils.SetXY(this.Container, x, y);
    
  this.X = x;
  this.Y = y;
}

//
// method SBO.Ajax.Panel.BeforeShow
//

SBO.Ajax.Panel.prototype.BeforeShow = function()
{
}

//
// method SBO.Ajax.Panel.AfterShow
//

SBO.Ajax.Panel.prototype.AfterShow = function()
{
}


//
// method SBO.Ajax.Panel.Show
//

SBO.Ajax.Panel.prototype.Show = function(html, x, y)
{
  this.Shown = true;
  
  this.SetXY(x, y);
  
  this.Container.innerHTML = this.PanelTopHtml + SBO.Ajax.PanelUtils.BuildInnerPanelHtml(html, "", "", 1, this.Resizable ? "SBOResizable" : "") + this.PanelBottomHtml;
  
  this.BeforeShow();
  
  this.Container.style.display = "";
  
  this.AfterShow();
}


//
// method SBO.Ajax.Panel.Hide
//

SBO.Ajax.Panel.prototype.Hide = function()
{
  delete this.Shown;
  
  this.Container.style.display = "none";
}


//
// method SBO.Ajax.Panel.Load
//

SBO.Ajax.Panel.prototype.Load = function(query, callback)
{
  SBO.Ajax.Call(this.Container, SBO.Config.XmlApi + "&"  + query, callback);
}


// Panel OnMouseDown handler
// TODO: move somewhere else

var _Panel = null;

function PanelOnMouseDown(e) 
{
  if(_Panel != null)
    return;
    
  e = e || event;
    
  var obj = e.target || e.srcElement;

  while(obj && (!obj.className || obj.className.indexOf("SBOMovable") == -1))
    obj = obj.parentNode;

  if(obj && obj.className && obj.className.indexOf("SBOMovable") != -1)
  {
    while(obj.id == "")
      obj = obj.parentNode;

    _Panel = obj;
   
    _Panel.InitialPosX = SBO.DomUtils.GetX(_Panel);
    _Panel.InitialPosY = SBO.DomUtils.GetY(_Panel);

    _Panel.MouseInitialPosX = e.clientX;
    _Panel.MouseInitialPosY = e.clientY;
                        
    _Panel.DocumentOnMouseUp = document.onmouseup;
    _Panel.DocumentOnMouseMove = document.onmousemove;

    document.onmousemove = PanelOnMouseMove;
    document.onmouseup = PanelOnMouseUp;
    
    return false;
  }
}

function PanelOnMouseMove(e)
{
  e = e || event;
    
  if (_Panel)
  {
    _Panel.SBOAjaxPanel.SetXY(_Panel.InitialPosX + e.clientX - _Panel.MouseInitialPosX,
                              _Panel.InitialPosY + e.clientY - _Panel.MouseInitialPosY);
    
    return false;
  }
}

function PanelOnMouseUp(e)
{
  if(_Panel)
  {
    document.onmousemove = _Panel.DocumentOnMouseMove;
    document.onmouseup = _Panel.DocumentOnMouseUp;
  }
  
  _Panel = null;
}





//
// namespace SBO.Format
//

SBO.Format = new function()
{
  //
  // method SBO.Format.SectionTitle
  //

  this.SectionTitle = function(section)
  {
    var title = "";
    
    if(section.heading && section.title)
      title = section.heading + ' ' + section.title;
    else if(section.heading)
      title = section.heading;
    else if(section.title)
      title = section.title;
      
    return title;
  }


  //
  // method SBO.Format.BuildBasicDescription
  //

  this.BuildBasicDescription = function(book)
  {
    var title = '<strong>' + book.title + '</strong>';
    
    var authors = '<br/>' + (book.authors? 'By ' + book.authors : '');
    
    var publisher = book.publisher && book.publisher.publishername ? '<br/>' + book.publisher.publishername : '';
    
    var pubdate = '<br/>' + book.pubdate;
    
    return '' + 
      /*'<table width="100%" cellspacing="0" cellpadding="0">' + 
        '<tr>' + 
          '<td valign="top">' + 
           '<img class="SBOSearchResultImage" src="' + book.imagesmall + '"/>' + 
          '</td>' + 
          '<td valign="top" width="100%" class="SBOSearchResultMeta">' + 
             title + 
             authors + 
             publisher + 
             pubdate + 
          '</td>' + 
        '</tr>' + 
      '</table>' + */
     '<img class="SBOSearchResultImage" src="' + book.imagesmall + '"/>' + 
     '<div class="SBOSearchResultMeta">' + 
       title + 
       authors + 
       publisher + 
       pubdate + 
     '</div>' +
      '<div style="clear:both"></div>';  
  }

  
  
}

//
// class SBO.Ajax.Panel.Book
//

SBO.Ajax.Panel.Book = function()
{
  SBO.Ajax.Panel.call(this, "SBOBookPanel", true, true);

  ///
  // method SBO.Ajax.Panel.Book.Init
  //
  
  this.Init = function()
  {
    SBO.Ajax.Panel.prototype.Init.call(this);
  }
  
  this.SetXY = function(x, y)
  {
    SBO.Ajax.Panel.prototype.SetXY.call(this, x, y);
    
    var panel = document.getElementById("SBOPreviewPanel");
    
    if(panel)
      SBO.Ajax.Panel.prototype.SetXY.call(panel.SBOAjaxPanel, x, y);
  }
  
  this.Init();
}

SBO.Extend(SBO.Ajax.Panel.Book, SBO.Ajax.Panel);



//
// class SBO.Ajax.Panel.Preview
//

SBO.Ajax.Panel.Preview = function()
{
  SBO.Ajax.Panel.call(this, "SBOPreviewPanel", true, true);


  ///
  // method SBO.Ajax.Panel.Preview.Init
  //
  
  this.Init = function()
  {
    SBO.Ajax.Panel.prototype.Init.call(this);
    
  }
  
  
  this.SetXY = function(x, y)
  {
    SBO.Ajax.Panel.prototype.SetXY.call(this, x, y);
    
    var panel = document.getElementById("SBOBookPanel");
    
    if(panel)
      SBO.Ajax.Panel.prototype.SetXY.call(panel.SBOAjaxPanel, x, y);
  }
  
  
  ///
  // method SBO.Ajax.Panel.Preview.LoadToc
  //
  
  this.LoadToc = function(obj, id)
  {
    SBO.Ajax.Panel.prototype.Load.call(obj ? obj : this, "id=" + id, "document.getElementById('SBOPreviewPanel').SBOAjaxPanel.ShowToc");
  }


  ///
  // method SBO.Ajax.Panel.Preview.ShowToc
  //
  
  this.ShowToc = function(results)
  {
    var book = results.book;
    
    this.Show
    (
        '<div id="SBOPreviewPanelContent">' + 
          SBO.Format.BuildBasicDescription(book) + 
          
          '<div id="SBOBookPanelLinks">' + 
            SBO.Ajax.PanelUtils.BuildInnerPanelHtml('<strong>Table of Contents</strong>', "", "", 2) + 
          '</div>' + 
          
          '<div id="SBOPreviewPanelSection">' + 
            this.BuildToc(book.tableofcontents) + 
          '</div>' +
        '</div>',
        this.X,
        this.Y
    );
    
    var panel = document.getElementById("SBOBookPanel");
    if(panel) 
      panel.SBOAjaxPanel.Hide();
  }


  //
  // method SBO.Ajax.Panel.Preview.BuildToc
  //

  this.BuildToc = function(parent, indent)
  {
    SBO.Ajax.ConvertObjectToArray(parent, "section");
   
    if(!indent)
      indent = 0; 
      
    var html = '<div ' + (indent ? 'style="padding-left: 10px"' : '') + '>';
    
    for(var section = parent.section, i = 0, n = section.length; i < n; i++)
    {
      var s = section[i];
      
      if(s.index == 1)
        continue;
     
      html += '' +
        '<br/>' + 
        '<a href="#" class="SBOFont SBOLink" onclick="document.getElementById(\'SBOPreviewPanel\').SBOAjaxPanel.LoadPreview(null,\''+ s.id + '\'); return false;">' + 
          SBO.Format.SectionTitle(s) + 
        '</a>';
      
      if(s.section)
        html += this.BuildToc(s, indent + 1);
    }

    html += '</div>';
    
   
    return html;
    
  }


  ///
  // method SBO.Ajax.Panel.Preview.LoadPreview
  //
  
  this.LoadPreview = function(obj, id, imagepage)
  {
    SBO.Ajax.Panel.prototype.Load.call(obj ? obj : this, "id=" + id + "&imagepage=" + (imagepage ? imagepage : ""), "document.getElementById('SBOPreviewPanel').SBOAjaxPanel.ShowPreview");
    
    this.CurrentXmlId = id;
    this.CurrentImagePage = imagepage;
  }

  this.ShowPreview = function(results)
  {
    var panel = document.getElementById("SBOBookPanel");
    if(panel) 
      panel.SBOAjaxPanel.Hide();
      
  
    var book = results.book;
    
    var section = book.section;


    // the API can return multiple sections due to chunking, so we have to select the one that has been requested
    if(section.length)
    {
      for(var i = 0, n = section.length; i < n; i++)
        if(section[i].position == "0")
          break;
        
      section = section[i];
    }
    
  
    this.Show
    (
        '<div id="SBOPreviewPanelContent">' + 
          SBO.Format.BuildBasicDescription(book) + 
          
          /*
          '<p></p>' +
          
          '<div>' +
            '[' + 
              '<strong>' + SBO.Format.SectionTitle(section.parent) + '</strong> &gt; ' + 
              '<strong>' + SBO.Format.SectionTitle(section) + '</strong>' + 
            ']' + 
          '</div>' + 
          */
          
          
          '<div id="SBOBookPanelLinks">' + 
            
            SBO.Ajax.PanelUtils.BuildInnerPanelHtml('' + 
          
              SBO.Ajax.PanelUtils.BuildTableHtml
              (
                '<a href="#" onclick="document.getElementById(\'SBOPreviewPanel\').SBOAjaxPanel.LoadToc(null,\'' + book.id + '\'); return false;" class="SBOFont SBOLink">' + 
                  'Table of Contents' + 
                '</a>' +

                ' &#8226; ' + 
              
                '<a target="_Safari" href="' + section.url + (this.CurrentImagePage ? '?imagepage=' + this.CurrentImagePage : '') + '" class="SBOFont SBOLink">' + 
                  'Read it on Safari' + 
                '</a>',
                
                (book.prevsection && book.prevsection.id && book.prevsection.id.indexOf("/") > 0 ? '<a href="#" onclick="document.getElementById(\'SBOPreviewPanel\').SBOAjaxPanel.LoadPreview(null,\'' + book.prevsection.id + '\',\'' + (book.prevsection.imagepage ? book.prevsection.imagepage : "") + '\'); return false;">' + '<img border="0" src="' + SBO.Config.Url + '/left-arrow.gif"></img>' + '</a>' : '<img border="0" src="' + SBO.Config.Url + '/left-arrow.gif"></img>') + 
                (book.nextsection && book.nextsection.id && book.nextsection.id.indexOf("/") > 0 ? '<a href="#" onclick="document.getElementById(\'SBOPreviewPanel\').SBOAjaxPanel.LoadPreview(null,\'' + book.nextsection.id + '\',\'' + (book.nextsection.imagepage ? book.nextsection.imagepage : "") + '\'); return false;">' + '<img border="0" src="' + SBO.Config.Url + '/right-arrow.gif"></img>' + '</a>' : '<img border="0" src="' + SBO.Config.Url + '/right-arrow.gif"></img>')  
              ),                
              "", "", 2) +
            
          '</div>' + 

          '<div id="SBOPreviewPanelSection">' + 
            section.preview + 
          '</div>' +
          
          '<div id="SBOPreviewPanelPromo">' + 
            '<a target="_Safari" href="' + SBO.Config.Host + '/promo"><img border="0" src="' + SBO.Config.Url + '/preview.gif"></img></a>' + 
          '</div>' +
            
          
        '</div>',
        
        this.X,
        this.Y
    );
  }
  
  /*this.BeforeShow = function()
  {
    var preview = document.getElementById("SBOPreviewPanelSection");
    
    if(preview)
      for (var images = preview.getElementsByTagName('img'), i = 0, n = images.length; i < n; i++)
      {
        var img = images[i];
        if (img.src && img.src.charAt(0) == "/")
          img.src = SBO.Config.Host + img.src;
      }
  }*/
  

  
  this.Init();
}

SBO.Extend(SBO.Ajax.Panel.Preview, SBO.Ajax.Panel);



//
// class SBO.Ajax.Panel.Search
//

SBO.Ajax.Panel.Search = function()
{
  SBO.Ajax.Panel.call(this, "SBOSearchPanel", false, false);
  

  ///
  // method SBO.Ajax.Panel.Search.Init
  //
  
  this.Init = function()
  {
    SBO.Ajax.Panel.prototype.Init.call(this);
    
    this.InitHtml();    
    
    
    this.SearchPanel = SBO.Ajax.PanelUtils.BuildInnerPanelHtml(this.SearchPanelHtml, "","", 1);
    
    this.SearchInfoPanel = SBO.Ajax.PanelUtils.BuildInnerPanelHtml(this.SearchInfoHtml, "SBOSearchInfo", "", 1);
    
    this.SearchNumberOfResultsPanel = SBO.Ajax.PanelUtils.BuildInnerPanelHtml("", "SBOSearchNumberOfResults", "display: none;", 1);
      
    this.SearchResultsPanel = SBO.Ajax.PanelUtils.BuildInnerPanelHtml("", "SBOSearchResults", "display: none;", 1);
    
    this.SearchResultsInfoPanel = SBO.Ajax.PanelUtils.BuildInnerPanelHtml("", "SBOSearchResultsInfo", "display: none;", 1);
    
    
    this.Container.innerHTML = '' + 
      this.PanelTopHtml + 
      this.SearchPanel + 
      this.SearchInfoPanel + 
      this.SearchNumberOfResultsPanel + 
      this.SearchResultsPanel + 
      this.SearchResultsInfoPanel + 
      this.PanelBottomHtml;
      
    
    this.SearchResults = document.getElementById("SBOSearchResults");
    this.SearchResultsContent = document.getElementById("SBOSearchResultsContent");
    
    this.SearchNumberOfResults = document.getElementById("SBOSearchNumberOfResults");
    this.SearchNumberOfResultsContent = document.getElementById("SBOSearchNumberOfResultsContent");
    
    this.SearchInfo = document.getElementById("SBOSearchInfo");
    this.SearchInfoContent = document.getElementById("SBOSearchInfoContent");
    
    this.SearchResultsInfo = document.getElementById("SBOSearchResultsInfo");
    this.SearchResultsInfoContent = document.getElementById("SBOSearchResultsInfoContent");

    this.SearchInput = document.getElementById("SBOSearchInput");

    this.BookPanel = new SBO.Ajax.Panel.Book();
    this.PreviewPanel = new SBO.Ajax.Panel.Preview();
  }
  
  ///
  // method SBO.Ajax.Panel.Search.Hide
  //
  
  
  this.Hide = function()
  {
    SBO.Ajax.Panel.prototype.Hide.call(this);
    
    
    this.SearchInput.value = "";
    
    this.SearchInfo.style.display = "";
    
    this.SearchNumberOfResults.style.display = "none";
    this.SearchResultsInfo.style.display = "none";
    this.SearchResults.style.display = "none";
  }
  
            
  ///
  // method SBO.Ajax.Panel.Search.InitHtml
  //
  
  this.InitHtml = function()
  {
    this.SearchPanelHtml = '' +
      '<form id="SBOSearchForm" onsubmit="document.getElementById(\'SBOSearchPanel\').SBOAjaxPanel.Load(document.getElementById(\'SBOSearchInput\').value); return false;">' +
        '<label id="SBOSearchLabel" for="SBOSearchInput">Search Safari: </label>' + 
        '<input type="text" id="SBOSearchInput" class="SBOFont"/>' + 
        '<a title="Submit Query" href="#" onclick="document.getElementById(\'SBOSearchPanel\').SBOAjaxPanel.Load(document.getElementById(\'SBOSearchInput\').value); return false;">' +
          '<img id="SBOSearchButton" border="0" src="' + SBO.Config.Url + '/go.gif"></img>' + 
        '</a>' + 
      '</form>';
    
    this.SearchInfoHtml = '' + 
    //'<p><strong>Explore Safari with this search widget!</strong> Morbi a metus. Phasellus enim erat, vestibulum vel, aliquam a, posuere eu, velit. Nullam sapien sem, ornare ac, nonummy non, lobortis a, enim.</p>';
      '<p>' + 
        '<strong>Explore Safari Books Online!</strong>' + 
        '<br/>Safari Books Online is the electronic reference library that delivers expert content from the world\'s most trusted leaders in technology publishing to professionals worldwide.' + 
        '<br/>' + 
        '<br/>Search across thousands of titles in our collection, including titles from O\'Reilly Media, Addison-Wesley, Peachpit, Adobe Press and many more.' + 
      '</p>';

    this.SearchNumberOfResultsHtml = 'Found {0} book(s) matching your search for <strong>{1}</strong>.';
    this.SearchNoResultsHtml = 'Your search for <strong>{1}</strong> returned {0} total results. Please try again with fewer or more general keywords.';

    this.SearchResultsInfoHtml = '<a target="_Safari" title="View Complete Results on Safari" class="SBOFont SBOLink" href="{0}/search?searchtextbox={1}&searchmode=simple&searchview=summary&searchfor=SearchForAllBooks&searchlistbox=&isbn=">View Complete Results on Safari ></a>';
  }
  
  
  this.Show = function(query, x, y)
  {
    this.SearchInput.value = query;
    
    if(x && y)
      this.SetXY(x, y);
      
    this.Shown = true;
    
    this.Container.style.display = "";
  }
 
  
  //
  // method SBO.Ajax.Panel.Search.Draw
  //

  this.Draw = function(html)
  {
    this.SearchInfo.style.display = "none";
    
    this.SearchResultsContent.innerHTML = html;
    this.SearchResults.style.display = this.Results && this.Results.books ? "" : "none";
    
    this.SearchNumberOfResultsContent.innerHTML = this.Results && this.Results.books > 0 ?
      SBO.StringUtils.Replace(this.SearchNumberOfResultsHtml, this.Results.books, this.SearchInput.value) : 
      SBO.StringUtils.Replace(this.SearchNoResultsHtml, 0, this.SearchInput.value);
      
    this.SearchNumberOfResults.style.display = "";

    this.SearchResultsInfoContent.innerHTML = SBO.StringUtils.Replace(this.SearchResultsInfoHtml, SBO.Config.Host, encodeURIComponent(this.SearchInput.value));
    this.SearchResultsInfo.style.display = this.Results && this.Results.books ? "": "none";
    
    this.Show(this.SearchInput.value);
  }


  //
  // method SBO.Ajax.Panel.Search.Load
  //

  this.Load = function(query, x, y)
  {
    if(!query)
      return;
  
    this.SearchInput.value = query;
    
    if(x && y)
      this.SetXY(x, y);
    
    SBO.Ajax.Panel.prototype.Load.call(this, "&imagepage=&page=&spp=20&&view=book&sort=rank&sortorder=desc&search=" + encodeURIComponent("(" + query + ")" + " ANDNOT VIDEO"), "document.getElementById(\'SBOSearchPanel\').SBOAjaxPanel.ShowSearch");
  }


  //
  // method SBO.Ajax.Panel.Search.ShowSearch
  //

  this.ShowSearch = function(results)
  { 
    this.PreviewPanel.Hide();
    this.BookPanel.Hide();
  
    if(!results.book)
    {
      this.Results = null;
      this.Draw("");
      return;
    }
        
    SBO.Ajax.ConvertObjectToArray(results, "book");
    
    results.book.sort(function(a,b){ return a.position - b.position });
    
    this.Results = results;
    
    var html = '<div id="SBOSearchResultsContentTable">';
    
    for(var i = 0, n = results.book.length; i < n; i++)
    {
      var book = results.book[i];
      
      html += '' + 
              '<div class="SBOSearchResult" onmouseover="document.getElementById(\'SBOSearchPanel\').SBOAjaxPanel.InternalShowBook(' + i + ', this)">' + 
                  SBO.Format.BuildBasicDescription(book) + 
                  /* (book.description ? book.description.slice(0, 100) : '') + '...' + */
              '</div>';
    }
    
    html += '</div>';
     
    

    this.Draw(html);
  }

  
  
  

  this.BuildLongDescription = function(book)
  {
    return '' + 
      '<div id="SBOBookPanelContent">' + 
          SBO.Format.BuildBasicDescription(book) + 
          
          '<div id="SBOBookPanelLinks">' + 
            SBO.Ajax.PanelUtils.BuildInnerPanelHtml
            (
          
            '<a href="#" onclick="document.getElementById(\'SBOPreviewPanel\').SBOAjaxPanel.LoadPreview(document.getElementById(\'SBOBookPanel\').SBOAjaxPanel,\'' + book.nextsection.id + '\'); return false;" class="SBOFont SBOLink">' +
              'Start Reading' + 
            '</a>' +
            
            ' &#8226; ' + 
            
            '<a href="#" onclick="document.getElementById(\'SBOPreviewPanel\').SBOAjaxPanel.LoadToc(document.getElementById(\'SBOBookPanel\').SBOAjaxPanel,\'' + book.id + '\'); return false;" class="SBOFont SBOLink">' + 
              'Table of Contents' + 
            '</a>' +

            ' &#8226; ' + 
            
            '<a target="_Safari" href="' + book.url + '" class="SBOFont SBOLink">' + 
              'Read it on Safari' + 
            '</a>' 
          , "", "", 2) +
          
          '</div>' +  
         
          '<div id="SBOBookPanelDescriptionShort">' + 
            book.htmldescription +
          '</div>' + 
          
          
      '</div>';
  
  }
  
  
  
  this.LoadBook = function(id, x, y)
  { 
    this.PreviewPanel.Hide();
    this.BookPanel.Hide();
    this.Hide();
    
    this.BookPanel.X = x;
    this.BookPanel.Y = y;
    
    SBO.Ajax.Panel.prototype.Load.call(this, "search=ISBN%3D" + id, "document.getElementById('SBOSearchPanel').SBOAjaxPanel.ShowBook");
  }
  
  
  this.ShowBook = function(results)
  {
    this.BookPanel.i = -1;
    this.BookPanel.Shown = true;
    
    this.BookPanel.Show
      (
        this.BuildLongDescription(results.book),
        this.BookPanel.X, this.BookPanel.Y
      );
      
    this.PreviewPanel.X = this.BookPanel.X;
    this.PreviewPanel.Y = this.BookPanel.Y;
  }
  

  this.InternalShowBook = function(i, obj)
  { 
    if(this.PreviewPanel.Shown)
      return;
      
    if(this.BookPanel.i == i && this.BookPanel.Shown)
      return;
   
    this.BookPanel.i = i;
    
    this.BookPanel.Show
      (
        this.BuildLongDescription(this.Results.book[i]),
        SBO.DomUtils.GetX(obj) - 464 - 12 /* harcoded temporarily */, 
        SBO.DomUtils.GetY(obj)
      );
      
    this.PreviewPanel.X = this.BookPanel.X - 50;
    this.PreviewPanel.Y = this.BookPanel.Y;
  }

  this.Init();
}

SBO.Extend(SBO.Ajax.Panel.Search, SBO.Ajax.Panel);


function ___MoveTo(xmlId, anchorId)
{
  //window.open(SBO.Config.Host + '/' + xmlid + "#" + anchor, '_blank');
  
  var panel = document.getElementById('SBOPreviewPanel').SBOAjaxPanel;
  
  if(panel && xmlId != panel.CurrentXmlId)
    panel.LoadPreview(null, xmlId);
  
  for (var a = document.getElementsByTagName('a'), i = 0, n = a.length; i < n; i++)
    if (a[i].name == anchorId)
    {
      var s = document.getElementById('SBOPreviewPanelSection');
      if(s)
        s.scrollTop = a[i].offsetTop;
      break;
    }
    
}
