Сведения о вопросе

profi

16:03, 1st July, 2020

Теги

javascript   jquery   html   css   cfml    

Перенос списков в столбцы

Просмотров: 771   Ответов: 13

Я использую ColdFusion для заполнения шаблона, который включает в себя HTML списков ( <ul>'s).

Большинство из них не так уж и длинны, но некоторые имеют смехотворно длинные длины и действительно могут стоять в колонках 2-3.

Есть ли HTML, ColdFusion или, возможно, JavaScript (у меня есть jQuery` в наличии) способ сделать это легко? Это не стоит какого-то сверхсложного тяжеловесного решения, чтобы сэкономить немного прокрутки.



  Сведения об ответе

PIRLO

18:03, 1st July, 2020

Итак, я откопал эту статью из списка CSS Swag: списки с несколькими столбцами . В итоге я использовал первое решение, оно не самое лучшее, но другие требуют либо использования сложных HTML, которые не могут быть созданы динамически, либо создания большого количества пользовательских классов, что можно было бы сделать, но для этого потребуется много встроенного стиля и, возможно, огромная страница.

Однако другие решения по-прежнему приветствуются.


  Сведения об ответе

LAST

18:03, 1st July, 2020

Если поддержка Safari и Firefox достаточно хороша для вас, есть решение CSS:

ul {
  -webkit-column-count: 3;
     -moz-column-count: 3;
          column-count: 3;
  -webkit-column-gap: 2em;
     -moz-column-gap: 2em;
          column-gap: 2em;
}

Я не уверен насчет Opera.


  Сведения об ответе

prince

18:03, 1st July, 2020

Насколько я знаю, нет никакого чистого CSS/HTML способа достичь этого. Лучше всего было бы сделать это в предварительной обработке (if list length > 150, split into 3 columns, else if > 70, split into 2 columns, else 1 ).

Другой вариант, используя JavaScript (я не знаком с библиотекой jQuery конкретно ), состоял бы в том, чтобы перебирать списки, вероятно, основываясь на том, что они являются определенным классом, подсчитывать количество дочерних элементов и, если это достаточно большое число, динамически создавать новый список после первого, перенося некоторое количество элементов списка в новый список. Что касается реализации столбцов, то вы, вероятно, можете переместить их влево, а затем добавить элемент, имеющий стиль clear: left или clear: both .

.column {

  float: left;

  width: 50%;

}

.clear {

  clear: both;

}
<ul class="column">

  <li>Item 1</li>

  <li>Item 2</li>

  <!-- ... -->

  <li>Item 49</li>

  <li>Item 50</li>

</ul>

<ul class="column">

  <li>Item 51</li>

  <li>Item 52</li>

  <!-- ... -->

  <li>Item 99</li>

  <li>Item 100</li>

</ul>

<div class="clear">


  Сведения об ответе

#hash

18:03, 1st July, 2020

Я сделал это с jQuery - это кросс-платформенный и минимум кода.

Выберите UL, клонируйте его и вставьте после предыдущего UL. Что-то вроде:

$("ul#listname").clone().attr("id","listname2").after()

Это позволит вставить копию вашего списка после предыдущего. Если исходный список стилизован под float:left, они должны отображаться рядом.

Затем вы можете удалить четные элементы из левого списка и нечетные элементы из правого списка.

$("ul#listname li:even").remove();
$("ul#listname2 li:odd").remove();

Теперь у вас есть слева направо список из двух столбцов.

Чтобы сделать больше столбцов, вам потребуется использовать .slice(begin,end) и / или селектор :nth-child . т. е. для 21 LIs вы можете .slice(8,14) создать новый UL, вставленный после вашего исходного UL, затем выбрать исходный UL и удалить li, выбранный с ul :gt(8) .

Попробуйте книгу Бибо/Каца на jQuery-это отличный ресурс.


  Сведения об ответе

P_S_S

18:03, 1st July, 2020

Вот вариация на примере Thumbkin (используя Jquery):

var $cat_list = $('ul#catList'); // UL with all list items.
var $cat_flow = $('div#catFlow'); // Target div.
var $cat_list_clone = $cat_list.clone(); // Clone the list.
$('li:odd', $cat_list).remove(); // Remove odd list items.
$('li:even', $cat_list_clone).remove(); // Remove even list items.
$cat_flow.append($cat_list_clone); // Append the duplicate to the target div.

Спасибо Пальчик!


  Сведения об ответе

davran

18:03, 1st July, 2020

Следующий код JavaScript работает только в Spidermonkey и Rhino, и он работает на узлах E4X-т. е. это полезно только для серверной части JavaScript, но это может дать кому-то отправную точку для выполнения версии jQuery. (Это было очень полезно для меня на стороне сервера, но я не нуждался в этом на клиенте достаточно сильно, чтобы действительно построить его.)

function columns(x,num) {
    num || (num = 2);
    x.normalize();

    var cols, i, j, col, used, left, len, islist;
    used = left = 0;
    cols = <div class={'columns cols'+num}></div>;

    if((left = x.length())==1)
        left = x.children().length();
    else
        islist = true;

    for(i=0; i<num; i++) {
        len = Math.ceil(left/(num-i));
        col = islist ? new XMLList
                     : <{x.name()}></{x.name()}>;

        if(!islist && x['@class'].toString())
            col['@class'] = x['@class'];

        for(j=used; j<len+used; j++)
            islist ? (col += x[j].copy()) 
                   : (col.appendChild(x.child(j).copy()));

        used += len;
        left -= len;
        cols.appendChild(<div class={'column'+(i==(num-1) ? 'collast' : '')}>{col}</div>);
    }
    return cols;
}

Вы называете его как columns(listNode,2) для двух столбцов, и он поворачивается:

<ul class="foo">
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>

в:

<div class="columns cols2">
  <div class="column">
    <ul class="foo">
      <li>a</li>
      <li>b</li>
    </ul>
  </div>
  <div class="column collast">
    <ul class="foo">
      <li>c</li>
    </ul>
  </div>
</div>

Он предназначен для использования с CSS, как это:

div.columns {
    overflow: hidden;
    _zoom: 1;
}

div.columns div.column {
    float: left;
}

div.cols2 div.column {
    width: 47.2%;
    padding: 0 5% 0 0;
}

div.cols3 div.column {
    width: 29.8%;
    padding: 0 5% 0 0;
}

div.cols4 div.column {
    width: 21.1%;
    padding: 0 5% 0 0;
}

div.cols5 div.column {
    width: 15.9%;
    padding: 0 5% 0 0;
}

div.columns div.collast {
    padding: 0;
}


  Сведения об ответе

прога

18:03, 1st July, 2020

Большинство людей забывают, что при плавании <li/> элементов все элементы должны быть одинаковой высоты, иначе столбцы начнут выходить из строя.

Поскольку вы используете серверный язык, я бы рекомендовал использовать CF для разделения списка на 3 массива. Затем вы можете использовать внешний ul , чтобы обернуть 3 внутренних ul так:

<cfset thelist = "1,2,3,4,5,6,7,8,9,10,11,12,13">  
<cfset container = []>  
<cfset container[1] = []>  
<cfset container[2] = []>  
<cfset container[3] = []>  

<cfloop list="#thelist#" index="i">  
    <cfif i mod 3 eq 0>  
        <cfset arrayappend(container[3], i)>  
    <cfelseif i mod 2 eq 0>  
        <cfset arrayappend(container[2], i)>  
    <cfelse>  
        <cfset arrayappend(container[1], i)>  
    </cfif>  
</cfloop>  

<style type="text/css"> 
    ul li { float: left; }  
    ul li ul li { clear: left; }  
</style>  

<cfoutput>  
<ul>  
    <cfloop from="1" to="3" index="a">  
    <li>  
        <ul>  
            <cfloop array="#container[a]#" index="i">  
            <li>#i#</li>  
            </cfloop>  
        </ul>  
    </li>  
    </cfloop>  
</ul>  
</cfoutput>


  Сведения об ответе

SEEYOU

18:03, 1st July, 2020

Используя операцию по модулю, вы можете быстро разделить свой список на несколько списков, вставив </ul><ul> во время цикла.

<cfset numberOfColumns = 3 />
<cfset numberOfEntries = 34 />
<ul style="float:left;">
    <cfloop from="1" to="#numberOfEntries#" index="i">
        <li>#i#</li>
            <cfif NOT i MOD ceiling(numberOfEntries / numberOfColumns)>
                </ul>
                <ul style="float:left;">
            </cfif>
    </cfloop>
</ul>

Используйте ceiling() вместо round() , чтобы убедиться, что у вас нет дополнительных значений в конце списка и что последний столбец является самым коротким.


  Сведения об ответе

lool

18:03, 1st July, 2020

Чтобы вывести список в несколько сгруппированных тегов, вы можете выполнить цикл таким образом.

<cfset list="1,2,3,4,5,6,7,8,9,10,11,12,13,14">
<cfset numberOfColumns = "3">

<cfoutput>
<cfloop from="1" to="#numberOfColumns#" index="col">
  <ul>
  <cfloop from="#col#" to="#listLen(list)#" index="i" step="#numberOfColumns#">
    <li>#listGetAt(list,i)#</li>
  </cfloop>
  </ul>
</cfloop>
</cfoutput>


  Сведения об ответе

lats

18:03, 1st July, 2020

Вот еще одно решение, которое позволяет создавать столбчатые списки в следующем стиле:

1.      4.      7.       10.
2.      5.      8.       11.
3.      6.      9.       12.

(но это чисто javascript, и требует jQuery, без запасного варианта)

Ниже приведен некоторый код, который изменяет прототип массива, чтобы дать новую функцию с именем 'chunk', которая разбивает любой данный массив на куски заданного размера. Далее следует функция с именем 'buildColumns', которая принимает строку селектора UL и число, используемое для обозначения количества строк, которые могут содержать столбцы. ( Вот рабочий JSFiddle )

$(document).ready(function(){
    Array.prototype.chunk = function(chunk_size){
        var array = this,
            new_array = [],
            chunk_size = chunk_size,
            i,
            length;

        for(i = 0, length = array.length; i < length; i += chunk_size){
            new_array.push(array.slice(i, i + chunk_size));
        }
        return new_array;
    }

    function buildColumns(list, row_limit) {
        var list_items = $(list).find('li').map(function(){return this;}).get(),
        row_limit = row_limit,
        columnized_list_items = list_items.chunk(row_limit);

        $(columnized_list_items).each(function(i){
            if (i != 0){
                var item_width = $(this).outerWidth(),
                    item_height = $(this).outerHeight(),
                    top_margin = -((item_height * row_limit) + (parseInt($(this).css('margin-top')) * row_limit)),
                    left_margin = (item_width * i) + (parseInt($(this).css('margin-left')) * (i + 1));

                $(this[0]).css('margin-top', top_margin);
                $(this).css('margin-left', left_margin);
            }
        });
    }

    buildColumns('ul#some_list', 5);
});


  Сведения об ответе

prince

18:03, 1st July, 2020

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

Основная идея состоит в том, чтобы установить flex-direction на контейнере либо в row , либо в column .

NB: в настоящее время поддержка браузера довольно хороша.

FIDDLE

(Образец markup взят из этой старой статьи 'list apart' )

ol {

  display: flex;

  flex-flow: column wrap; /* flex-direction: column */

  height: 100px; /* need to specify height :-( */

}

ol ~ ol {

  flex-flow: row wrap; /* flex-direction: row */

  max-height: auto; /* override max-height of the column direction */

}

li {

  width: 150px;

}

a {

  display: inline-block;

  padding-right: 35px;

}
<p>items in column direction</p>

<ol>

  <li><a href="#">Aloe</a>

  </li>

  <li><a href="#">Bergamot</a>

  </li>

  <li><a href="#">Calendula</a>

  </li>

  <li><a href="#">Damiana</a>

  </li>

  <li><a href="#">Elderflower</a>

  </li>

  <li><a href="#">Feverfew</a>

  </li>

  <li><a href="#">Ginger</a>

  </li>

  <li><a href="#">Hops</a>

  </li>

  <li><a href="#">Iris</a>

  </li>

  <li><a href="#">Juniper</a>

  </li>

  <li><a href="#">Kava kava</a>

  </li>

  <li><a href="#">Lavender</a>

  </li>

  <li><a href="#">Marjoram</a>

  </li>

  <li><a href="#">Nutmeg</a>

  </li>

  <li><a href="#">Oregano</a>

  </li>

  <li><a href="#">Pennyroyal</a>

  </li>

</ol>

<hr/>

<p>items in row direction</p>

<ol>

  <li><a href="#">Aloe</a>

  </li>

  <li><a href="#">Bergamot</a>

  </li>

  <li><a href="#">Calendula</a>

  </li>

  <li><a href="#">Damiana</a>

  </li>

  <li><a href="#">Elderflower</a>

  </li>

  <li><a href="#">Feverfew</a>

  </li>

  <li><a href="#">Ginger</a>

  </li>

  <li><a href="#">Hops</a>

  </li>

  <li><a href="#">Iris</a>

  </li>

  <li><a href="#">Juniper</a>

  </li>

  <li><a href="#">Kava kava</a>

  </li>

  <li><a href="#">Lavender</a>

  </li>

  <li><a href="#">Marjoram</a>

  </li>

  <li><a href="#">Nutmeg</a>

  </li>

  <li><a href="#">Oregano</a>

  </li>

  <li><a href="#">Pennyroyal</a>

  </li>

</ol>


  Сведения об ответе

P_S_S

18:03, 1st July, 2020

Поскольку у меня была та же проблема и я не мог найти ничего "clean", я решил, что опубликовал свое решение. В этом примере я использую обратный цикл while , поэтому я могу использовать splice вместо slice . Теперь преимущество состоит в том, что splice() нужен только индекс и диапазон, где slice() нужен индекс и итог. Последнее, как правило, становится трудным во время цикла.

Недостатком является то, что мне нужно перевернуть стек при добавлении.

Пример:

cols = 4; liCount = 35

для петли со срезом = [0, 9]; [9, 18]; [18, 27]; [27, 35]

обратный пока с соединением = [27, 8]; [18, 9]; [9, 9]; [0, 9]

Код:

// @param (list): a jquery ul object
// @param (cols): amount of requested columns
function multiColumn (list, cols) {
    var children = list.children(),
        target = list.parent(),
        liCount = children.length,
        newUl = $("<ul />").addClass(list.prop("class")),
        newItems,
        avg = Math.floor(liCount / cols),
        rest = liCount % cols,
        take,
        stack = [];

    while (cols--) {
        take = rest > cols ? (avg + 1) : avg;
        liCount -= take;

        newItems = children.splice(liCount, take);
        stack.push(newUl.clone().append(newItems));
    }

    target.append(stack.reverse());
    list.remove();
}


  Сведения об ответе

lesha

18:03, 1st July, 2020

Вы можете попробовать это конвертировать в cols.

CSS:

ul.col {
    width:50%;
    float:left;
}

div.clr {
    clear:both;
}

Html часть :

<ul class="col">
    <li>Number 1</li>
    <li>Number 2</li>

    <li>Number 19</li>
    <li>Number 20</li>
</ul>
<ul class="col">
    <li>Number 21</li>
    <li>Number 22</li>

    <li>Number 39</li>
    <li>Number 40</li>
</ul>


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться