Solved

Help with nested jQuery accordions

Posted on 2013-06-27
9
378 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
 
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
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

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 42

Expert Comment

by:Rob Jurd, EE MVE
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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

I've been trying to accomplish this for a while and it just struck me yesterday how to accomplish this task. I have done searches all over the internet looking for ways to email pages from my applications and finally I have done it!!! Every single s…
Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
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…

747 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now