Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Help with nested jQuery accordions

Posted on 2013-06-27
9
403 Views
Last Modified: 2013-11-27
Hello.

I have a table (must be a table) where the row expands to reveal another row that also expands/collapses.

The problem is when I click on the sub-row to expand it the parent row collapses.

Here is my table:
<tr class="accordion">
	<td>
		<span></span><div class="head">Header 1</div>
	</td>
</tr>
<tr class="content">
	<td colspan="12">
		<table border="0" cellspacing="0" cellpadding="0" id="lit">
			<!-- panel -->
			<tr class="accordion">
				<td>
					<span></span><div class="head">Header 2</div>
				</td>
			</tr>
			<tr class="content">
				<td>Some content here</td>
			</tr>
		<!-- end panel -->
		</table>
	</td>
</tr>
<!-- end panel -->

Open in new window


...And here is the jQuery code:

$(document).ready(function() {
				
	//syntax highlighter
	hljs.tabReplace = '    ';
	hljs.initHighlightingOnLoad();

	//accordion
	$('tr.accordion').accordion({
		//defaultOpen: 'section1',
		speed: 'fast',
		animateOpen: function (elem, opts) { //replace the standard slideUp with custom function
			elem.next().slideFadeToggle(opts.speed);
		},
		animateClose: function (elem, opts) { //replace the standard slideDown with custom function
			elem.next().slideFadeToggle(opts.speed);
		}
	});

	

	//custom animation for open/close
	$.fn.slideFadeToggle = function(speed, easing, callback) {
		return this.animate({opacity: 'toggle', height: 'toggle'}, speed, easing, callback);
	};

});

Open in new window


Please help!
0
Comment
Question by:tekgrl
9 Comments
 
LVL 58

Expert Comment

by:Gary
ID: 39282806
You would need to reclassify your nested accordion as a new accordion or try this plugin
http://www.adipalaz.com/experiments/jquery/nested_accordion.html
0
 
LVL 6

Expert Comment

by:lightspeedvt
ID: 39282862
Will be good to see the site.
0
 

Author Comment

by:tekgrl
ID: 39282918
There is no solution for my current code? I am showing you a VERY abridged version of what I have built. It will take me a long time to start over.

Hopefully someone out there can help me.

My code is attached.
my-accordion.zip
0
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 58

Expert Comment

by:Gary
ID: 39282973
You have two solutions above. That is the only way - the jquery Accordion plugin is not designed for nested levels, that is why you have to declare a new accordion element with the parent Accordion.
Or use the other plugin
0
 

Author Comment

by:tekgrl
ID: 39283003
Hmmm, okay I'm game. How do I reclassify my nested accordion? I tried giving it a new name "accordion2" and duplicating the .js but that didn't do it.
0
 
LVL 82

Accepted Solution

by:
hielo earned 500 total points
ID: 39284828
The code below is a modified implementation of the accordion you provided.  I did not do thorough testing so if you have other pages that are already using the original accordion plugin, I suggest you save the code below as jquery.nested-accordion.js instead of overwriting the original jquery.accordion.js file.  It should work with the markup you provided.

/**
 * Accordion, jQuery Plugin
 *
 * This plugin provides an accordion with cookie support.
 *
 * Copyright (c) 2010 John Snyder (snyderplace.com)
 * @license http://www.snyderplace.com/accordion/license.txt New BSD
 * @version alpha 0.1
 */
(function($) {
	$.fn.accordion = function(options) {
		initialize(this, options);
	};

	//create the initial accordion
	function initialize(obj, options) {
		//build main options before element iteration
		var opts = $.extend({}, $.fn.accordion.defaults, options);

		//store any opened default values to set cookie later
		var opened = '';
		opts.bind=opts.bind.toLowerCase();

		//iterate each matched object, bind, and open/close
		obj.each(function() {
			var $this = $(this);
			saveOpts($this, opts);

			//bind it to the event
			if (opts.bind.match(/^mouseenter|mouseover|click|dblclick$/)) {
				$this.bind(opts.bind, function(e) {

					if( opts.stopPropagation )
					{
						e.stopPropagation();
					}

					e.preventDefault();
					toggle($this, opts, e);
				});
			}

			//initialize the panels
			//get the id for this element
			id = $this.attr('id');

			//if not using cookies, open defauls
			if (!useCookies(opts)) {
				//close it if not defaulted to open
				if (id != opts.defaultOpen) {
					$this.addClass(opts.cssClose);
					$this.next().hide();
				} else { //its a default open, open it
					$this.addClass(opts.cssOpen);
					$this.next().show();
					opened = id;
				}
			} else { //can use cookies, use them now
				//has a cookie been set, this overrides default open
				if (issetCookie(opts)) {
					if (inCookie(id, opts) === false) {
						$this.addClass(opts.cssClose);
						$this.next().hide();
					} else {
						$this.addClass(opts.cssOpen);
						$this.next().show();
						opened = id;
					}
				} else { //a cookie hasn't been set open defaults
					if (id != opts.defaultOpen) {
						$this.addClass(opts.cssClose);
						$this.next().hide();
					} else { //its a default open, open it
						$this.addClass(opts.cssOpen);
						$this.next().show();
						opened = id;
					}
				}
			}
		});

		//now that the loop is done, set the cookie
		if (opened.length > 0 && useCookies(opts)) {
			setCookie(opened, opts);
		} else { //there are none open, set cookie
			setCookie('', opts);
		}

		return obj;
	};

	//load opts from object
	function loadOpts($this) {
		return $this.data('accordion-opts');
	}

	//save opts into object
	function saveOpts($this, opts) {
		return $this.data('accordion-opts', opts);
	}

	//hides a accordion panel
	function close(opts, e) {
		var t=e.target;
		opened = $(t).find('.' + opts.cssOpen);
		$.each(opened, function() {
			//give the proper class to the linked element
			$(this).addClass(opts.cssClose).removeClass(opts.cssOpen);
			opts.animateClose($(this), opts, e);
		});
	}

	//opens a accordion panel
	function open($this, opts, e) {
		close(opts, e);
		//give the proper class to the linked element
		$this.removeClass(opts.cssOpen).addClass(opts.cssClose);

		//open the element
		opts.animateOpen($this, opts, e);

		//do cookies if plugin available
		if (useCookies(opts)) {
			// split the cookieOpen string by ","
			id = $this.attr('id');
			setCookie(id, opts);
		}
	}

	//toggle a accordion on an event
	function toggle($this, opts, e) {
		// close the only open item
        if ($this.hasClass(opts.cssOpen))
		{
		     close(opts, e);
             //do cookies if plugin available
             if (useCookies(opts)) {
             	// split the cookieOpen string by ","
             	setCookie('', opts);
             }
        return false;
		}
		//close(opts, e);
		//open a closed element
		open($this, opts, e);
		return false;
	}

	//use cookies?
	function useCookies(opts) {
		//return false if cookie plugin not present or if a cookie name is not provided
		if (!$.cookie || opts.cookieName == '') {
			return false;
		}

		//we can use cookies
		return true;
	}

	//set a cookie
	function setCookie(value, opts)
	{
		//can use the cookie plugin
		if (!useCookies(opts)) { //no, quit here
			return false;
		}

		//cookie plugin is available, lets set the cookie
		$.cookie(opts.cookieName, value, opts.cookieOptions);
	}

	//check if a accordion is in the cookie
	function inCookie(value, opts)
	{
		//can use the cookie plugin
		if (!useCookies(opts)) {
			return false;
		}

		//if its not there we don't need to remove from it
		if (!issetCookie(opts)) { //quit here, don't have a cookie
			return false;
		}

		//unescape it
		cookie = unescape($.cookie(opts.cookieName));

		//is this value in the cookie arrray
		if (cookie != value) { //no, quit here
			return false;
		}

		return true;
	}

	//check if a cookie is set
	function issetCookie(opts)
	{
		//can we use the cookie plugin
		if (!useCookies(opts)) { //no, quit here
			return false;
		}

		//is the cookie set
		if ($.cookie(opts.cookieName) == null) { //no, quit here
			return false;
		}

		return true;
	}

	// settings
	$.fn.accordion.defaults = {
		cssClose: 'accordion-close', //class you want to assign to a closed accordion header
		cssOpen: 'accordion-open', //class you want to assign an opened accordion header
		cookieName: 'accordion', //name of the cookie you want to set for this accordion
		cookieOptions: { //cookie options, see cookie plugin for details
			path: '/',
			expires: 7,
			domain: '',
			secure: ''
		},
		stopPropagation: false,
		defaultOpen: '', //id that you want opened by default
		speed: 'slow', //speed of the slide effect
		bind: 'click', //event to bind to, supports click, dblclick, mouseover and mouseenter
		animateOpen: function (elem, opts, e) { //replace the standard slideDown with custom function
			elem.next().slideDown(opts.speed);
		},
		animateClose: function (elem, opts, e) { //replace the standard slideUp with custom function
			elem.next().slideUp(opts.speed);
		}
	};
})(jQuery);

Open in new window

0
 
LVL 43

Expert Comment

by:Rob
ID: 39672763
I've requested that this question be closed as follows:

Accepted answer: 500 points for hielo's comment #a39284828

for the following reason:

This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.
0
 
LVL 58

Expert Comment

by:Gary
ID: 39672764
Well I gave a very simple answer - give the nested accordion a different class.
No messing about.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Else condition 9 23
how can i get the sole odd and th sole even 2 33
Create an automated page index 9 50
VBScript on Html 15 47
Avoid defining the variables in the global scope; trying to define them in a local function scope. Because:   • Look-up is performed every time a variable is accessed.   • Variables are resolved backwards from most specific to least specific scope…
In Part 1 (http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/A_7849-Hex-Maze.html) we covered the hexagonal maze basics -- how the cells are represented in a JavaScript array and how the maze is displayed.  In this part, we'…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question