Колонки Single / Double Bootstrap в зависимости от размера экрана, сохраняя порядок содержимого в каждом, не теряя места - PullRequest
0 голосов
/ 31 мая 2018

У меня есть 6 различных элементов различной длины, и я пытаюсь придумать макет сетки начальной загрузки, который обеспечивает следующее:

Макет с двумя столбцами для отображения на средних и больших дисплеях:

Обратите внимание, что блок 3 в приведенном ниже примере начинается сразу под блоком 1, даже если блок 2 намного длиннее блока 1.

MD+
|-----|-----|
|  1  |  2  |
|-----|     |    
|  3  |-----|
|-----|  4  |    
|  5  |-----|
|-----|  6  |
      |-----|

При следующей схеме размещения в один столбец для дисплеев, размер которых меньше среднего:

XS/SM:
|-----|
|  1  |
|-----|
|  2  |
|     |
|-----|
|  3  |
|-----|
|  4  |
|-----|
|  5  |
|-----|
|  6  |
|-----|

Просто чтобы быть точным, я никогда не хочу, чтобы 3 или более столбцов:

|-----|-----|-----|          
|  1  |  2  |  3  |
|-----|     |-----|     
|  4  |-----|  6  |
|-----|  5  |-----|
      |-----|

И порядок должен оставаться 1-6, никогда 1-3, а затем 4-6

Я могу по отдельности выполнить макет с двумя столбцами и макеты с одним столбцом, используя следующий код, но они оба ломаются, когда размер дисплея изменяется с SM / MD и наоборот:

Работает для XS / SM:

<div class="row">
    <div class="col-xs-12 col-md-6"> 1 </div>
    <div class="col-xs-12 col-md-6"> 2 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc quis interdum diam, in tempor est. Pellentesque nulla mi, egestas et rhoncus non, rhoncus bibendum velit. Nulla facilisi. Aenean faucibus nulla rutrum elementum cursus. Nam vel varius libero, eu porttitor tortor. In et ultricies nunc. Duis volutpat posuere urna, id faucibus ante lobortis sit amet. Maecenas urna nisl, tristique eget sem vel, semper tincidunt nisi.  </div>
    <div class="col-xs-12 col-md-6"> 3 </div>
    <div class="col-xs-12 col-md-6"> 4 </div>
    <div class="col-xs-12 col-md-6"> 5 </div>
    <div class="col-xs-12 col-md-6"> 6 </div>
</div>

Работает для MD +:

<div class="row">
    <div class="col-xs-12 col-md-6">
        <div class="row">
            <div class="col-xs-12"> 1 </div>
            <div class="col-xs-12"> 3 </div>
            <div class="col-xs-12"> 5 </div>
        </div>
    </div>
    <div class="col-xs-12 col-md-6">
        <div class="row">
            <div class="col-xs-12"> 2 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc quis interdum diam, in tempor est. Pellentesque nulla mi, egestas et rhoncus non, rhoncus bibendum velit. Nulla facilisi. Aenean faucibus nulla rutrum elementum cursus. Nam vel varius libero, eu porttitor tortor. In et ultricies nunc. Duis volutpat posuere urna, id faucibus ante lobortis sit amet. Maecenas urna nisl, tristique eget sem vel, semper tincidunt nisi.  </div>
            <div class="col-xs-12"> 4 </div>
            <div class="col-xs-12"> 6 </div>
        </div>
    </div>
</div>    

Можно ли получить нужный макет с помощью Bootstrap 3, и если да, то как?

1 Ответ

0 голосов
/ 01 июня 2018

В итоге я взломал решение jquery, которое преобразует HTML-код для структуры сетки начальной загрузки в макет, работающий в зависимости от текущего размера экрана.

Для упрощения я также взломал функцию класса, которая предоставляетОбъект dz (displaySize), который не только определяет, какой из текущих размеров экрана начальной загрузки активен (xs, sm, md или lg), но также предоставляет метод для выполнения ссылок на пользовательские функции, зарегистрированных в классе, если размер дисплея изменяется после перезагрузки (событие изменения размера окна опровергается с использованием подчеркивания).

Это код, который я в конечном итоге использовал, если вы знаете, как этого добиться, используя только структуру и классы начальной загрузки, то, пожалуйста, опубликуйте ответ, так как я бы предпочел простосделать это.

Единственное изменение в HTML - это добавление двух имен классов, добавленных к родительскому элементу .row (.custom-layout .custom-layout-2col).Начинаете ли вы с макета с одним столбцом или с макетом из 2 столбцов, зависит только от вас.просто измените имя второго класса в соответствии с макетом, с которого вы начинаете.На самом деле не имеет значения, с какого из них вы начнете, поскольку код заменит его на другой, если это необходимо, но вы должны начать с макета, который соответствует размеру дисплея для большинства ваших пользователей.

Ниже показаны добавленные классы для макета с двумя столбцами:

<div class="row custom-layout custom-layout-2col">
    <div class="col-xs-12 col-md-6">
        <div class="row">
            <div class="col-xs-12"> 1 </div>
            <div class="col-xs-12"> 3 </div>
            <div class="col-xs-12"> 5 </div>
        </div>
    </div>
    <div class="col-xs-12 col-md-6">
        <div class="row">
            <div class="col-xs-12"> 2 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc quis interdum diam, in tempor est. Pellentesque nulla mi, egestas et rhoncus non, rhoncus bibendum velit. Nulla facilisi. Aenean faucibus nulla rutrum elementum cursus. Nam vel varius libero, eu porttitor tortor. In et ultricies nunc. Duis volutpat posuere urna, id faucibus ante lobortis sit amet. Maecenas urna nisl, tristique eget sem vel, semper tincidunt nisi.  </div>
            <div class="col-xs-12"> 4 </div>
            <div class="col-xs-12"> 6 </div>
        </div>
    </div>
</div> 

javascript:

// This is the dz class. Load this after jquery.
// Note that it instantiates itself, just load it on your page.
// Requires the underscore library (or just the _.restArguments, _.delay, 
// and _.debounce functions from the library if you want to copy them out
// separately. )
; (function () {
    var Def = function () { return constructor.apply(this, arguments); }
    var attr = Def.prototype;

    //attributes
    attr.currentSize = '?';
    attr.previousSize = '?';
    attr.changeHandler = [];

    //constructor
    function constructor() {
        var self = this;
        $(document).ready(function () {
            $('.wrapper-content').append('<div class="device-xs hidden-xs"></div><div class="device-sm hidden-sm"></div><div class="device-md hidden-md"></div><div class="device-lg hidden-lg"></div>');
            $(window).resize(_.debounce(function () {
                self._determineDeviceSize();
            }.bind(self), 200));
            self._determineDeviceSize();
        }.bind(self));
    }

    //methods
    attr.getCurrentSize = function () {
        return this.currentSize;
    }

    attr.getPreviousSize = function () {
        return this.previousSize;
    }

    attr.addChangehandler = function (f) {
        if (typeof f === 'function') { this.changeHandler.push(f); }
    }

    attr._determineDeviceSize = function () {
        var c = this.currentSize;
        this.currentSize = $('.device-lg').is(':hidden') ? 'lg' : ($('.device-md').is(':hidden') ? 'md' : ($('.device-sm').is(':hidden') ? 'sm' : 'xs'));
        if (c !== this.currentSize) {
            this.previousSize = c;
            // execute any registered size change handler functions
            for (i = 0; i < this.changeHandler.length; ++i) {
                this.changeHandler[i](this.currentSize, this.previousSize);
            }
        }
    }

    //unleash the class (if it hasn't already been)
    if (typeof window.dz === 'undefined') {
        window.dz = new Def();
    }
})();


// Register our function with dz for the work that needs to be done
// if the bootstrap display size changes
dz.addChangehandler(function (csz, psz) {
    $('.custom-layout').each(function () {
        var parentRow = $(this);

        // Change from 1 col to 2 col ?
        if (parentRow.is('.custom-layout-1col') && (csz == 'md' || csz == 'lg')) {
            var allDivs = parentRow.children('div');
            var mCt = allDivs.length;
            if (mCt > 0) {
                // create the new row/col structure that we will move all the existing .col-* div's into
                var id = 'custom' + (new Date).getTime();
                var id2 = id + '2';
                parentRow.after('<div class="row custom-layout custom-layout-2col"><div class="col-md-6"><div id="' + id + '" class="row"></div></div><div class="col-md-6"><div id="' + id2 + '" class="row"></div></div></div>');
                var newOddParent = $('#' + id);
                var newEvenParent = $('#' + id2);
                var idx = 0;
                while (idx < mCt) {
                    if (idx === 0 || idx % 2 === 0) {
                        // odd
                        newOddParent.append($(allDivs[idx]));
                    } else {
                        // even
                        newEvenParent.append($(allDivs[idx]));
                    }
                    idx++;
                }
                // remove the old parent from the DOM
                parentRow.remove();
            } else {
                console.log('Unable to change custom-layout -- Unable to locate any div (col-*) elements in parent: ', parentRow);
            }
        }

        // Change from 2 col to 1 col ?
        if (parentRow.is('.custom-layout-2col') && (csz == 'xs' || csz == 'sm')) {
            var childRows = parentRow.children('div').children('.row');
            if (childRows.length == 2) {
                // create the new .row div that we will move all the .col-* div's into
                var id = 'custom' + (new Date).getTime();
                parentRow.after('<div id="' + id + '" class="row custom-layout custom-layout-1col"></div>');
                var newParent = $('#' + id);
                // locate all of the col-* div's that we will be moving
                var oddRowDivs = $(childRows[0]).children('div');
                var evenRowDivs = $(childRows[1]).children('div');
                childRows = '';
                var oCt = oddRowDivs.length;
                var eCt = evenRowDivs.length;
                var mCt = Math.max(oCt, eCt);
                var idx = 0;
                // move the div's directly into the parentDiv in a staggered order
                //  starting with the odd (left side) div #1, then even (right side) div #2, etc..
                while (idx < mCt) {
                    if (idx < oCt) {
                        newParent.append($(oddRowDivs[idx]));
                    }
                    if (idx < eCt) {
                        newParent.append($(evenRowDivs[idx]));
                    }
                    idx++;
                }
                // remove the old parent from the DOM
                parentRow.remove();
            } else {
                console.log('Unable to change custom-layout -- Unable to locate the 2 child .row elements in parent: ', parentRow);
            }
        }
    });
});

Если кому-то интересно, использование класса dz выглядит следующим образом:

  • dz.getCurrentSize () - возвращаемым значением будет текущий размер экрана начальной загрузки клиентского устройства: xs, sm, md или lg
  • dz.getPreviousSize () -Возвращаемым значением будет предыдущий размер начальной загрузки или '?'если размер не изменился с момента инициализации страницы
  • dz.addChangehandler (functionRef) - позволяет добавить собственную функцию-обработчик изменения размера экрана, которая будет выполняться при загрузке страницы и в любое время после изменения размера экрана.

Пример использования:

// if all you need is the current display size then use the dzCurrentSize variable
// just make sure your accessing it after jquery's $(document).ready
$(document).ready(function () {
    console.log('page size: ' + dz.getCurrentSize());
});


// using a change handler function
dz.addChangehandler(function (currentSize, previousSize) {
    // example usage scenarios:

    // always do stuff (on page initialization and when the size changes anytime afterwards)
    alert("The bootstrap display size is: " + currentSize);

    // do stuff ONLY if the size changed after page initialization
    if (previousSize !== '?') {
        console.log('The size has changed after initialization from: ' + previousSize + ' to: ' + currentSize);
    }

    // do stuff ONLY on page initialization
    if (previousSize === '?') {
        console.log('The page has just initialized with a size of: ' + currentSize);
    }

});
...