Solved

How can I get the links in a Dreamweaver spry accordion tab to work?

Posted on 2008-10-12
7
1,325 Views
Last Modified: 2009-05-19
I am using a Dreamweaver CS3 spry accordion.  Dreamweaver CS3 adds a javascript page called SpryAccordion.js (version 1.6.1).  I have four links in the tabs of the accordion.  I believe the SpryAccordion.js script is disabling the links.  When the user clicks on any of the links the accordion expands or collapses, but the links never work.

My goal is to get the links to work.  When the links are clicked the accordion should neither expand or collapse.

I saw a previous response on a similar issue, but simply commenting out the (e.preventDefault) and (e.stopPropagation) does not seem to work.
// SpryAccordion.js - version 0.15 - Spry Pre-Release 1.6.1
 

var Spry;

if (!Spry) Spry = {};

if (!Spry.Widget) Spry.Widget = {};
 

Spry.Widget.Accordion = function(element, opts)

{

	this.element = this.getElement(element);

	this.defaultPanel = -1;

	this.hoverClass = "AccordionPanelTabHover";

	this.openClass = "AccordionPanelOpen";

	this.closedClass = "AccordionPanelClosed";

	this.focusedClass = "AccordionFocused";

	this.enableAnimation = true;

	this.enableKeyboardNavigation = true;

	this.currentPanel = null;

	this.animator = null;

	this.hasFocus = null;
 

	this.previousPanelKeyCode = Spry.Widget.Accordion.KEY_UP;

	this.nextPanelKeyCode = Spry.Widget.Accordion.KEY_DOWN;
 

	this.useFixedPanelHeights = false;

	this.fixedPanelHeight = 0;
 

	Spry.Widget.Accordion.setOptions(this, opts, true);
 

	this.attachBehaviors();

};
 

Spry.Widget.Accordion.prototype.getElement = function(ele)

{

	if (ele && typeof ele == "string")

		return document.getElementById(ele);

	return ele;

};
 

Spry.Widget.Accordion.prototype.addClassName = function(ele, className)

{

	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))

		return;

	ele.className += (ele.className ? " " : "") + className;

};
 

Spry.Widget.Accordion.prototype.removeClassName = function(ele, className)

{

	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1))

		return;

	ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");

};
 

Spry.Widget.Accordion.setOptions = function(obj, optionsObj, ignoreUndefinedProps)

{

	if (!optionsObj)

		return;

	for (var optionName in optionsObj)

	{

		if (ignoreUndefinedProps && optionsObj[optionName] == undefined)

			continue;

		obj[optionName] = optionsObj[optionName];

	}

};
 

Spry.Widget.Accordion.prototype.onPanelTabMouseOver = function(e, panel)

{

	if (panel)

		this.addClassName(this.getPanelTab(panel), this.hoverClass);

	return false;

};
 

Spry.Widget.Accordion.prototype.onPanelTabMouseOut = function(e, panel)

{

	if (panel)

		this.removeClassName(this.getPanelTab(panel), this.hoverClass);

	return false;

};
 

Spry.Widget.Accordion.prototype.openPanel = function(elementOrIndex)

{

	var panelA = this.currentPanel;

	var panelB;
 

	if (typeof elementOrIndex == "number")

		panelB = this.getPanels()[elementOrIndex];

	else

		panelB = this.getElement(elementOrIndex);

	

	if (!panelB || panelA == panelB)	

		return null;
 

	var contentA = panelA ? this.getPanelContent(panelA) : null;

	var contentB = this.getPanelContent(panelB);
 

	if (!contentB)

		return null;
 

	if (this.useFixedPanelHeights && !this.fixedPanelHeight)

		this.fixedPanelHeight = (contentA.offsetHeight) ? contentA.offsetHeight : contentA.scrollHeight;
 

	if (this.enableAnimation)

	{

		if (this.animator)

			this.animator.stop();

		this.animator = new Spry.Widget.Accordion.PanelAnimator(this, panelB, { duration: this.duration, fps: this.fps, transition: this.transition });

		this.animator.start();

	}

	else

	{

		if(contentA)

		{

			contentA.style.display = "none";

			contentA.style.height = "0px";

		}

		contentB.style.display = "block";

		contentB.style.height = this.useFixedPanelHeights ? this.fixedPanelHeight + "px" : "auto";

	}
 

	if(panelA)

	{

		this.removeClassName(panelA, this.openClass);

		this.addClassName(panelA, this.closedClass);

	}
 

	this.removeClassName(panelB, this.closedClass);

	this.addClassName(panelB, this.openClass);
 

	this.currentPanel = panelB;
 

	return panelB;

};
 

Spry.Widget.Accordion.prototype.closePanel = function()

{

	// The accordion can only ever have one panel open at any

	// give time, so this method only closes the current panel.

	// If the accordion is in fixed panel heights mode, this

	// method does nothing.
 

	if (!this.useFixedPanelHeights && this.currentPanel)

	{

		var panel = this.currentPanel;

		var content = this.getPanelContent(panel);

		if (content)

		{

			if (this.enableAnimation)

			{

				if (this.animator)

					this.animator.stop();

				this.animator = new Spry.Widget.Accordion.PanelAnimator(this, null, { duration: this.duration, fps: this.fps, transition: this.transition });

				this.animator.start();

			}

			else

			{

				content.style.display = "none";

				content.style.height = "0px";

			}

		}		

		this.removeClassName(panel, this.openClass);

		this.addClassName(panel, this.closedClass);

		this.currentPanel = null;

	}

};
 

Spry.Widget.Accordion.prototype.openNextPanel = function()

{

	return this.openPanel(this.getCurrentPanelIndex() + 1);

};
 

Spry.Widget.Accordion.prototype.openPreviousPanel = function()

{

	return this.openPanel(this.getCurrentPanelIndex() - 1);

};
 

Spry.Widget.Accordion.prototype.openFirstPanel = function()

{

	return this.openPanel(0);

};
 

Spry.Widget.Accordion.prototype.openLastPanel = function()

{

	var panels = this.getPanels();

	return this.openPanel(panels[panels.length - 1]);

};
 

Spry.Widget.Accordion.prototype.onPanelTabClick = function(e, panel)

{

	if (panel != this.currentPanel)

		this.openPanel(panel);

	else

		this.closePanel();
 

	if (this.enableKeyboardNavigation)

		this.focus();
 

	if (e.preventDefault) e.preventDefault();

	else e.returnValue = false;

	if (e.stopPropagation) e.stopPropagation();

	else e.cancelBubble = true;

	
 
 
 

	return false;

};
 

Spry.Widget.Accordion.prototype.onFocus = function(e)

{

	this.hasFocus = true;

	this.addClassName(this.element, this.focusedClass);

	return false;

};
 

Spry.Widget.Accordion.prototype.onBlur = function(e)

{

	this.hasFocus = false;

	this.removeClassName(this.element, this.focusedClass);

	return false;

};
 

Spry.Widget.Accordion.KEY_UP = 38;

Spry.Widget.Accordion.KEY_DOWN = 40;
 

Spry.Widget.Accordion.prototype.onKeyDown = function(e)

{

	var key = e.keyCode;

	if (!this.hasFocus || (key != this.previousPanelKeyCode && key != this.nextPanelKeyCode))

		return true;

	

	var panels = this.getPanels();

	if (!panels || panels.length < 1)

		return false;

	var currentPanel = this.currentPanel ? this.currentPanel : panels[0];

	var nextPanel = (key == this.nextPanelKeyCode) ? currentPanel.nextSibling : currentPanel.previousSibling;
 

	while (nextPanel)

	{

		if (nextPanel.nodeType == 1 /* Node.ELEMENT_NODE */)

			break;

		nextPanel = (key == this.nextPanelKeyCode) ? nextPanel.nextSibling : nextPanel.previousSibling;

	}
 

	if (nextPanel && currentPanel != nextPanel)

		this.openPanel(nextPanel);
 

	if (e.preventDefault) e.preventDefault();

	else e.returnValue = false;

	if (e.stopPropagation) e.stopPropagation();

	else e.cancelBubble = true;
 

	return false;

};
 

Spry.Widget.Accordion.prototype.attachPanelHandlers = function(panel)

{

	if (!panel)

		return;
 

	var tab = this.getPanelTab(panel);
 

	if (tab)

	{

		var self = this;

		Spry.Widget.Accordion.addEventListener(tab, "click", function(e) { return self.onPanelTabClick(e, panel); }, false);

		Spry.Widget.Accordion.addEventListener(tab, "mouseover", function(e) { return self.onPanelTabMouseOver(e, panel); }, false);

		Spry.Widget.Accordion.addEventListener(tab, "mouseout", function(e) { return self.onPanelTabMouseOut(e, panel); }, false);

	}

};
 

Spry.Widget.Accordion.addEventListener = function(element, eventType, handler, capture)

{

	try

	{

		if (element.addEventListener)

			element.addEventListener(eventType, handler, capture);

		else if (element.attachEvent)

			element.attachEvent("on" + eventType, handler);

	}

	catch (e) {}

};
 

Spry.Widget.Accordion.prototype.initPanel = function(panel, isDefault)

{

	var content = this.getPanelContent(panel);

	if (isDefault)

	{

		this.currentPanel = panel;

		this.removeClassName(panel, this.closedClass);

		this.addClassName(panel, this.openClass);
 

		// Attempt to set up the height of the default panel. We don't want to

		// do any dynamic panel height calculations here because our accordion

		// or one of its parent containers may be display:none.
 

		if (content)

		{

			if (this.useFixedPanelHeights)

			{

				// We are in fixed panel height mode and the user passed in

				// a panel height for us to use.

	

				if (this.fixedPanelHeight)

					content.style.height = this.fixedPanelHeight + "px";

			}

			else

			{

				// We are in variable panel height mode, but since we can't

				// calculate the panel height here, we just set the height to

				// auto so that it expands to show all of its content.

	

				content.style.height = "auto";

			}

		}

	}

	else

	{

		this.removeClassName(panel, this.openClass);

		this.addClassName(panel, this.closedClass);
 

		if (content)

		{

			content.style.height = "0px";

			content.style.display = "none";

		}

	}

	

	this.attachPanelHandlers(panel);

};
 

Spry.Widget.Accordion.prototype.attachBehaviors = function()

{

	var panels = this.getPanels();

	for (var i = 0; i < panels.length; i++)

		this.initPanel(panels[i], i == this.defaultPanel);
 

	// Advanced keyboard navigation requires the tabindex attribute

	// on the top-level element.
 

	this.enableKeyboardNavigation = (this.enableKeyboardNavigation && this.element.attributes.getNamedItem("tabindex"));

	if (this.enableKeyboardNavigation)

	{

		var self = this;

		Spry.Widget.Accordion.addEventListener(this.element, "focus", function(e) { return self.onFocus(e); }, false);

		Spry.Widget.Accordion.addEventListener(this.element, "blur", function(e) { return self.onBlur(e); }, false);

		Spry.Widget.Accordion.addEventListener(this.element, "keydown", function(e) { return self.onKeyDown(e); }, false);

	}

};
 

Spry.Widget.Accordion.prototype.getPanels = function()

{

	return this.getElementChildren(this.element);

};
 

Spry.Widget.Accordion.prototype.getCurrentPanel = function()

{

	return this.currentPanel;

};
 

Spry.Widget.Accordion.prototype.getPanelIndex = function(panel)

{

	var panels = this.getPanels();

	for( var i = 0 ; i < panels.length; i++ )

	{

		if( panel == panels[i] )

			return i;

	}

	return -1;

};
 

Spry.Widget.Accordion.prototype.getCurrentPanelIndex = function()

{

	return this.getPanelIndex(this.currentPanel);

};
 

Spry.Widget.Accordion.prototype.getPanelTab = function(panel)

{

	if (!panel)

		return null;

	return this.getElementChildren(panel)[0];

};
 

Spry.Widget.Accordion.prototype.getPanelContent = function(panel)

{

	if (!panel)

		return null;

	return this.getElementChildren(panel)[1];

};
 

Spry.Widget.Accordion.prototype.getElementChildren = function(element)

{

	var children = [];

	var child = element.firstChild;

	while (child)

	{

		if (child.nodeType == 1 /* Node.ELEMENT_NODE */)

			children.push(child);

		child = child.nextSibling;

	}

	return children;

};
 

Spry.Widget.Accordion.prototype.focus = function()

{

	if (this.element && this.element.focus)

		this.element.focus();

};
 

Spry.Widget.Accordion.prototype.blur = function()

{

	if (this.element && this.element.blur)

		this.element.blur();

};
 

/////////////////////////////////////////////////////
 

Spry.Widget.Accordion.PanelAnimator = function(accordion, panel, opts)

{

	this.timer = null;

	this.interval = 0;
 

	this.fps = 60;

	this.duration = 500;

	this.startTime = 0;
 

	this.transition = Spry.Widget.Accordion.PanelAnimator.defaultTransition;
 

	this.onComplete = null;
 

	this.panel = panel;

	this.panelToOpen = accordion.getElement(panel);

	this.panelData = [];

	this.useFixedPanelHeights = accordion.useFixedPanelHeights;
 

	Spry.Widget.Accordion.setOptions(this, opts, true);
 

	this.interval = Math.floor(1000 / this.fps);
 

	// Set up the array of panels we want to animate.
 

	var panels = accordion.getPanels();

	for (var i = 0; i < panels.length; i++)

	{

		var p = panels[i];

		var c = accordion.getPanelContent(p);

		if (c)

		{

			var h = c.offsetHeight;

			if (h == undefined)

				h = 0;
 

			if (p == panel && h == 0)

				c.style.display = "block";
 

			if (p == panel || h > 0)

			{

				var obj = new Object;

				obj.panel = p;

				obj.content = c;

				obj.fromHeight = h;

				obj.toHeight = (p == panel) ? (accordion.useFixedPanelHeights ? accordion.fixedPanelHeight : c.scrollHeight) : 0;

				obj.distance = obj.toHeight - obj.fromHeight;

				obj.overflow = c.style.overflow;

				this.panelData.push(obj);
 

				c.style.overflow = "hidden";

				c.style.height = h + "px";

			}

		}

	}

};
 

Spry.Widget.Accordion.PanelAnimator.defaultTransition = function(time, begin, finish, duration) { time /= duration; return begin + ((2 - time) * time * finish); };
 

Spry.Widget.Accordion.PanelAnimator.prototype.start = function()

{

	var self = this;

	this.startTime = (new Date).getTime();

	this.timer = setTimeout(function() { self.stepAnimation(); }, this.interval);

};
 

Spry.Widget.Accordion.PanelAnimator.prototype.stop = function()

{

	if (this.timer)

	{

		clearTimeout(this.timer);
 

		// If we're killing the timer, restore the overflow

		// properties on the panels we were animating!
 

		for (i = 0; i < this.panelData.length; i++)

		{

			obj = this.panelData[i];

			obj.content.style.overflow = obj.overflow;

		}

	}
 

	this.timer = null;

};
 

Spry.Widget.Accordion.PanelAnimator.prototype.stepAnimation = function()

{

	var curTime = (new Date).getTime();

	var elapsedTime = curTime - this.startTime;
 

	var i, obj;
 

	if (elapsedTime >= this.duration)

	{

		for (i = 0; i < this.panelData.length; i++)

		{

			obj = this.panelData[i];

			if (obj.panel != this.panel)

			{

				obj.content.style.display = "none";

				obj.content.style.height = "0px";

			}

			obj.content.style.overflow = obj.overflow;

			obj.content.style.height = (this.useFixedPanelHeights || obj.toHeight == 0) ? obj.toHeight + "px" : "auto";

		}

		if (this.onComplete)

			this.onComplete();

		return;

	}
 

	for (i = 0; i < this.panelData.length; i++)

	{

		obj = this.panelData[i];

		var ht = this.transition(elapsedTime, obj.fromHeight, obj.distance, this.duration);

		obj.content.style.height = ((ht < 0) ? 0 : ht) + "px";

	}

	

	var self = this;

	this.timer = setTimeout(function() { self.stepAnimation(); }, this.interval);

};

Open in new window

0
Comment
Question by:tprofits
  • 3
  • 2
7 Comments
 
LVL 70

Expert Comment

by:Jason C. Levine
ID: 22699942
>> My goal is to get the links to work.  When the links are clicked the accordion should neither expand or collapse.

Why use the Accordion construct, then?  As you saw in the other question, the javascript that controls the Accordion behavior is disabling links in the control area.  Rolling the code back from 1.6.1 to 1.4 helped the issue but did not solve it completely.

But you don't want the Accordion to even open, don't use Spry for this at all.  Just create a look-alike region using CSS and things will work as intended.
0
 

Author Comment

by:tprofits
ID: 22701684
I created some confusion, sorry.  

I use the accordion functionality.  The accordion expands/collapses whenever the user clicks anywhere on the tab EXCEPT the links.
0
 
LVL 70

Expert Comment

by:Jason C. Levine
ID: 22706384
Okay, got it.

Unfortunately, my answer is still somewhat the same.  The behavior of the Spry Accordion is not easy to alter.  You can roll the javascript file back to version 1.4 but that may introduce a compatibility problem with IE based on what the other asker experienced.

In all honesty, your best bet is to use a different AJAX library that is written in a more flexible manner instead of trying to reinvent the wheel in Spry.
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

Author Comment

by:tprofits
ID: 22706596
It stinks that the entire tab has to be active.  If I could just reduce the size of "clickable" portion of the tab (say to width=30px ), while maintaining the overall size of the tab (width=700px), that would work nicely.  I can't seem to make that happen using CSS.  Is this possible?
0
 
LVL 70

Expert Comment

by:Jason C. Levine
ID: 22728124
Not with the CSS, because that's being done via Javascript.  An onclick event is being added to the <li>...the CSS just formats the <li> to look like a tab.

Again, modifying the core javascript of an AJAX library is not trivial to the point where you are better off spending the time looking for an AJAX library that does what you want.
0
 

Accepted Solution

by:
ee_auto earned 0 total points
ID: 24419580
Question PAQ'd, 500 points refunded, and stored in the solution database.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

This article shows how to create and access 2-dimensional arrays in JavaScript.  It includes a tutorial in case you are just trying to "get your head wrapped around" the concept and we'll also look at some useful tips for more advanced programmers. …
I still run into .cgi files every now and then. In some instances, I actually prefer the simplicity of a .cgi script to other options. Since I use DreamWeaver extensively, what I needed was a way to open .cgi scripts in Dreamweaver. And I wanted 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…

706 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

20 Experts available now in Live!

Get 1:1 Help Now