contao / core-bundle

[READ-ONLY] Contao Core Bundle
GNU Lesser General Public License v3.0
123 stars 58 forks source link

"Start open/closed" option for accordions #1713

Closed Anke closed 4 years ago

Anke commented 4 years ago

I'd like to reactivate several requests from the past to add an option to accordions like "Initial state: Open/Closed".

As the requirements to have open or closed states differ, I think this can be called a basic option, while changing templates isn't very update-safe ...

asaage commented 4 years ago

The problem is, that the implementation for accordions in contao is in my opinion a bit quirky anyway. Currently you can place accordion-start/stop and single-elements all over the page in different articles, layout-sections or modules and they all affect each other because the generated mark-up (in terms of a wrapper) and the initialisation (j_accordion Template) differs significantly from what is suggested here https://api.jqueryui.com/accordion/

Unless we have nested elements it'll stay a matter of customized templates i guess.

Anke commented 4 years ago

We had that option in the extension independent_accordion. I don't know much about programming, but it worked quite well.

asaage commented 4 years ago

There is a native element which could be used in the future: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details and it accepts an open attribute as well.

It doesn't quite work the same (closing other elements) but that could probably be added with some lines of vanilla-js. For some reason the accordions did not make it to the list of revise-components for 4.9


i think...this works even in github

I can provide the j_accordion template (jquery version) that works for me. It let's me have basically independent accordions for #header, #main, #left, #right, #footer and activates/opens the first start- or single-element with class="active"

/* j_accordion.html5 */

<script src="<?= $this->asset('js/jquery-ui.min.js', 'contao-components/jquery-ui') ?>"></script>
<script>
  jQuery(function($) {
    $('.ce_accordionStart.active').find('.toggler').addClass('active');
    $('.ce_accordionSingle.active').find('.toggler').addClass('active');

    let findActive = function(section) {
        let active = false;
        let togs = $(section).find('.toggler').each(function(i, toggler){
            if ($(toggler).hasClass('active')) {
                active = i;
                return false;
            }
            if (active) return false;
        });
        return active;
    };

    $('#header, #main, #left, #right, #footer').each(function(i, section){
        $(section).accordion({
            heightStyle: 'content',
            header: '.toggler',
            collapsible: true,
            active: findActive(section),
            create: function(event, ui) {
                ui.header.addClass('active');
                $('.toggler').attr('tabindex', 0);
            },
            activate: function(event, ui) {
                ui.newHeader.addClass('active');
                ui.oldHeader.removeClass('active');
                $('.toggler').attr('tabindex', 0);
            }
        });     
    });
  });
</script>
Anke commented 4 years ago

Thanks for sharing your template. However, it doesn't provide the possibility to individually set open or closed states, does it?

The independent_accordion extension had a BE checkbox "Initial state open" and as far as I remember all it did was add the active class to the toggler. This enabled the user to set the state for every single accordion and there was no need to fiddle with templates.

An easier possibility would be to enter "active" into an accordions class field, whenever the initial state is to be "open". This is failing, though, because classes that are added to accordions are added content part of an accordion and not to the toggler. So if the class "active", set by a BE user, would be added to the toggler, the toggler could imo do its job accoding to the state set by the class. Or am I wrong?

asaage commented 4 years ago

@Anke with this template the BE-user is able to set the active-class on the element (not the toggler). This becomes initially open then. If there is no active to be found everthing is collapsed. Only one item can be active at any time (per accordion in any layout-section). This is just how i think a accordion should work - i see this as a collection and not as an individual independent collapsible item.

Anke commented 4 years ago

@Anke with this template the BE-user is able to set the active-class on the element (not the toggler).

True, I just found that out. You just need to know which class field to use. A respective hint in the fields help text would do the trick...

Well, I can understand you other argument, but I did have cases where it was helpful for FE users being able to open more than one accordion at a time.

Anyway, thank you for your help!

Anke commented 4 years ago

Gosh (confused, sorry), but having the possibility to use the active class in the backend, the script should be set to "active: false" by default to avoid template changes. I think it's important to have user-friendly choices.