samsono / Easy-Responsive-Tabs-to-Accordion

Easy responsive tabs - is a lightweight jQuery plugin which optimizes normal horizontal or vertical tabs to accordion on multi devices like: web, tablets, Mobile (IPad & IPhone). This plugin adapts the screen size and changes its action accordingly.
Other
603 stars 259 forks source link

Not really an issue - scroll to the beginning of the tab on accordion? #34

Open jaygao79 opened 10 years ago

jaygao79 commented 10 years ago

On a mobile, when it turns into accordion, if I am reading a long text on tab 1, at the end of it, I tap on tab 2, then tab 2 opens, but I will be looking at the bottom of tab 2, rather than automatically scrolling up to the beginning of tab 2.

I know this is not an issue, but would be great if it does this. Without this, after tapping on tab 2, I would have to scroll up to the beginning of tab 2 to continue reading.

Any ideas? Thanks for your help.

ghost commented 10 years ago

Oh my! I never tested that! Thank you for finding it! Another opportunity for being Sherlock! That's a great question!

jaygao79 commented 10 years ago

@suenotsuan Thank you for looking into this!

jaygao79 commented 10 years ago

@suenotsuan Not to be a pain or something, just wondered if you had any time to look at this?

ghost commented 10 years ago

This is on my bug list but they have me doing more development with debugging at the end. I'll try to look into it today!

jlcallalle commented 10 years ago

Why, when I click on the tab up the scroll in Easy Responsive Tabs to Accordion maquetadoresperu.com/clientes/sunwork/actual/producto1.html

How I can solve it email: jlcallalle@gmail.com twitter: jlcallalle

thanks

jlcallalle commented 10 years ago

This is the web that the problem tab http://maquetadoresperu.com/clientes/sunwork/actual/producto1.html

ghost commented 10 years ago

Finally figured it out! Add this:

$('body').scrollTop(0);

here:

            //Tab Click action function
            $respTabs.find("[role=tab]").each(function () {

                var $currentTab = $(this);
                $currentTab.click(function () {

                    var $currentTab = $(this);
                    var $tabAria = $currentTab.attr('aria-controls');
        $('body').scrollTop(0);

Sorry it took so long jaygao79!

jaygao79 commented 10 years ago

Thank you @suenotsuan it is the idea. Thank you for taking the time to help me as well.

The problem with this solution is that it always scroll to the top of the page. It is fine if the tabs/accordions are at the top of the page, but when I have it lower in the content, or when I have 2 sets of tabs/accordions, it became a problem. The ideal would be for it to scroll to the div id position. For example, I have one horizontal and one vertical on the page, with div id="horizontal-tab", and div id="vertical-tab". Is it at all possible to set the scroll up position to be a variable which equals to the div id to which the clicked tab belongs, instead of a fixed position such as 0 or 100px from the top?

Do you think this is at all possible? Once again thanks for your time.

jaygao79 commented 10 years ago

hi @suenotsuan, I realise that you are probably very busy at the moment. I have tried to work something out based on your solution, but because I am completely useless when it comes to javascript, I can't get it to work. I do think however that the position it should scroll to is the position of the <li id of the tab that I click on. We should be able to get the id from the

  • as tab-1 and append a # to the front, and set that to be the position it should scroll to. I hope this helps.

  • jaygao79 commented 10 years ago

    Hi @suenotsuan I have managed to figure it out with one tab on the page, although it is not perfect. Because the scrolling should only take place when I click on a tab that's not currently active, the code should be inserted in one of the if conditions. Since I also needed a bit of animation, my code looks like this: if (!$currentTab.hasClass('resp-tab-active') && $currentTab.hasClass('resp-accordion')) { $respTabs.find('.resp-tab-active').removeClass('resp-tab-active'); $respTabs.find('.resp-tab-content-active').slideUp().removeClass('resp-tab-content-active resp-accordion-closed'); $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');

                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').slideDown().addClass('resp-tab-content-active');
                            $('html, body').animate({scrollTop: $("#horizontalTab").offset().top}, 1000);

    I used the id of the tab (#horizontalTab) as the position anchor, which is not ideal. Ideally, it should use the new resp-tab-active class as the anchor but for some reason that doesn't work.

    ghost commented 10 years ago

    Your code is very similar to what I came up with yesterday. Mine isn't perfect, as there's still a bit of jumpiness to it, but this is what I came up with.

    I just needed this action for tabs that are in the accordion mode, my accordion div being C13 and the tabs themselves h2. I didn't want the top tab to do anything.

    $(function() { $('#C13 h2:not(:first)').bind('click',function(){ var self = this; setTimeout(function() { theOffset = $(self).offset(); $('body,html').animate({ scrollTop: theOffset.top - 100 }); }, 310); }); });

    And then, in the Easy Responsive Tabs.js I added a css call to hide overflow in the click function:

                        if (!$currentTab.hasClass('resp-tab-active') && $currentTab.hasClass('resp-accordion')) {
                            $respTabs.find('.resp-tab-active').removeClass('resp-tab-active');
                            $respTabs.find('.resp-tab-content-active').slideUp().removeClass('resp-tab-content-active resp-accordion-closed');
                            $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');
                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').slideDown().addClass('resp-tab-content-active').attr('style', 'overflow:hidden');
    
                        }

    Maybe if we combined our code we'd have a perfect answer. I'm still going to try to make it better.

    Thanks for sharing jaygao79!

    jaygao79 commented 10 years ago

    @suenotsuan thanks and mine is barely a solution to be honest. I think your code would probably work perfectly to my requirement. Can I just ask where should I put the bit below on the page, as I assume it doesn't go into easyresponsivetabs.js? $(function() { $('#C13 h2:not(:first)').bind('click',function(){ var self = this; setTimeout(function() { theOffset = $(self).offset(); $('body,html').animate({ scrollTop: theOffset.top - 100 }); }, 310); }); });

    ghost commented 10 years ago

    It can go on your HTML page or it can go on a separate script page. I usually keep a utilities.js page with all of my little scripting pieces such as this. That's what I did with this piece.

    remekdebski commented 10 years ago

    Hi everyone.

    I'm having trouble implementing this bug fix.

    I've tried modifying the .js file with the new if statement. I tried in different places and got different behaviour.

    One version made it that the accordian would open then close another version made the scroll really slow.

    It seems i don't know what i'm doing.

    I really like these tabs/accordian - it's perfect as the solution i'm trying. But i can't get top scroll part right.

    remekdebski commented 10 years ago

    So i stared and stared at the code.

    Was i meant to REPLACE one of the if statements? Because I did and I does seem to work. Still testing.

    mundgold commented 9 years ago

    thats my solution:

    inside easyresponsivetabs.js: $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').slideDown('fast',function () { if (!$currentTab.isOnScreen()) { $('body,html').scrollTop($currentTab.offset().top); } }).addClass('resp-tab-content-active');

    and outside: thanks to: http://upshots.org/javascript/jquery-test-if-element-is-in-viewport-visible-on-screen (function ($) { $.fn.isOnScreen = function(){ var viewport = {}; viewport.top = $(window).scrollTop(); viewport.bottom = viewport.top + $(window).height(); var bounds = {}; bounds.top = this.offset().top; bounds.bottom = bounds.top + this.outerHeight(); return ((bounds.top <= viewport.bottom) && (bounds.bottom >= viewport.top)); }; })(jQuery);

    chadkouse commented 9 years ago

    This seems to be the best solution I could come up with.. using the activate option:

    $('#yourTabContainer').easyResponsiveTabs({
        type: 'vertical',
        activate: function() {
             setTimeout(function() {
                 $('.resp-accordion.resp-tab-active')[0].scrollIntoView();
             }, 500);
         }
    });
    korthjp17 commented 9 years ago

    Another possible solution would be to have it close the current active panel first, then have the panel you clicked on slide down:

    if (!$currentTab.hasClass('resp-tab-active') && $currentTab.hasClass('resp-accordion')) { $respTabs.find('.resp-tab-active').removeClass('resp-tab-active'); $respTabs.find('.resp-tab-content-active').slideUp('', function() { $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').slideDown().addClass('resp-tab-content-active') }).removeClass('resp-tab-content-active resp-accordion-closed'); $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active'); }

    JustinCAZ commented 9 years ago

    I still can't get one particular tab in accordion to open and the focus remain on that tab. It's especially bad if a prior tab's contents are large and you open the next one. the previous one closes, and the screen jumps and focus is completely lost.

    bc1970 commented 8 years ago

    This seems to be a workable solution:

    In the HTML, add a DIV with id "tab1" above the start of the tab content, so:

    <div id="tab1"></div>
    <div id="parentHorizontalTab">

    Then modify easyresponsiveTabs.js with:

    $('html, body').animate({scrollTop:$('#tab1').position().top}, 'slow');

    I know virtually nothing about javascript, so didn't know where to add this, but I put it in the same place as @suenotsuan suggested for the scrollTop solution described above, which seems to work:

                //Tab Click action function
                $respTabs.find("[role=tab]").each(function () {
    
                    var $currentTab = $(this);
                    $currentTab.click(function () {
    
                        var $currentTab = $(this);
                        var $tabAria = $currentTab.attr('aria-controls');
    
                        if ($currentTab.hasClass('resp-accordion')) {
                        $('html, body').animate({scrollTop:$('#tab1').position().top}, 'slow')
                        };

    I wrapped it inside an "if" statement so that it would only apply when in accordion mode - not sure if I've targeted/formed the "if" correctly?

    The idea I got from:

    http://stackoverflow.com/questions/4565381/scrolltop-jquery-scrolling-to-div-with-id

    The page then scrolls to the top of the content whenever a new accordion is opened. It's not perfect (I would prefer that it scrolled to the top of the active accordion), but seems a lot more usable than scrolling all the way to the top of the page as described above and, as long as there are not a huge number of tabs in the list, seems to be quite usable even on very small screens.

    If someone can suggest a better place to add the code in the easyresponsiveTabs.js or how to modify it for to replace #tab1 with an identifier for the active accordion, or if my "if" statement could be better expressed, that would be great! This solution was found just by trial and error searching. But it does seem to be an improvement.

    brianyerkes commented 8 years ago

    @chadkouse Worked perfectly. Awesome solution, thanks for posting