Solved

Help with nested jQuery accordions

Posted on 2013-06-27
9
408 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Suggested Solutions

JavaScript can be used in a browser to change parts of a webpage dynamically. It begins with the following pattern: If condition W is true, do thing X to target Y after event Z. Below are some tips and tricks to help you get started with JavaScript …
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
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…

726 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