开发者

Multiple functions and callbacks in a custom jquery plugin?

Okay I'm not sure if I'm going about this in the right way or not, but here goes...

I'm writing a custom jQuery plugin to provide drop menu functionality with animation (and as a learning exercise so please no "Why not just use superduperwonderplugin-x").

I want to be able to animate the menu in different ways depending on user options (i.e fade, slide, drop etc.). At the moment each different animation is handled by a separate function within the plugin file but I'm not sure how to handle the callback functions (passing this back)!

-- i.e. The animation is only happening on the last element in the object's stack.

Here's my code:

/**
 * Grizzly's Menuifier
 * 
 * @author  Chris.Leaper
 * @version a1.0
 */
(function($){
    $.fn.gmenu = function(options) {

        /* Transitions:
            - fade >> fadeIn / fadeOut
            - slide >> slideDown / slideUp
            - drop >> (different to above?)
            - bounce >> (custom config transition=? and easing=bounce)
            - stretch >> (custom config transition=? and easing=elastic)
            - fold >> (custom) drop menu @ half width then 'fold' out to full menu width
        */

        // Set the plugin default options:
        var defaults = {
            levels: '1',
            fit: 'auto',
            easing: 'linear',
            transition: 'slide',
            speed: 500
        };

        options = $.extend(defaults, options); // Merge the user options with the plugin defaults

        return this.each(function() {
            var $this = $(this);
            var opt = options;
            var container;
            var ul;

            // Setup the container elements (parent DIV/NAV and UL)!
            if( $this.is('ul') ) container = $(this).parent();
            else container = $(this);

            console.log('Container: ' + container.get(0).tagName + ' id=#' + container.attr('id') + ' class=' + container.attr('class'));

            ul = container.children('ul:first-child');

            console.log('UL: ' + ul);

            // Set the UL's position to relative:
            if($(ul).css('position') != 'relative') $(ul).css('pos开发者_如何学运维ition', 'relative');

            var offset;
            var menus = ul.children('li:has(ul)');

            console.log('List Item: ' + menus);

            menus.each(function(index, menu) {
                $menu = $(menu);

                console.log('Menu: ' + $menu);

                // Set the menu LI's position to relative (contains the absolutely positioned child UL!)
                if($menu.css('position') != 'relative') $menu.css('position', 'relative');

                // Get the menu LI's position relative to the document (it's offset)
                // -- This is only needed when positioning non-child elements
                // (i.e. ID linked menu>submenu relationships as may be used for a separated DIV based menu!!)
//              offset = menu.offest();

                // Position the submenu according to it's parent
                var submenu = $menu.children('ul');

                console.log('Submenu: ' + submenu.get(0).tagName + ' id=#' + submenu.attr('id') + ' class=' + submenu.attr('class'));

                setPosition(submenu, $menu.height());

                switch(opt.transition) {
                    case 'bounce':
                        setSMBounce(menu, opt);
                        break;
                    case 'fade':
                        setSMFade(menu, opt);
                        break;
                    case 'fold':
                        setSMFold(menu, opt);
                        break;
                    case 'stretch':
                        setSMStretch(menu, opt);
                        break;
                    case 'slide':
                    default:
                        menu = setSMSlide(menu, opt);
                }
            });

            debug(this);
        });
    };
})(jQuery);

function setPosition(submenu, height) {
    $(submenu).css({
        left: 0,
        position: 'absolute',
        top: height
    }).hide();
}

function setSMSlide(menu, opt) {
    $menu = $(menu);

    console.log('SM Slide: ' + $menu.get(0));

    $menu.first('a').mouseenter(function() {
        console.log('Start SlideDown');
        $menu.stop(true, true).slideDown(opt.speed, opt.easing);
        console.log('Stop SlideDown');
    });

    $menu.first('a').mouseleave(function() {
        console.log('Start SlideUp');
        $menu.stop(true, true).slideUp(opt.speed, opt.easing);
        console.log('Stop SlideUp');
    });
}

I think that I should be using a (same) namespace based approach to defining my separate functions (object literal or something?) but I wasn't sure what this meant or how to do it.

Can anyone help me please?


To encapsulate your functions setPosition and setSMSlide (in your example) just define them inside your plugin function (the good place would be after definition of default variable. It would look something like that:

var defaults = {
        levels: '1',
        fit: 'auto',
        easing: 'linear',
        transition: 'slide',
        speed: 500
    },
    setPosition = function(submenu, height) {...},
    setSMSlide = function(menu, opt) {...};

Because of the way the scoping in Javascript works your setPosition and setSMSlide functions will be still accessible from inside of your gmenu declaration.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜