﻿// Accordion.js
// Javascript Behaviour for the AccordionBehaviour Control
// Copyright (c) by Matthias Hertel, http://www.mathertel.de
// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
// ----- 
// 13.05.2007 created by Matthias Hertel
// 18.12.2007 Simplifications and documentation.
// 12.01.2008 adding postback-support by saving the current open area.

var AccordionBehaviour = {
  /// <summary>Implementation of a JavaScript Behavior for a accordion control.
  /// This control implements a space saving visual effect with multiple stacked
  /// areas of content. There is only one of the content areas visible.
  /// Any other area can be made visible by clicking into the associated title.</summary>

  _timer: null, /// <summary>reference to the timer used for the transitions</summary>
  _openarea: 0, /// <summary>number of the part that is visible.</summary>
  
  init: function () {
    /// <summary>Initialize the component and show the last open area.</summary>
    var area = -1;
    c = this.firstChild;
    if (c.tagName == "INPUT")
      this._openarea = c.value;

    if (this._openarea) {
      // adjustClassNames and calc the openPart number
      var allElements = this.getElementsByTagName("div");
      for (var n = 0; n < allElements.length; n++) {
        var obj = allElements[n];
        if ((obj.className == "VEACCORDIONHEADER") || (obj.className == "VEACCORDIONHEADERACTIVE")) {
          area++;
          obj.className = "VEACCORDIONHEADER" + (area == this._openarea ? "ACTIVE" : "");
        } else if ((obj.className == "VEACCORDIONCONTENT") || (obj.className == "VEACCORDIONCONTENTACTIVE")) {
          obj.className = "VEACCORDIONCONTENT" + (area == this._openarea ? "ACTIVE" : "");
        } // if
      } // for
    } // if
  }, // init
  
  // --- events

  onclick: function (evt) {
    /// <summary>Handle click events for opening a new accordion area.</summary>
    evt = evt || window.event;
    if (this._timer == null)
      this.SlideOpen(evt.srcElement);
  }, // onclick


  // --- public methods

  SlideOpen: function (obj) {
    /// <summary>Start opening a new content area.
    /// Setup the timer and start the size transitions.</summary>
    var h, c;
    var area = 0;
    
    // search the HEADER
    while ((obj != null) && (obj != this) && (obj.className != "VEACCORDIONHEADER"))
      obj = obj.parentNode;
    if ((obj != null) && (obj != this) && (obj.className == "VEACCORDIONHEADER"))
      obj.className = "VEACCORDIONHEADERACTIVE";
    h = obj;
    
    // search the next CONTENT
    while ((obj != null) && (obj != this) && (obj.className != "VEACCORDIONCONTENT"))
      obj = obj.nextSibling;
      
    if ((obj != null) && (obj != this) && (obj.className == "VEACCORDIONCONTENT")) {
      c = obj;
      c.style.height = "0px";
      c.className = "VEACCORDIONCONTENTACTIVE";
      
      // adjustClassNames and calc the openPart number
      var allElements = this.getElementsByTagName("div");
      for (var n = 0; n < allElements.length; n++) {
        var obj = allElements[n];
        if ((obj.className == "VEACCORDIONHEADERACTIVE") && (obj != h))
          obj.className = "VEACCORDIONHEADER";
        if ((obj.className == "VEACCORDIONCONTENTACTIVE") && (obj != c))
          obj.className = "VEACCORDIONCONTENT";

        if (obj.className == "VEACCORDIONHEADER") area++;
        if (obj.className == "VEACCORDIONHEADERACTIVE") this._openarea = area;

      } // for
      
      // save the new state of the accordion to enable round-trips.
      c = this.firstChild;
      if (c.tagName == "INPUT")
        c.value = this._openarea;
      
      // start sliding...
      this._timer = window.setTimeout(this._resizeItem.bind(this), 5);
    } // if
  }, // SlideOpen
  

  _resizeItem: function (obj) {
    /// <summary>Handle the internal timer event and
    /// resize the accordion content regions by a view pixel.</summary>
    var allElements = this.getElementsByTagName("div");
    var isFinished = true;
    var delta;

    this._timer = null;

    for (var n = 0; n < allElements.length; n++) {
      var obj = allElements[n];
      if (obj.className == "VEACCORDIONCONTENTACTIVE") {
        // enlarge
        delta = obj.scrollHeight - obj.offsetHeight;
        if (delta <= 0) {
          // nothing.
        } else if ((delta <= 2) && (delta > 0)) {
          // snap exactly
          obj.style.height = obj.offsetHeight + "px";
        } else {
          obj.style.height = Math.round(obj.offsetHeight + Math.max(2, Math.min(12, delta/3))) + "px";
          isFinished = false;
        } // if
          
      } else if (obj.className == "VEACCORDIONCONTENT") {
        // shrink
        delta = obj.offsetHeight;
        if (delta <= 0) {
          // nothing.
        } else if (delta <= 2) {
          // snap exactly
          obj.style.height = "0px";
        } else {
          obj.style.height = Math.round(obj.offsetHeight - Math.max(2, Math.min(12, delta/3))) + "px";
          isFinished = false;
        } // if
      }
    } // for
    if (! isFinished)
      this._timer = window.setTimeout(this._resizeItem.bind(this), 20);
  } // _resizeItem
} // AccordionBehaviour
// End
