0

I have an horizontal accordion that I'd like to unfold and then fold again, on page load, to "invite" the user to hover the elements.

I'm using the very cool Kwicks for jQuery, but unfortunately there's no options for something like this, and after a couple of hours of trial and error I'd like to ask for help.

Here I set up a test, out of the box: http://paragraphe.org/accordion/accordion-slider.html

And, for a quick look, here's the script:

/*
    Kwicks for jQuery (version 1.5.1)
    Copyright (c) 2008 Jeremy Martin
    http://www.jeremymartin.name/projects.php?project=kwicks

    Licensed under the MIT license:
        http://www.opensource.org/licenses/mit-license.php

    Any and all use of this script must be accompanied by this copyright/license notice in its present form.
*/

(function($){
    $.fn.kwicks = function(options) {
        var defaults = {
            isVertical: false,
            sticky: false,
            defaultKwick: 0,
            event: 'mouseover',
            spacing: 0,
            duration: 500
        };
        var o = $.extend(defaults, options);
        var WoH = (o.isVertical ? 'height' : 'width'); // WoH = Width or Height
        var LoT = (o.isVertical ? 'top' : 'left'); // LoT = Left or Top

        return this.each(function() {
            container = $(this);
            var kwicks = container.children('li');
            var normWoH = kwicks.eq(0).css(WoH).replace(/px/,''); // normWoH = Normal Width or Height
            if(!o.max) {
                o.max = (normWoH * kwicks.size()) - (o.min * (kwicks.size() - 1));
            } else {
                o.min = ((normWoH * kwicks.size()) - o.max) / (kwicks.size() - 1);
            }
            // set width of container ul
            if(o.isVertical) {
                container.css({
                    width : kwicks.eq(0).css('width'),
                    height : (normWoH * kwicks.size()) + (o.spacing * (kwicks.size() - 1)) + 'px'
                });             
            } else {
                container.css({
                    width : (normWoH * kwicks.size()) + (o.spacing * (kwicks.size() - 1)) + 'px',
                    height : kwicks.eq(0).css('height')
                });             
            }

            // pre calculate left or top values for all kwicks but the first and last
            // i = index of currently hovered kwick, j = index of kwick we're calculating
            var preCalcLoTs = []; // preCalcLoTs = pre-calculated Left or Top's
            for(i = 0; i < kwicks.size(); i++) {
                preCalcLoTs[i] = [];
                // don't need to calculate values for first or last kwick
                for(j = 1; j < kwicks.size() - 1; j++) {
                    if(i == j) {
                        preCalcLoTs[i][j] = o.isVertical ? j * o.min + (j * o.spacing) : j * o.min + (j * o.spacing);
                    } else {
                        preCalcLoTs[i][j] = (j <= i ? (j * o.min) : (j-1) * o.min + o.max) + (j * o.spacing);
                    }
                }
            }

            // loop through all kwick elements
            kwicks.each(function(i) {
                var kwick = $(this);
                // set initial width or height and left or top values
                // set first kwick
                if(i === 0) {
                    kwick.css(LoT, '0px');
                } 
                // set last kwick
                else if(i == kwicks.size() - 1) {
                    kwick.css(o.isVertical ? 'bottom' : 'right', '0px');
                }
                // set all other kwicks
                else {
                    if(o.sticky) {
                        kwick.css(LoT, preCalcLoTs[o.defaultKwick][i]);
                    } else {
                        kwick.css(LoT, (i * normWoH) + (i * o.spacing));
                    }
                }
                // correct size in sticky mode
                if(o.sticky) {
                    if(o.defaultKwick == i) {
                        kwick.css(WoH, o.max + 'px');
                        kwick.addClass('active');
                    } else {
                        kwick.css(WoH, o.min + 'px');
                    }
                }
                kwick.css({
                    margin: 0,
                    position: 'absolute'
                });

                kwick.bind(o.event, function() {
                    // calculate previous width or heights and left or top values
                    var prevWoHs = []; // prevWoHs = previous Widths or Heights
                    var prevLoTs = []; // prevLoTs = previous Left or Tops
                    kwicks.stop().removeClass('active');
                    for(j = 0; j < kwicks.size(); j++) {
                        prevWoHs[j] = kwicks.eq(j).css(WoH).replace(/px/, '');
                        prevLoTs[j] = kwicks.eq(j).css(LoT).replace(/px/, '');
                    }
                    var aniObj = {};
                    aniObj[WoH] = o.max;
                    var maxDif = o.max - prevWoHs[i];
                    var prevWoHsMaxDifRatio = prevWoHs[i]/maxDif;
                    kwick.addClass('active').animate(aniObj, {
                        step: function(now) {
                            // calculate animation completeness as percentage
                            var percentage = maxDif != 0 ? now/maxDif - prevWoHsMaxDifRatio : 1;
                            // adjsut other elements based on percentage
                            kwicks.each(function(j) {
                                if(j != i) {
                                    kwicks.eq(j).css(WoH, prevWoHs[j] - ((prevWoHs[j] - o.min) * percentage) + 'px');
                                }
                                if(j > 0 && j < kwicks.size() - 1) { // if not the first or last kwick
                                    kwicks.eq(j).css(LoT, prevLoTs[j] - ((prevLoTs[j] - preCalcLoTs[i][j]) * percentage) + 'px');
                                }
                            });
                        },
                        duration: o.duration,
                        easing: o.easing
                    });
                });
            });
            if(!o.sticky) {
                container.bind("mouseleave", function() {
                    var prevWoHs = [];
                    var prevLoTs = [];
                    kwicks.removeClass('active').stop();
                    for(i = 0; i < kwicks.size(); i++) {
                        prevWoHs[i] = kwicks.eq(i).css(WoH).replace(/px/, '');
                        prevLoTs[i] = kwicks.eq(i).css(LoT).replace(/px/, '');
                    }
                    var aniObj = {};
                    aniObj[WoH] = normWoH;
                    var normDif = normWoH - prevWoHs[0];
                    kwicks.eq(0).animate(aniObj, {
                        step: function(now) {
                            var percentage = normDif != 0 ? (now - prevWoHs[0])/normDif : 1;
                            for(i = 1; i < kwicks.size(); i++) {
                                kwicks.eq(i).css(WoH, prevWoHs[i] - ((prevWoHs[i] - normWoH) * percentage) + 'px');
                                if(i < kwicks.size() - 1) {
                                    kwicks.eq(i).css(LoT, prevLoTs[i] - ((prevLoTs[i] - ((i * normWoH) + (i * o.spacing))) * percentage) + 'px');
                                }
                            }
                        },
                        duration: o.duration,
                        easing: o.easing
                    });
                });
            }
        });
    };
})(jQuery);

Would you know of some addition to allow an initial deployment / collapse to defaults?

Many thanks for your suggestions,

Peanuts
  • 2,641
  • 6
  • 29
  • 34

3 Answers3

1

You can simulate several clicks on the accordeon...

ChristopheCVB
  • 7,269
  • 1
  • 29
  • 54
  • this approach seems the pretty cool, but I wouldn't have an idea of the code I should use for that.. – Peanuts Jul 25 '11 at 19:35
1
$("ul#accordion-slider li.d").mouseover()
Joseph Marikle
  • 76,418
  • 17
  • 112
  • 129
  • super! how did you figured it out!? Is there a way to reverse the move after it finishes? – Peanuts Jul 25 '11 at 19:37
  • reverse to what in particular? – Joseph Marikle Jul 25 '11 at 19:38
  • also (though it's entirely unrelated) you could even make this into a slideshow with the following code: var state = 97; var cycleImages = setInterval(function(){if (state == 100) state = 97; else state++; $("ul#accordion-slider li."+String.fromCharCode(state)).mouseover()},5000) – Joseph Marikle Jul 25 '11 at 19:40
  • reverse so the first slice gets expanded at the end of the animation – Peanuts Jul 25 '11 at 19:44
  • you can just use '$("ul#accordion-slider li.a").mouseover()'. The only thing that is changing is the "li.a". a (the li element's class) corresponds to the first one, b to the second, c to the third, and d to the fourth. – Joseph Marikle Jul 25 '11 at 19:47
  • awesome, should I do this with a 'callback' right? Something like: $("ul#accordion-slider li.d").mouseover(function () { $("ul#accordion-slider li.a").mouseover(); }); – Peanuts Jul 25 '11 at 19:50
  • unfortunately that will set the mouseover function for that panel and break the code. (jquery allows you to set [e.g. $(this).id("blah")] or get [e.g. $(this).id()]. by leaving mousover() empty, we are "getting" or calling it). I would say set a timeout. something like the following: $("ul#accordion-slider li.d").mouseover(); setTimout(function(){$("ul#accordion-slider li.a")},1000); That would cause it to change to the last frame, wait 1 second (1000ms), and then change back to frame 1. – Joseph Marikle Jul 25 '11 at 19:55
1

I needed something similar and i did it with a short jQuery function :

function kwicksSlide(){$("#slider li:first").addClass('first');$("#slider li:last").addClass('last');var currentSlide=$("#slider .active");var nextSlide=$("#slider .active").next();(!currentSlide.is('.last'))?$(nextSlide).trigger('mouseover'):$("#slider .first").trigger('mouseover');}

Where #slider is your ul id.

Then you could use it with :

$(document).ready(function(){ setInterval(kwicksSlide,3000) });

Where 3000 is the time between each animation... You should add some conditions on user's mouseover to stop the current function otherwise the timer won't be stopped.

I'm sure there must be simpler solutions but this works great.

Codzeen
  • 11
  • 1