Add Pagination to Issue TOC Page

Our journal’s (OJS 3.2.0.3) issue table of contents pages has been getting extremely long and endless scrolling down the list of over 50 articles is not appealing. Is there is a way to add pagination to this page? Or is there a more creative way to breakdown the long list of articles by section or category so that it is more presentable? Please let me know!

Hi @talknshare

This might be achievable moreso through modifying a theme. Please see our Theming guide for a sense of what is involved in this: PKP Theming Guide

Not quite the same issue, but the idea of modifying the table of contents is discussed here: Is it possible to have subsections in the Table of Contents? - and theming is discussed as the possible approach to doing this.

@NateWr or others may be able to weigh in further on the extent to which this might be achievable through theming.

Roger
PKP staff

2 Likes

Hi @rcgillis and @NateWr,
Thank you, Roger, for a quick response!

I compared these two tpl files: /templates/frontend/pages/issueArchive.tpl and /templates/frontend/pages/issue.tpl

The “issueArchive.tpl” file for displaying all the issues in the journal archive has the code for pagination (blockquote below); the “issue.tpl” file for the issue table of contents (TOC) page does not. How do I modify this code to insert in the issue.tpl file, so that it can paginate? Yes, I’ve been on PKP forum since 2010 and still cannot code. Thanks!

{* Pagination *}
		{if $prevPage > 1}
			{capture assign=prevUrl}{url router=$smarty.const.ROUTE_PAGE page="issue" op="archive" path=$prevPage}{/capture}
		{elseif $prevPage === 1}
			{capture assign=prevUrl}{url router=$smarty.const.ROUTE_PAGE page="issue" op="archive"}{/capture}
		{/if}
		{if $nextPage}
			{capture assign=nextUrl}{url router=$smarty.const.ROUTE_PAGE page="issue" op="archive" path=$nextPage}{/capture}
		{/if}
		{include
			file="frontend/components/pagination.tpl"
			prevUrl=$prevUrl
			nextUrl=$nextUrl
			showingStart=$showingStart
			showingEnd=$showingEnd
			total=$total
		}

Hi @talknshare,

Unfortunately, it won’t be possible to add the pagination code from issueArchive.tpl to issue.tpl. That’s because the issueArchive.tpl pagination makes use a handler to support multiple URLs for each page of the results. There’s no such handler on the single issue page.

The only way to get pagination on the issue table of contents is going to be to paginate the results through JavaScript, perhaps using #anchors to give each page a unique URL. Or to write a custom handler to support pagination.

Both of these will require a fair amount of coding skills, and are beyond the level of support that we can offer on the forum. Perhaps a technically-skilled community member will jump in with a solution that they’ve used.

Thank you, @NateWr. Sounds more work than I thought it would entail. If I am able to get it done by a freelancer, I will share it with you so that it can be integrated with the future releases of the software.

Hi @NateWr,

I’ve been playing with the issue_toc.tpl to add pagination using javascript as you suggested. If you can guide me to correct this snippet, I will really appreciate it.

I added the following in the bottom of the issue_toc.tpl file:

<nav aria-label="Page navigation example">
  <ul class="pagination">
    <li class="page-item1">
      <a class="page-link" href="javascript:void(0)" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
  </ul>
</nav>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<script src="/templates/frontend/objects/script2.js"></script>

And in the javascript file, I have the following code:
script2js
It works on my browser offline:
offlinepagination

But when I add the code to the OJS online, it doesn’t work:
onserver
Am I doing this right? Would you recommend any changes to the code?

Thanks!
@talknshare

HI @talknshare. Nothing jumps out at me, but it’s very hard to pick up on a bug from reading code like this. If you had an example online (at a test site) that I could look at I might be able to help.

It looks like you are using Bootstrap5. Have you considered using the Accordion pattern? Accordion · Bootstrap v5.0 If your issue is broken down into sections, you could make each section an accordion item and leave the first one open.

Hi. I solved this problem for version 3.2, but I think it will work for other versions as well.

1.Open the file:
pages\issue\IssueHandler.inc.php
2.Find the code:

$issueSubmissions = iterator_to_array(Services::get('submission')->getMany([
			'contextId' => $journal->getId(),
			'issueIds' => [$issue->getId()],
			'status' => $allowedStatuses,
			'orderBy' => 'seq',
			'orderDirection' => 'ASC',
		]));

		$sections = Application::get()->getSectionDao()->getByIssueId($issue->getId());
		$issueSubmissionsInSection = [];
		foreach ($sections as $section) {
			$issueSubmissionsInSection[$section->getId()] = [
				'title' => $section->getHideTitle()?null:$section->getLocalizedTitle(),
				'articles' => [],
			];
		}
		foreach ($issueSubmissions as $submission) {
			if (!$sectionId = $submission->getCurrentPublication()->getData('sectionId')) {
				continue;
			}
			$issueSubmissionsInSection[$sectionId]['articles'][] = $submission;
		}

		$templateMgr->assign(array(
			'issue' => $issue,
			'issueGalleys' => $issueGalleyDao->getByIssueId($issue->getId()),
			'publishedSubmissions' => $issueSubmissionsInSection,
			'primaryGenreIds' => $primaryGenreIds,
		));

3.Change to:

		$params = array(
			'contextId' => $journal->getId(),
			'issueIds' => [$issue->getId()],
			'status' => $allowedStatuses,
			'orderBy' => 'seq',
			'orderDirection' => 'ASC',
		);
		$issueSubmissions = iterator_to_array(Services::get('submission')->getMany($params));
		$total = Services::get('submission')->getMax($params);

		$page = intval( $_REQUEST['page'] );
		if ( $page == 0 ) { $page = 1; }
		$context = $request->getContext();
		$count = $context->getData('itemsPerPage') ? $context->getData('itemsPerPage') : Config::getVar('interface', 'items_per_page');
		$offset = $page > 1 ? ($page - 1) * $count : 0;
		$showingStart = $offset + 1;
		$showingEnd = min($offset + $count, $offset + count($issueSubmissions));
		$nextPage = $total > $showingEnd ? $page + 1 : null;
		$prevPage = $showingStart > 1 ? $page - 1 : null;
		if ( $nextPage ) { $nextPage = '?page='.$nextPage; }
		if ( $prevPage ) { $prevPage = '?page='.$prevPage; }
		
		$sections = Application::get()->getSectionDao()->getByIssueId($issue->getId());
		$issueSubmissionsInSection = [];
		foreach ($sections as $section) {
			$issueSubmissionsInSection[$section->getId()] = [
				'title' => $section->getHideTitle()?null:$section->getLocalizedTitle(),
				'articles' => [],
			];
		}
		
		ksort($issueSubmissionsInSection);

		function mySort($a, $b) {
			$a = $a->getCurrentPublication()->getData('sectionId');
			$b = $b->getCurrentPublication()->getData('sectionId');
    		if($a == $b)
        		return 0;
    		if($a < $b)
       			return -1;
    		else
        		return 1;
		}

		usort($issueSubmissions,'mySort');

		$i = 0;
		foreach ($issueSubmissions as $submission) {
			if ( $i >= $showingStart && $i <= $showingEnd ) {
				if (!$sectionId = $submission->getCurrentPublication()->getData('sectionId')) {
					continue;
				}
				$issueSubmissionsInSection[$sectionId]['articles'][] = $submission;
			}
			if ( $i == $showingEnd ) { break; }
			$i++;
		}

		$templateMgr->assign(array(
			'issue' => $issue,
			'issueGalleys' => $issueGalleyDao->getByIssueId($issue->getId()),
			'publishedSubmissions' => $issueSubmissionsInSection,
			'primaryGenreIds' => $primaryGenreIds,
			
			'prevUrl' => $prevPage,
			'nextUrl' => $nextPage,
			'showingStart' => $showingStart,
			'showingEnd' => $showingEnd,
			'total' => $total,
		));

4.Open the file:
templates\frontend\objects\issue_toc.tpl
5.Add code at the end of the file between these lines:

</div><!-- .sections -->
</div>

6.Like this:

</div><!-- .sections -->

	{* Pagination *}
	<div>
		{include
			file="frontend/components/pagination.tpl"
			prevUrl=$prevUrl
			nextUrl=$nextUrl
			showingStart=$showingStart
			showingEnd=$showingEnd
			total=$total
		}
		<a href="{url router=$smarty.const.ROUTE_PAGE page="issue" op="archive"}" class="read_more">
				{translate key="journal.viewAllIssues"}
		</a>
	</div>

</div>
2 Likes

You are a great addition to our community. @NateWr @rcgillis @asmecher . Thank you!