frekw / kirby-modules

A simple module system for http://getkirby.com
MIT License
23 stars 3 forks source link

Style + collapse/expand + remember #5

Closed ghost closed 8 years ago

ghost commented 8 years ago

Did a little make over, and added remember state for collapsed modules, content and settings tab. What you think..? I know you mention that you didn´t like to incorporate a hidden field in the blueprint, but for me anyway, it definetely beats the experience over the hidden field... ; ) The field is active..

type: image
fields:
    image:
        label: Image
        type: select
        options: images
    active:
        type: hidden
    caption:
        label: Caption
        type: textarea
options:
    size:
        label: Size
        type: text
        width: 4/4
    margin:
        label: Margin
        type: text
        width: 2/4
    padding:
        label: Padding
        type: text
        width: 2/4

accord_style

ghost commented 8 years ago

I you wanna have a go here are the code : It´s kind of ugly but hey it works.. lol

modules.js

(function($) {

    //var dragging = false;

    function tabber(mod) {

        var mods = mod.children('.modules-entries').children('.modules-entry');

        mods.each(function() {

            var obj = $(this),
                tabs = obj.children('.tabs'),
                accord = obj.children('.accordion-content'),
                active = accord.find("input[name$='[active]']"),
                modToggle = tabs.children('.mod-toggle'),
                modContent = tabs.children('.mod-content'),
                modOptions = tabs.children('.mod-options'),
                modEntryFields = accord.children('.modules-entry-content').children('.modules-entry-fields'),
                modEntryOptions = accord.children('.modules-entry-content').children('.modules-entry-options');

            if (active.val() == 'modContent') {
                accord.removeClass('hide');
                modEntryFields.removeClass('hide');
                modEntryOptions.addClass('hide');
            } else if (active.val() == 'modOptions') {
                accord.removeClass('hide');
                modEntryOptions.removeClass('hide');
                modEntryFields.addClass('hide');
            } else if (active.val() == 'modContent-hide') {
                accord.addClass('hide');
                modEntryFields.removeClass('hide');
                modEntryOptions.addClass('hide');
            } else if (active.val() == 'modOptions-hide') {
                accord.addClass('hide');
                modEntryOptions.removeClass('hide');
                modEntryFields.addClass('hide');
            } else {
                accord.removeClass('hide');
                modEntryFields.removeClass('hide');
                modEntryOptions.addClass('hide');
                active.val('modContent');
            }

            modContent.on('click', function() {
                accord.removeClass('hide');
                modEntryFields.removeClass('hide');
                modEntryOptions.addClass('hide');
                active.val('modContent');
            });

            modOptions.on('click', function() {
                accord.removeClass('hide');
                modEntryOptions.removeClass('hide');
                modEntryFields.addClass('hide');
                active.val('modOptions');
            });

            modToggle.on('click', function() {
                if (accord.hasClass('hide')) {
                    if (active.val() == 'modContent-hide') {
                        accord.removeClass('hide');
                        modEntryFields.removeClass('hide');
                        modEntryOptions.addClass('hide');
                        active.val('modContent');
                    } else {
                        accord.removeClass('hide');
                        modEntryOptions.removeClass('hide');
                        modEntryFields.addClass('hide');
                        active.val('modOptions');
                    }
                } else {
                    accord.addClass('hide');
                    if (active.val() == 'modContent') {
                        active.val('modContent-hide')
                    } else {
                        active.val('modOptions-hide')
                    }
                }

            });

        })
    }

    var Modules = function(el) {

        var element  = $(el);
        var api      = element.data('api');
        var sortable = element.data('sortable');

        tabber(element);

        if (sortable === false) { return false; }

        // This is really ugly. Oh well.
        element.find('> .modules-entries > .modules-actions > .modules-add-button, > .modules-entries > .modules-empty > p > .modules-empty-add-button').on('click', function(){
            $(this).closest('form').trigger('keep');
        });

        element.sortable({
            items: '.modules-entry',
            //axis: 'y',
            delay: 100,
            //scroll: true,
            //tolerance: 'pointer',
            handle: '.tabs',
            start: function() {
                dragging = true;
            },
            update: function() {

                var ids = [];

                $.each($(this).sortable('toArray'), function(i, id) {
                    ids.push(id.replace('modules-entry-', ''));
                });

                $.post(api, {ids: ids}, function() {
                    //app.content.reload();
                });
                /*
                $.post(api, {ids: ids}, function() {
                    //app.content.reload();
                });
                */
            }

        });
    }

    $.fn.modules = function() {
        return this.each(function() {

            if($(this).data('modules')) {
                return $(this);
            } else {
                var modules = new Modules(this);
                $(this).data('modules', modules);
                return $(this);
            }
        });
    }

})(jQuery);
ghost commented 8 years ago

config.php

c::set('panel.stylesheet',array(
    //'/assets/icon/css/font-awesome.min.css',
    '/assets/css/panel.css'
));

panel.css

.modules-entry {
        margin-bottom: 1em;
        position: relative;
    }
    .modules-add-button {
        background: #fff none repeat scroll 0 0;
        border-color: #ddd;
        margin-bottom: 0px;
    }

    .modules-entry-fields .fieldset  { margin-bottom: -1.5em; }

    .modules .modules-entries {
        border: none;
        background: none;
        padding: 0;
    }
    .modules-empty {
        border: 1px dashed #bebebe;
        padding: 4em 0;
        text-align: center;
    }
    .tabs {
        background: #f7f7f7 none repeat scroll 0 0;
        border: 1px solid #ddd;
        list-style: outside none none;
        overflow: hidden;
        height: 50px;
        padding: 0;
        position: relative;
        top: 1px;
        cursor: grab;
    }
    .modules-entry.ui-sortable-helper .tabs,
    .modules-entry.ui-sortable-helper .tabs .mod-toggle,
    .modules-entry.ui-sortable-helper .tabs .mod-options,
    .modules-entry.ui-sortable-helper .tabs .mod-content,
    .modules-entry.ui-sortable-helper .tabs .mod-delete a{
        cursor: grabbing;
    }
    .tabs:after {
        display: table;
        content: "";
        clear: both;
    }
    .tabs li {
        float: left;
        font-weight: bold;
        min-width: 50px;
        padding: 14px;
        position: relative;
        text-align: center;
    }
    .tabs li .icon {
        font-size: 14px;
        font-weight: normal;
    }
    .tabs li .modules-entry-delete,
    .tabs li .modules-entry-delete:hover,
    .tabs li .modules-entry-delete:active {
        background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
        border: medium none;
        display: inline-block;
        float: none;
        font-size: 14px;
        font-weight: normal;
        line-height: inherit;
        margin: 0;
        opacity: 1;
        padding: 0;
        color: #333;
        position: relative;
        right: auto;
        text-align: center;
        text-transform: none;
        top: auto;
        transition: none 0s ease 0s;
    }
    .tabs li .modules-entry-delete .icon {
        font-size: 14px;
        font-weight: normal;
        padding: 0;
        margin: 0;
        color: #333;
    }
    .tabs .mod-toggle, .tabs .mod-options, .tabs .mod-content, .tabs .mod-delete {
        border-right: none;
        border-left: 1px solid #ddd;
        float: right;
        cursor: pointer;
    }
    .accordion-content.hide, .modules-entry-options.hide, .modules-entry-fields.hide { display: none; }
ghost commented 8 years ago

forgot the items.php

<?php
$form = require implode(DS, array(__DIR__, 'form.php'));

foreach($field->entries() as $i => $entry): ?>
    <div class="modules-entry" id="modules-entry-<?php echo $entry->id() ?>">

        <ul class="tabs">
            <li class="mod-type"><span><?php echo ucfirst($entry->type()); ?></span></li>
            <?php if(!$field->readonly()): ?>
                <li class="mod-delete">
                    <a data-modal
                    class="btn btn-icon btn-rounded btn-negative modules-entry-delete"
                    href="<?php __($field->url('delete') . '/' . $entry->id()) ?>">
                        <?php i('trash-o', 'left'); ?>
                    </a>
                </li>
            <?php endif; ?>
            <li class="mod-toggle"><?php i('toggle-on'); ?></li>
            <?php if($form('hasOptions', $entry, $field)): ?>
                <li class="mod-options"><?php i('gear'); ?></li>
                <li class="mod-content"><?php i('pencil'); ?></li>
            <?php endif; ?>
        </ul>

        <div class="accordion-content">
            <div class="modules-entry-content">
                <?php if(!$field->readonly()): ?>
                    <div class="modules-entry-fields" id="modules-entry-fields-<?php echo $entry->id() ?>">
                        <?php $form('fields', $entry, $field); ?>
                    </div>
                    <?php if($form('hasOptions', $entry, $field)): ?>
                        <div class="modules-entry-options" id="modules-entry-options-<?php echo $entry->id() ?>">
                            <?php $form('options', $entry, $field); ?>
                        </div>
                    <?php endif; ?>
                    <?php require implode(DS, array(__DIR__, 'form.php')); ?>
                <?php endif ?>
            </div>
        </div>
    </div>
<?php endforeach ?>
frekw commented 8 years ago

I really like that styling!

I have some ideas of how to remember the state (during the duration of the editing, at least). Right now, all data is shadowed in field/modules/cache.php so I'm thinking we could shove it in there during its own key and set it deeply for each module. Hopefully I can get around to kicking the idea around for real later this week.

frekw commented 8 years ago

As of 053c9021c8dacc745da1cb882119803590902d57 the state should be persisted between reloads/saves without storing it in the blueprint/content.

I'll have a look at incorporating your styling changes!

frekw commented 8 years ago

I've updated the styling as of 37fb82b12954e47cd5bd710c9188e5ecd0e52f77. Closing this issue. Thanks for the input!

ghost commented 8 years ago

Cool man tested it, and yeah it rocks ! Great job !!

ghost commented 8 years ago

Really like the new option to just click on the module to toggle the "collapsed" state, but when dragging stops the "collapsed" state is triggered again, to prevent this from happening I suggest to listen to the sortable start and end function, something like this, I also suggest to add an "handle" for the dragging to prevent "accident" toggles and dragging..

var dragging = false;

    element.sortable({
        handle: '.modules-header',
        start: function() {
            dragging = true;
        },
        stop: function() {
            dragging = false;
        }
    })
frekw commented 8 years ago

Ah, seems to happen in Firefox. I'll see if I can work around it.

frekw commented 8 years ago

Should be fixed now! @A-Monkey

ghost commented 8 years ago

Aha! Det stämmer nog, sitter i firefox, kanon ! En grej som jag tänkte testa imorgon är att byta ut jQuery:s sortable mot denna http://rubaxa.github.io/Sortable/ verkar riktigt smidig med touchsupport.. Är riktigt trött på gamla jQuery sortable, känns som man måste "ta i" varenda gång man ska flytta nått haha

ghost commented 8 years ago

aahhhhh kunde inte låta bli... haha https://forum.getkirby.com/t/somethings-cooking-astonished/3790 Om du jag tar bort det så hojta till !!!