I have an accordion set up to handle registration. I am wanting to validate the data entered on each panel when the user clicks on a different panel tab. I have a continue button on each panel, and am able to validate to my heart's content when the user uses that to go to the next panel.

My problem is that they can also click independently on the accordion tabs (and I want them to be able to skip around for editing purposes), but I would like to validate on those events too.

I've done a bunch of searching, but have not found a satisfactory answer. I am fairly new to Javascript and super-brand-new to jQuery, so please, if you have code snippets for me, be thorough in explaining them.

This should be a straightforward problem (similar to on-click, etc.). I'm quite surprised and frustrated that I haven't found an answer yet.

Edit:
Eric, I couldn't get this to work. Here is my version. I put it in the head section. I have some test code in there that has worked reliably for me in the past (changing the label on one of the tabs). I'm assuming this code has worked for you? Anyway, thanks for your help and I hope we've understood each other sufficiently.

// add capability to detect when accordion tab has been clicked

RegFormAccordion.addEventListener('click', function(e){
    var btnElement;

    (function findAccordionButton(el){

        //e.target is the original element actually clicked on
        //the event bubbles up to ancestor/parent nodes which is why you can listen at
        //the container

        if(!btnElement){ btnElement = e.target; }
        else { btnElement = el; }

        if(e.target.className !== 'accordionBtn')
        {
            findAccordionButton(btnElement.parentNode);
        }
        else
    {
        var curr_panel_index = RegFormAccordion.getCurrentPanelIndex();

            document.getElementById("verify-reg-panel-label").innerHTML = "Index = " + curr_panel_index; // test code to see if it's even getting here

        if (curr_panel_index == 1) // contact section
            {
        ValidateContact();
        }
        else if (curr_panel_index == 2) // payment section
        {
        ValidatePayment();
        }
        UpdateVerifyPanel(); // update contents of verification panel
    }
    })()

} );
2

There are 2 best solutions below

0
On

OK. I found the function that SpryAccordion.js uses to open a new panel and added my own code. Simple and elegant. It's not what I would normally do (usually I leave "libraries" alone). But if you make it editable without giving me another way to take needed control, then the hack is gonna happen.

If I need to use another accordion somewhere else on my website, I will have to double check that I have the correct accordion before invoking the hack. A trade-off I'm willing to make. It works perfectly now. Here is the code:

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;

// Start Becca's code
var panelIndex = this.getPanelIndex(panelA);
if (panelIndex == 1) // contact info panel
{
   if (ValidateContact())
      UpdateVerifyPanel();
       else
      return null;
}
else if (panelIndex == 2) // payment info panel
{
   if (ValidatePayment())
      UpdateVerifyPanel();
   else
      return null;
}
// End Becca's code

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

... ... ...

};

Yes, all I wanted was the same control over the panel tabs as I have over my own user-defined buttons, to make sure I could both validate before moving on, and to update my verification screen after any edit the user makes, not just the ones where they happen to hit my continue button. I'm a happy camper. So glad I took a couple of days off.

I hope this helps someone get more control over their own accordions. So glad I don't have to do a crash-course on jQuery when all I want right now is to get my blasted website up.

3
On

Event delegation.

someAccordianContainer.addEventListener('click', function(e){
    var btnElement;

    (function findAccordionButton(el){

        //e.target is the original element actually clicked on
        //the event bubbles up to ancestor/parent nodes which is why you can listen at
        //the container

        if(!btnElement){ btnElement = e.target; }
        else { btnElement = el; }

        if(e.target.className !== 'accordionBtn'){
            findAccordionButton(btnElement.parentNode);
        }
        else { doSomething(btnElement); }
    })()

} );

You will have to normalize for IE<=8 however if you're supporting older browsers, since it uses a proprietary attachEvent method. Hit quirksmode.org for the details or just use something like jQuery or MooTools.