Sanches
@Sanches

Итерация javascript объекта с разбивкой на группы по N элементов?

Есть объект-коллекция с другими объектами, содержащие в себе данные нескольких страниц.
Нужно вывести данные этих страниц списком, но с разбивкой по 16 элементов.

Использую DocPad и Jade как шаблонизатор.

Код имеет такой вид:
- var projects = getCollection('projects').toJSON()
- var count = projects.length
- var pages = Math.ceil(count / 16)

.entry-list
    each project in projects
        - for ( var page = 1; page <= pages; page++ )
            .entry-list-page
                - for (var item = 1; item <= 16; item++,count-- )
                    - if (count > 0)
                        .hentry
                            a(href=project.url).entry-link
                                h3= project.title
                    - else
                        .hentry.emty

Недостающие элементы выводятся пустыми (.empty).
Естественно первый for отрабатывает полностью на каждый project, что ведет к совсем не тем результатам.
А получить хочется что-то вроде этого:
.entry-list
    .entry-list-page.page1
        .hentry
            a(href="page1.html").entry-link
                h3= title1
        .hentry
            a(href="page2.html").entry-link
                h3= title2
...
        .hentry
            a(href="page16.html").entry-link
                h3= title16
 
    .entry-list-page.page2
        .hentry
            a(href="page17.html").entry-link
                h3= title17
        .hentry
            a(href="page18.html").entry-link
                h3= title18
...
        .hentry
            a(href="page30.html").entry-link
                h3= title30
        .hentry.emty
        .hentry.emty


Буду признателен за помощь, моих знаний здесь не хватает.

UPD. Для меня решение нашлось таким:
- var projects = getCollection('projects').toJSON()
- var count = projects.length
- var ppage = 16
- var pages = Math.ceil(count / ppage)

.entry-list

    - for ( var cpage = 1; cpage <= pages; cpage++ )
        - var projectsPage = projects.splice(0,ppage)  // вырезаем первые 16 элементов
        .entry-list-page

            each project in projectsPage               // Итерируем вырезанные элементы
                .hentry
                    a(href=project.url).entry-link
                        h3= project.title

            - var ecount = ppage - projectsPage.length // Если элементов оказалось меньше нужного,
            - for ( var i = 0; i < ecount; i++  )      // заполняем нехватку
                .hentry.empt                           // пустыми блоками
  • Вопрос задан
  • 2783 просмотра
Решения вопроса 1
Sanches
@Sanches Автор вопроса
Спасибо Вам большое за помощь, но, к сожалению, ваш вариант так-же не работает — у Jade нет endif и блок .entry-list-page он закрывает сразу-же после обработки.
Но это уже не важно, я открыл для себя волшебный метод splice ), решение с ним в UPD.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Добрый день!

Мне кажется, что получился некий каламбур. Не совсем пойму: каждый проект делится на страницы или же на страницах выводятся проекты?

Исходя из Вашего кода, можно сделать вывод, что происходит и то, и то, что невозможно :)

Также, хочу заметить, что не имел дел с этим шаблонизатором, но, на мой взгляд, должно выйти что-то в духе:
- var projects = getCollection('projects').toJSON()
- var count = projects.length
- var ppage = 16 // per page
- var pages = Math.ceil(count / ppage)
- var cpage = 1 // current page

// добавляем пустые элементы в projects
- if (count < ppage*pages)
	- for (var n = count+1; n <= ppage*pages; n++)
		projects[n] = null

.entry-list
    each project, i in projects
    	- if (i == (1 + ppage * (cpage - 1)))	// 1,17,33,etc
        .entry-list-page.page$cpage				// не знаю, как вывести переменную
        // тут, возможно, нужен endif какой-то

        	- if (project != null)
            .hentry
                a(href=project.url).entry-link
                    h3= project.title
            - else
            .hentry.empty


Вместо добавления пустых элементо в projects можно было бы просто после each (когда он закончится уже) сделать еще for, который дописал бы "пустые" теги, но, насколько понимаю, этого сделать нельзя, т.к. див .entry-list-page.page2 будет закрыт внутри последней итерации each.

Исходя из этого есть такой вариант еще:
- var projects = getCollection('projects').toJSON()
- var count = projects.length
- var ppage = 16 // per page
- var pages = Math.ceil(count / ppage)
- var cpage = 1 // current page

.entry-list
    each project, i in projects					// это подсмотрел на stackoverflow, должно возвращать индекс
    	- if (i == (1 + ppage * (cpage - 1)))	// 1,17,33,etc
        .entry-list-page.page$cpage				// не знаю, как вывести переменную
        // тут, возможно, нужен endif какой-то

            .hentry
                a(href=project.url).entry-link
                    h3= project.title

            - if (i == count && count < ppage*pages)
            	- for (var n = count+1; n <= ppage*pages; n++)
            	.hentry.empty


Извиняюсь, если мои идеи только запутают, но алгоритмически это должно работать.
Необходимо пофиксить вывод переменной и проверить each.
Ну и все прочие элементы синтаксиса :)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы