Sunday, July 26, 2009

Using two spry tabbed panels within the same site or page

***LATEST UPDATE*** If you're looking for a simple tabbed panels script, check out my other post about jQuery.

***UPDATED*** This post has been updated - see the "widget inside widget" section for details.


Dreamweaver's Spry Tabbed Panels is one of the most versatile scripts I've worked with. I've been able to implement it with a variety of other scripts with virtually no conflicts. It's even possible to have two or more tabbed panels with different styles in the same website, webpage, or even within each other - here's how.

Within the same website
Each spry tabbed panels widget is referenced in your html:

var TabbedPanels1 = new Spry.Widget.TabbedPanels("divID")

This tells to look for function name "spry.widget.tabbedpanels" in the js script file to determine which css styles to apply. That's why you'll first need two "SpryTabbedPanels.js" files, each referencing the appropriate css styles.

To do this, edit the lines this.tabSelectedClass, this.tabHoverClass, this.tabFocusedClass, this.panelVisibleClass (lines 11-14) to use the class names you want - you should create the css styles first though. Save them separately - for example as 'sprytabbedpanels1.js' and 'sprytabbedpanels2.js' and make sure you reference both files in your <'head'> tag.

Next, to connect each widget to the correct css styles, change the name in the html reference - for example to something like:
var TabbedPanels1 = new Spry.Widget.Panels("divID")

Then open the 'sprytabbedpanels.js' file that references the css classes that you want associated with the widget instance that you just changed, and replace all spry.widget.tabbedpanels with the new name - in this case Spry.Widget.Panels. This is a basic find-replace; nothing more. The name doesn't really matter, so long as it's consistent.

Quick summary:
1) Each "var TabbedPanels1 ..." line is referencing the same widget name as exist in the js file.
2) Lines 11-14 in each sprytabbedpanels.js file are referencing classes that exist in the stylesheet.
3) Each "var TabbedPanels1 ..." line is referencing the divID in the div that you want the styles to apply.
4) All js and stylesheets are referenced in your head tag of each page.

If you've done all of the above everything should work smoothly. I know it did for me...

Within the same page, separated
This is a bit more complicated but definitely possible. First, to avoid major functionality problems, the "var TabbedPanels1 ..." line should appear immediately after the closing "div" tag of each tabbed panels widget. Otherwise the browser can easily mess up your panels and content. Then follow the instructions above for multiple widgets within the same site and you should be good to go.

Within the same page, widget inside widget
I actually had a case where I had a tabbedpanels widget where each panel's content was another tabbedpanels widget! Here, I used all the techniques mentioned above, and was able to get everything working except for the different class styles to show for "hover" and "selected" states. My trick was to use pictures to overcome this issue, at least for the tabs. Creating images as if for a button, I added the following code - from Dreamweaver's menu bar widget - inside the <'li'> tag to get the tab to change to over state when a user clicks it:

'< onclick="MM_nbGroup('down','group1','button-id','path-to-over-image',state-id)" onmouseover="MM_nbGroup('over','group-id','path-to-over-image','',state-id)" onmouseout="MM_nbGroup('out')">< src="path-to-up-image" alt="" name="button-id" border="0" id="button-id" onload="MM_nbGroup('init','group1','button-id', 'path-to-up-image', '', state-id)">< /a>'

(Remember to remove the spaces when opening tags).

*** UPDATED ***
I just realized that my instructions for spry tabbed panels within spry tabbed panels imply that you should change the function name (spry.widget.tabbedpanels) in the html reference and javascript file. This should be done to achieve different styles as long as the widgets are not within each other. If they are, do not follow this step or your widget will not work! Accordingly, you don't need to change the css class names in the javascript code, either.

To achieve different styles for a widget inside another widget, you can add a new div with a class name defined in your regular stylesheet inside the < 'li > of each tab or < 'div > of each panel. This would work for the up-state only (i.e. until the tab is clicked). If you want the different style to persist when clicked on, use images as described above.

The quickest way to place a widget inside another widget is to open Design view, then choose the tab corresponding to the panel where you want the inner widget to appear, place the cursor inside the panel, and click on the insert widget button.

May seem complicated but easy if you understand how the script works. Anyway, enjoy!

15 comments:

  1. Dear Rubin, i find your article about 'two tabbed panels within same page' most easy-to-follow. but still struggling with find-replace to associate right .js. I have 2 tabbed panels on same page - First and Second. I made 2 css files - First.css and Second.css. I also 'saved as' First.js to make Second.js. Please help: what exsactly I find and replace in the Second.js to make it work with Second.css and Second tabbed panels. Can you send a sample code? I am desperate. Thank you, if you'll be able to help. Natalia

    ReplyDelete
  2. Hi Natalia,

    You need to do three things:
    1) If you want it each tabbed panels widget to look different, then you need to change all the class names in the css file - the names you choose are arbitrary - then match it in the js file.

    For example, the default is:

    .TabbedPanels {
    margin: 0px;
    padding: 0px;
    float: left;
    clear: none;
    width: 100%;
    }

    I might change it to

    .Panels {
    margin: 0px;
    padding: 0px;
    float: left;
    clear: none;
    width: 100%;
    }

    and so forth.

    In the js file, find around line 10 or 11:

    this.tabSelectedClass = "TabbedPanelsTabSelected";
    this.tabHoverClass = "TabbedPanelsTabHover";
    this.tabFocusedClass = "TabbedPanelsTabFocused";
    this.panelVisibleClass = "TabbedPanelsContentVisible";

    You need to change these class names to whatever you changed in the css.

    2) The default basic function for this widget is Spry.Widget.TabbedPanels but you can only have one with this name if you want multiple ones to work. So you need to run a basic find-replace for Spry.Widget.TabbedPanels in the js file, again what you're replacing it with is arbitrary - you can just do Spry.Widget.Panels for example.

    3) In your html file, find something like this:
    var TabbedPanels1 = new Spry.Widget.TabbedPanels("TabbedPanels1")

    Because you changed the function in step 2 in the js file, you need to do it over here as well. Using my example, it would become
    var TabbedPanels1 = new Spry.Widget.Panels("divID")

    That's it! You should be good to go...

    Let me know how it goes.

    ReplyDelete
  3. By the way - I'm assuming you're trying to do two widgets on the same page but separated, not within each other. If you want to do them within each other it's very different...

    ReplyDelete
  4. I was able to follow your direction to create another spry tabbed panel set within my website. However now I am unable to edit the basic properties of the spry (tabbed window, name, etc...). Also the tab contents are no longer stacked behind each other but stacked down the page. I imagine this is a css issue? I'm new at web design, and I know that when I change the name in the html var TabbedPanel1 = new Spry.Widget.NEWNAME("divid"), the text is no longer red? Possibly the issue?

    It previews fine within explorer and firefox, but in dreamweaver it appears stacked and the tabs are unselectable.

    Thanks for you help

    ReplyDelete
  5. Hi Daniel,

    I see the issue... I've never noticed this before because I didn't need to use the properties! I'd recommend that you change the name of the widget back to Spry.Widget.TabbedPanels momentarily, to edit the properties, and then change it back. I've also noticed the fact that when you change the name, the text is no longer orange, however that's internal to Dreamweaver; as you indicated the widget will show up as usual in the browser.

    Good luck!

    ReplyDelete
  6. Hi!
    I'm trying to put 1 tabbed panel into another tabbed panel... and i succeeded thanks to you!

    Now I'm trying to select the tab panel using mouseover.. it succeeded for the outer tabbed panel... So i put the same code for the inner tabbed panel, however, when i mouseover the inner tabbed panel's tabs, the outer tabbed panel container closes =.=||

    this is the code tt i change

    Spry.Widget.Panels.addEventListener(tab, "click", function(e) { return self.onTabClick(e, tab); }, false);

    TO

    Spry.Widget.Panels.addEventListener(tab, "mouseover", function(e) { return self.onTabClick(e, tab); }, false);

    ReplyDelete
  7. Do you have the references of Spry.Widget.Panels named for both panels on the two sets of code?

    I'm not sure that this could be done with onmouseover, since by definition that only works when the mouse is over the tab. You might need to get the onmouseover to apply to the whole tab content area (rather than just the tab itself) to get this to work...

    ReplyDelete
  8. hi, i was wondering if you could check out this link.. i'm trying to have two tabbed panels in one page, the first vertical, the 2nd horizontal. i took the "v" out of the 2nd one, but still is V..

    i thought i followed your instructions above, but they are crossed up.. i made a tabbedpanels2.js & .css

    thanks much

    ReplyDelete
  9. http://meta-morph.com/new/metamorph3.html

    ReplyDelete
  10. If you want the same look, you don't need two JS and CSS files, and two references to tabbedpanels. Just keep one reference and have the V class for one and the regular class for another.

    If you do want different styles, make sure the widget name is different for each - as I describe in the "Within the same website" section above.

    ReplyDelete
  11. hoping you can help me check out one last thing.. i named everything accordingly. i want the 2nd horizontal tabs to have red text on "selected" as do the 1st vertical tabs... but for some reason does not work the way it should.. any ideas?

    http://www.meta-morph.com

    thanks

    ReplyDelete
  12. I appreciate all you help. I was wondering if you could tell me if it is possible to have a panel that is ALWAYS open no matter what other panels might be open/closed. Thanks so much!

    ReplyDelete
  13. Hi Rubin, I need some help. I have succesfully applied one TabbedPanel to my website and tried to apply another one on the same post (blogger) but the second one is not working. Like someone here said: "...the tab contents are no longer stacked behind each other but stacked down the page..." I assume I cant use the same Javascript for both, is that right? How can I run another Javascript for the second TabbedPanel? I tried to insert the same javascript line twice on the head section but it is only taking one. In a few words, with just one widget ir works like a charm, but the second one doesnt work.
    Btw both are with the same CSS :) so no problems with CSS, the problem is Javascript I guess!

    Thanks in advance

    ReplyDelete
    Replies
    1. Nevermind, got it! I just needed to change "id="TabbedPanels1">" to "id="TabbedPanels2">". And then run the script with TabbedPanels2!

      Thanks xD lol

      Delete