How to disable jQuery accordion conditionally
Asked Answered
D

5

9

I want to enable and disable or better to add and remove jQuery accordion on my menu conditionally, is it possible to add or remove this on screen rotate or screen-size change ? I tried it but It does not seems to be working, The accordion is remaining for change in screen-size .

jQuery( document ).ready( function(){
    apply_accordion();
    jQuery(window).on("orientationchange",function(){
        apply_accordion();
    });
} );
function apply_accordion(){
    if (jQuery(window).width() < 540) {
        jQuery('.footer-area').accordion({
            icons: { "header": "icon-large ui-icon-carat-1-s", "activeHeader": "icon-large ui-icon-caret-1-n" },
            active: false,
            autoHeight: false,
            navigation: true,
            collapsible: true,
        });
    } else {
        //jQuery( '.footer-area' ).accordion( "disable" );
        //jQuery( '.footer-area' ).accordion( "destroy" );
        // jQuery( '.footer-area' ).accordion( "refresh" );
        jQuery( '.footer-area' ).accordion( "destroy" ).accordion();
    }
}

update

if else part will be,

} else {
    jQuery( '.footer-area' ).accordion( "destroy" );
    jQuery('.footer-area').accordion('option', 'active', 0);
}

when I starts with moving from portrait to landscape, it is working, but the reverse is not working , means when I am moving from landscape to portrait it is not working . And also gives error in console cannot call methods on accordion prior to initialization; attempted to call method 'destroy'

New jsfield

I would like to remove and add accordion with screen size.

Note:

jQuery version 1.11.4

check Techbreak's answer https://jsfiddle.net/voytfj2q/20/ it seems to be working but if you will check console it will generate " Uncaught Error: cannot call methods on accordion prior to initialization; attempted to call method 'destroy'" . and in actual implementation it does not work when I am moving from landscape to portrait.

And I have also posted an workaround, for now in my implementation it is working for me, but I know this is only a workaround.

Here is another fiddle if you will increase and decrease the screen-size slowly you can notice the issue.

Screenshot of issue, you can notice for few of them the accordion is disabled for increase in size and for some it is not disabled.

enter image description here

Drudge answered 1/12, 2016 at 5:9 Comment(9)
can you add working fiddle link?Ossuary
refer to this #23997226 I believe you are ending up triggering both events.Ossuary
@TechBreak please look at my updated code, I have tried few thngs and now it is only on screensize change, but still not working. can you please suggest something ?Drudge
I have fixed your issue, please refer to following answer. Please accept if really fixes your issue :)Ossuary
@PrafullaKumarSahu: instead of try...catch you can fix the initialization error,: var isInstance = (typeof $(element).data("ui-accordion") != "undefined"); then, if (isInstance) you can destroy, else you can initialize or refresh it. Did you tried this already?Monkhood
@Monkhood here jsfiddle.net/Lgx4es86/2 you can see the problem, if you will increase and decrease the size of the screen "slowly" you will be able to see the problem jsfiddle.net/Lgx4es86/5Drudge
please check the update in question, I have added a screenshot.Drudge
@PrafullaKumarSahu: 2 issues solved here: jsfiddle.net/Lgx4es86/6Monkhood
@Monkhood you should post it as an answer, that will be great, but please add some explanation and compare it with my workaround, as the work around functioning more smoothly than you some how !! I would like to understand why it is a better solution.Drudge
M
4

OK. Actually, you have solved the issue with many different instances of the accordion, which wasn't in evidence from your original post, so the wrong selector .footer-area used here:

      jQuery('.footer-area').accordion({
          active: false, collapsible:true, active:true
      });

has been adjusted.

Issue #1:

As you need to create and destroy the widget based on the page size, we need to check for the existence of every widget instance before calling any method of the accordion, otherwise we will raise the infamous error: ...cannot call methods on *some-widget* prior to initialization.

This issue is solved by checking for the existence of the data which has been appended to the element at widget instance creation:

var isInstance1 = (typeof jQuery('#footer-widget-area-1 .footer-area').data("ui-accordion") != "undefined");

Issue #2:

When you are switching back to the unstyled menu, the page height will increase and the page will show the vertical scrollbar, which is resulting in a different page width. The page is resized again and your check for window.width will behave unstable.

This is the reason why you need to check for jQuery('body').width() + scrollbar_width(). Simply take the provided function to get the scrollbar width as-is, and include it in your snippet lbrary.

Fiddle: https://jsfiddle.net/Lgx4es86/6/

/* Calculates scrollbar width in pixels */
function scrollbar_width() {
    if( jQuery('body').height() > jQuery(window).height()) {

        /* Modified from: http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php */
        var calculation_content = jQuery('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
        jQuery('body').append( calculation_content );
        var width_one = jQuery('div', calculation_content).innerWidth();
        calculation_content.css('overflow-y', 'scroll');
        var width_two = jQuery('div', calculation_content).innerWidth();
        jQuery(calculation_content).remove();
        return ( width_one - width_two );
    }
    return 0;
}

jQuery( document ).ready( function(){
    apply_accordion();
    jQuery(window).resize(function() {
        apply_accordion();
    });
} );
function apply_accordion(){
  var ww = jQuery('body').width() + scrollbar_width();
    if (ww < 540) {
        jQuery('#footer-widget-area-1 .footer-area').accordion({
                active: false, collapsible:true
            });
        jQuery('#footer-widget-area-2 .footer-area').accordion({
                active: false, collapsible:true
            });
        jQuery('#footer-widget-area-3 .footer-area').accordion({
                active: false, collapsible:true
            });
        jQuery('#footer-widget-area-5 .footer-area').accordion({
                active: false, collapsible:true
            });
        jQuery('#footer-widget-area-6 .footer-area').accordion({
                active: false, collapsible:true
            });
        } else {
            var isInstance1 = (typeof jQuery('#footer-widget-area-1 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance1) {
                jQuery('#footer-widget-area-1 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-1 .footer-area').accordion("destroy");
            }
            var isInstance2 = (typeof jQuery('#footer-widget-area-2 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance2) {
                jQuery('#footer-widget-area-2 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-2 .footer-area').accordion("destroy");
            }
            var isInstance3 = (typeof jQuery('#footer-widget-area-3 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance3) {
                jQuery('#footer-widget-area-3 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-3 .footer-area').accordion("destroy");
            }
            var isInstance5 = (typeof jQuery('#footer-widget-area-5 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance5) {
                jQuery('#footer-widget-area-5 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-5 .footer-area').accordion("destroy");
            }
            var isInstance6 = (typeof jQuery('#footer-widget-area-6 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance6) {
                jQuery('#footer-widget-area-6 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-6 .footer-area').accordion("destroy");
            }
        // var isInstance = (typeof jQuery('.footer-area').data("ui-accordion") != "undefined");
        // if (isInstance){
        //  jQuery('.footer-area').accordion('option', 'active', 0);
        //  jQuery('.footer-area').accordion( "destroy" );
        // }
    }
}

Your workaround:

You are applying and removing the accordion styles, but not destroying the widget instances, so data event handlers are still there. You would need at least to move the jQuery('.footer-area').accordion part in another place to execute it just only one time. Moreover, beside this, the page width issue isn't solved by your workaround.

Scrollbar width function: credit Alex Mansfield (http://alexmansfield.com/javascript/css-jquery-screen-widths-scrollbars)

Monkhood answered 14/12, 2016 at 12:7 Comment(0)
O
7

You need to activate the accordian to expand when the size is big enough to expand the content or screen rotated completely as follows,

jQuery(document).ready(function() {

  jQuery(window).on("resize", function() {
      if (jQuery(window).width() < 540) {

          jQuery('.footer-area').accordion({
              active: false, collapsible:true, active:true
          });
      } else {
          //reactivate the accordian so that it can be expanded again
          jQuery('.footer-area').accordion('option', 'active', 0);
      }
   });

Working fiddle for your example : https://jsfiddle.net/voytfj2q/18/ });

Ossuary answered 2/12, 2016 at 7:44 Comment(11)
Thank you for your quick reply TechBreak, but that too not fixing my problem, I added mobile jquery and tested it again. :(Drudge
i have attached working fiddle already check with that what you are missing which is not triggering the event.Ossuary
if you are talking about that alert, in my case also I was getting that but that does not disabled accordion, problem is not that the code is not executing it is about it is not doing the job.Drudge
Even I test with jQuery(window).resize :(Drudge
sorry about that, actually that is sidebar-area while typing here, I have committed a mistake here, but in my code it is footer-area and not working.Drudge
@PrafullaKumarSahu always provide correct and full code. Can not guess and suggest.Ossuary
Let us continue this discussion in chat.Drudge
Have you find any other possible things that can be done on this ? As in last 3/4 days I have not got any improvement to this ? Another issue with it, when first time I am going to a small screen from a large screen( ie. landscape to portrait ) the accordion is not working.Drudge
With jsfiddle.net/voytfj2q/20 it is not keeping the css of earlier state, but here the issue is when I starts with moving from portrait to landscape, it is working, but the reverse is not working , means when I am moving from landscape to portrait it is not working .Drudge
Your code will also gives error "cannot call methods on accordion prior to initialization; attempted to call method 'option'" in console, so even you should not use it .Drudge
Added an work around which is not an edit to your post that is why not updated your answer, still trying to get a correct solution, if I will get a solution which will be an update to your solution, I will definitely update your answer.Drudge
M
4

OK. Actually, you have solved the issue with many different instances of the accordion, which wasn't in evidence from your original post, so the wrong selector .footer-area used here:

      jQuery('.footer-area').accordion({
          active: false, collapsible:true, active:true
      });

has been adjusted.

Issue #1:

As you need to create and destroy the widget based on the page size, we need to check for the existence of every widget instance before calling any method of the accordion, otherwise we will raise the infamous error: ...cannot call methods on *some-widget* prior to initialization.

This issue is solved by checking for the existence of the data which has been appended to the element at widget instance creation:

var isInstance1 = (typeof jQuery('#footer-widget-area-1 .footer-area').data("ui-accordion") != "undefined");

Issue #2:

When you are switching back to the unstyled menu, the page height will increase and the page will show the vertical scrollbar, which is resulting in a different page width. The page is resized again and your check for window.width will behave unstable.

This is the reason why you need to check for jQuery('body').width() + scrollbar_width(). Simply take the provided function to get the scrollbar width as-is, and include it in your snippet lbrary.

Fiddle: https://jsfiddle.net/Lgx4es86/6/

/* Calculates scrollbar width in pixels */
function scrollbar_width() {
    if( jQuery('body').height() > jQuery(window).height()) {

        /* Modified from: http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php */
        var calculation_content = jQuery('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
        jQuery('body').append( calculation_content );
        var width_one = jQuery('div', calculation_content).innerWidth();
        calculation_content.css('overflow-y', 'scroll');
        var width_two = jQuery('div', calculation_content).innerWidth();
        jQuery(calculation_content).remove();
        return ( width_one - width_two );
    }
    return 0;
}

jQuery( document ).ready( function(){
    apply_accordion();
    jQuery(window).resize(function() {
        apply_accordion();
    });
} );
function apply_accordion(){
  var ww = jQuery('body').width() + scrollbar_width();
    if (ww < 540) {
        jQuery('#footer-widget-area-1 .footer-area').accordion({
                active: false, collapsible:true
            });
        jQuery('#footer-widget-area-2 .footer-area').accordion({
                active: false, collapsible:true
            });
        jQuery('#footer-widget-area-3 .footer-area').accordion({
                active: false, collapsible:true
            });
        jQuery('#footer-widget-area-5 .footer-area').accordion({
                active: false, collapsible:true
            });
        jQuery('#footer-widget-area-6 .footer-area').accordion({
                active: false, collapsible:true
            });
        } else {
            var isInstance1 = (typeof jQuery('#footer-widget-area-1 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance1) {
                jQuery('#footer-widget-area-1 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-1 .footer-area').accordion("destroy");
            }
            var isInstance2 = (typeof jQuery('#footer-widget-area-2 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance2) {
                jQuery('#footer-widget-area-2 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-2 .footer-area').accordion("destroy");
            }
            var isInstance3 = (typeof jQuery('#footer-widget-area-3 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance3) {
                jQuery('#footer-widget-area-3 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-3 .footer-area').accordion("destroy");
            }
            var isInstance5 = (typeof jQuery('#footer-widget-area-5 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance5) {
                jQuery('#footer-widget-area-5 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-5 .footer-area').accordion("destroy");
            }
            var isInstance6 = (typeof jQuery('#footer-widget-area-6 .footer-area').data("ui-accordion") != "undefined");
            if (isInstance6) {
                jQuery('#footer-widget-area-6 .footer-area').accordion('option', 'active', 0);
                jQuery('#footer-widget-area-6 .footer-area').accordion("destroy");
            }
        // var isInstance = (typeof jQuery('.footer-area').data("ui-accordion") != "undefined");
        // if (isInstance){
        //  jQuery('.footer-area').accordion('option', 'active', 0);
        //  jQuery('.footer-area').accordion( "destroy" );
        // }
    }
}

Your workaround:

You are applying and removing the accordion styles, but not destroying the widget instances, so data event handlers are still there. You would need at least to move the jQuery('.footer-area').accordion part in another place to execute it just only one time. Moreover, beside this, the page width issue isn't solved by your workaround.

Scrollbar width function: credit Alex Mansfield (http://alexmansfield.com/javascript/css-jquery-screen-widths-scrollbars)

Monkhood answered 14/12, 2016 at 12:7 Comment(0)
E
0
        var myAccordion = null;
        jQuery(document).ready(function () {
            createAccordion(true);
            jQuery(window).bind("resize", function (event) {

                updateAccordion();
            });
        });
        function createAccordion(value){
        try{


           $(".footer-area").accordion({
                    icons: {"header": "icon-large ui-icon-carat-1-s", "activeHeader": "icon-large ui-icon-caret-1-n"},
                    active: 0,
                   // heightStyle: "fill",

                    collapsible: value
                });


             }catch(e){
        alert(e);
        }   
        }

        function updateAccordion() {

      try{
       var w = jQuery(window).width();
           if (w < 540){
           $(".footer-area").accordion("option", "collapsible", false);


           }else{

            $(".footer-area").accordion("option", "collapsible", true);
           }


      }catch(e){

      alert(e);
      }


            }
Electrodialysis answered 10/12, 2016 at 16:41 Comment(11)
Thank you for your kind reply, the first one I have already tried and that did not worked for me, the second one, I will definitely try, when I will return to home, away from my system now, also I would like to apologizes for so late reply.Drudge
The second one is not working too, Second one causing the div to be disappeared for mobile and when returning to landscape it is keeping the accordion, which is what I want to remove, For landscape, I am trying to display this as normal html and for portrait, I want it to use accordion.Drudge
Hello toto, I tried your updated code but still it does not worked for me, you can check here jsfiddle.net/voytfj2q/21 and jsfiddle.net/voytfj2q/22Drudge
what version of jquery you are using?Electrodialysis
Hi, i updated jsfiddle code and from my side work. please check. jsfiddle.net/voytfj2q/69Electrodialysis
in your fiddle, if you have noticed the menu is remaining in open condition for all screen-size, but it should work only for protrait( small screen ) what my question ask for and when the screen changes to landscape ( bigger screen ), the accordion should disappear / destroyed and the menu should display as normal menu and again for small screen it should display as accordion menu.Drudge
my jquery version is 1.11.4.Drudge
check jsfiddle.net/voytfj2q/20 it seems to be working but if you will check console it will generate " Uncaught Error: cannot call methods on accordion prior to initialization; attempted to call method 'destroy'" . and in actual implementation it does not work when I am moving from landscape to portrait.Drudge
hello, this link not is the code that i modified. is this: jsfiddle.net/voytfj2q/69Electrodialysis
hello toto, I have seen your fiddle, but the link I have provided seems like working having error, but your version is not working totally, if you change the screen size for your version and the link I have provided you can notice the link I have provided seems to be working, but when you look into console it has errors and in actual implementation it is not working .Drudge
perhaps, I was unable to make you understand my problem clearly, but please look at this jsfiddle.net/voytfj2q/78 your code and result, change the screen and see the result, you will notice even in small screen the accordion is unfolded and having a console error.Drudge
D
0

A work around will be removing and adding the classes and attributes when ever the screen size is changing. I am posting this workaround but would like to have an correct solution to it.

jQuery(document).ready(function() {

  jQuery(window).on("resize", function() {
      if (jQuery(window).width() < 540) {

          jQuery('.footer-area').accordion({
              active: false, collapsible:true, active:true
          });

          jQuery('.footer-area h2').append('<span class="ui-accordion-header-icon ui-icon ui-icon-carat-1-s"></span>');
          jQuery('.footer-area div').css('display', 'none');
          jQuery('.footer-area div').addClass('ui-widget-content');
          jQuery('.footer-area div').addClass('ui-accordion-content');
          jQuery('.footer-area h2').addClass('ui-accordion-header');
          jQuery('.footer-area h2').addClass('ui-accordion-icons');

      } else {
          jQuery('.footer-area h2 .ui-accordion-header-icon').remove();
          jQuery('.footer-area div').removeAttr('style');
          jQuery('.footer-area div').removeClass('ui-widget-content');
          jQuery('.footer-area div').removeClass('ui-accordion-content');
          jQuery('.footer-area h2').removeClass('ui-accordion-header');
          jQuery('.footer-area h2').removeClass('ui-accordion-icons');
      }
   });
Drudge answered 12/12, 2016 at 7:40 Comment(0)
V
0

There an option using pure css in which you can use media quires to show or hide them accordingly based on screen size:

Let's say you have ui-accordion-header class on your accordion headers when it's rendered.

Now you can put this in your style sheet:

@media screen and (min-width: 0) and (max-width: 1024px) {
  .ui-accordion-header { display: block; }  /* show it on small screens */
}

@media screen and (min-width: 0) and (max-width: 400px) {
  .ui-accordion-header { display: none; }   /* hide it elsewhere */
}

Or:

@media all and (orientation:portrait) {
  .ui-accordion-header { display: none; }
}

@media all and (orientation:landscape) {
  .ui-accordion-header { display: block; }
}

And you don't need to write any js code. Check the code here.

Vookles answered 13/12, 2016 at 0:14 Comment(5)
I tried your code , both of them and none of them worked for me, still I am thankful to you for your effort .Drudge
do you have a fiddle or plunkr? @PrafullaKumarSahuVookles
yes, the question itself contains one link if you have noticed jsfiddle.net/voytfj2q/20Drudge
I've put a working code there based on id selectors but you get the idea @PrafullaKumarSahuVookles
check jsfiddle.net/voytfj2q/20 it seems to be working but if you will check console it will generate " Uncaught Error: cannot call methods on accordion prior to initialization; attempted to call method 'destroy'" . and in actual implementation it does not work when I am moving from landscape to portrait.Drudge

© 2022 - 2024 — McMap. All rights reserved.