1

I know a lot of people ask questions about plug-ins and callbacks (and I've read lots of them - that's how i got this far) so please, bear with me. I tried my hand at a very simple hide/show accordion type plugin for FAQs and was successful at getting it to do what I wanted. However, as I am still learning, I am not really sure how some things work. I was able to add a callback to the plugin after reading this question and a few others.
My question is: Is this code correct and is there a better way to implement this callback? Here's a working sample and the code below. Thank you for your time.

( function($) {
$.fn.simpleFAQ = function( options, callback ) {
    // define default options
    var defaults = {
        textExpand      : "Expand all",
        textCollapse    : "Collapse all",
        displayAll      : false,
        toggleSpeed     : 250
    };
    var options = $.extend( defaults, options );
    // callback
    if( typeof callback != "function" ) { callback = function(){} }

    this.each( function () {
        obj = $(this);
        // insert FAQ expand all/collapes all text before FAQ
        var txt = '<span class="simple_jfaqText"><a href="javascript:;" rel="jfaq_expand">' + options.textExpand + '</a> / <a href="javascript:;" rel="jfaq_collapse">' + options.textCollapse + '</a></span>';
        $( txt ).insertBefore( obj );

        // add class to desired FAQ element
        obj.addClass( 'simple_jfaq' );

        // show/hide faq answers according to displayAll option
        ( options.displayAll == false ) ? ddDisplay = 'none' : ddDisplay = 'block';
        obj.children( 'dd' ).css( 'display', ddDisplay );


        // add classes according to <dd> state (hidden/visible)
        obj.children( 'dd:visible' ).prev( 'dt' ).addClass( 'expanded' );
        obj.children( 'dd:hidden' ).prev( 'dt' ).addClass( 'collapsed' );

        obj.children( 'dt' )
            .click( function() {
                // show/hide all answers (dd elements) on click
                $(this).nextUntil( 'dt' ).slideToggle( options.toggleSpeed, callback );
                // dt class change on click
                $(this).toggleClass( 'collapsed' ).toggleClass( 'expanded' ); })
            .hover( function() { $(this).toggleClass( 'hover' ); }, function(){ $(this).toggleClass( 'hover' ); });
    });

    // Expand All
    obj.prev( 'span' ).children( 'a[rel=jfaq_expand]' ).click( function() {
        // show all answers
        $(this).parent( 'span' ).next( '.simple_jfaq' ).children( 'dd:hidden' ).slideToggle( options.toggleSpeed );
        setTimeout( callback, options.toggleSpeed )
        // change classes
        $(this).parent( 'span' ).next( '.simple_jfaq' ).children( 'dt' ).removeClass( 'collapsed' ).addClass( 'expanded' );
    });

    // Collapse all
    obj.prev( 'span' ).children( 'a[rel=jfaq_collapse]' ).click( function() {
        // hide all answers
        $(this).parent( 'span' ).next( '.simple_jfaq' ).children( 'dd:visible' ).slideToggle( options.toggleSpeed );
        setTimeout( callback, options.toggleSpeed );
        // change classes
        $(this).parent( 'span' ).next( '.simple_jfaq' ).children( 'dt' ).removeClass( 'expanded' ).addClass( 'collapsed' );
    });
};
})( jQuery );

2 Answers 2

1

I would recommend using jQuery's built in event system for this. You can trigger an event on any node, then the user of the FAQ code could bind to that event on that node. You can even pass data to the binding function.

Of course, my real recommendation is to use my plug-in of the same name. :)

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the reply. I just realized I did see your plugin before I posted mine and linked to it (leo.dolcepixels.com/learning/jquery/simple-faq-jquery-plugin). I was only trying from scratch so I could learn from the beginning. I will take a better look at your code and try again.Thanks
0

It might be nice if the callback would execute in the context of some relevant element.

var clicked = this;
setTimeout(function() { callback.call(clicked); }, options.toggleSpeed );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.