// 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
This page is part of the http://www.mathertel.de/AJAXEngine/default.aspx project. For updates and discussions see The AJAX Engine blog.
For updates and discussions see http://ajaxaspects.blogspot.com/.