Jump to content

Pagebreak or Multi-page on single entry


biotech
 Share

Recommended Posts

Probably best way to use some custom tag like #PAGEBREAK# and then use some logic and urlSegments to split those into different pages.

But usually I would try to avoid multipage articles. Only reason those exists are that sites running ads want to maximize their page views.

  • Like 1
Link to comment
Share on other sites

Probably best way to use some custom tag like #PAGEBREAK# and then use some logic and urlSegments to split those into different pages.

But usually I would try to avoid multipage articles. Only reason those exists are that sites running ads want to maximize their page views.

Right, something in that line where TinyMCE would have a custom 'insert page break' deal.

Page length - well, might be true in 'blogging' world but I am more inclined to think printing, tech 'how to' documents (tutorials) that have to span over pages...in my case trying to build a small KB app and try out PW.

Thanks for the pointers, to both of you.

Link to comment
Share on other sites

Biotech, I agree with the idea to use a '#pagebreak#' tag or something like that. In your template your code would look something like this:

$pageBreaks = explode('<p>#pagebreak#</p>', $page->body);
if($input->pageNum && isset($pageBreaks[$input->pageNum])) $body = $pageBreaks[$input->pageNum];
   else $body = $pageBreaks[0];
echo $body; 
Link to comment
Share on other sites

Biotech, while it is certainly possible to achieve what you want i gotta agree with some of the previous comments; try to avoid multipage articles/tutorials/whatever.

If you are dealing with lengthy tutorials why not create some sort of table of contents and work with page anchors? I think this makes much more sense in the web world. You could write some logic in your tutorial template that generates the table of contents for you, depending on your structure and requirements.

Link to comment
Share on other sites

Thanks Ryan!

@SiNNut - I have not really set my mind on this, just exploring what is possible with WP . CI has a really nice TOC page with some jquerry so that is also an option to presenting just straight up pages as single entries and anchors as you suggest.

The idea of 'pagebreak' came from using WordPress and ExpressionEngine but most certainly is not a must for me but it might be for some users down the line.

Thanks guys.

Link to comment
Share on other sites

I don't think any of us like pagebreaks for these kinds of things. But the reality is that the folks in the marketing department like that one article can generate 4 pageviews (for instance) rather than 1. And we sometimes have to meet the needs of marketing whether we like the result or not. ProcessWire should be flexible enough (and hopefully is) to accommodate needs like this.

Link to comment
Share on other sites

I don't think any of us like pagebreaks for these kinds of things. But the reality is that the folks in the marketing department like that one article can generate 4 pageviews (for instance) rather than 1. And we sometimes have to meet the needs of marketing whether we like the result or not. ProcessWire should be flexible enough (and hopefully is) to accommodate needs like this.

Absolutely and it seems like there is a solution, thank you.

It would be a clacks with the new repeater field.

I saw that discussion ^-^

Link to comment
Share on other sites

  • 1 year later...

Being able to add a custom tag in tinyMCE to create a pagebreak would be ideal for a project I'm working on. I tried out Ryan's code here, which works for splitting things up (although I discovered that I need to add a #pagebreak# at the beginning of the first page for it to work right or else it will start at page 2).

The problem is when it comes time to add navigation, since the resulting array is not a WireArray and thus I can't use get("limit=1") on it and then call renderPager() on the result.

I tried creating a new WireArray object from scratch and adding the contents of $pageBreaks to that, but it won't accept them as valid input.

I feel like I'm probably barking up the wrong tree with this...

EDIT:  Ok, so it looks like I just need to build my own navigation from scratch. I can see why a repeater is probably the better way to go here.

EDIT 2: I have it working now. The reason I had to add a #pagebreak# to the top of the page with the original code is that the page numbers start at 1 while the array was 0-based so there was a mismatch. If anyone else wants to do something similar, here's the final code from my template with my custom navigation:

<? 
$pageBreaks = explode('<p>#pagebreak#</p>', $page->body);
$numPages = count($pageBreaks);
$currentPage = $input->pageNum;

if(array_key_exists($currentPage-1, $pageBreaks))
{
    $body = $pageBreaks[$currentPage-1];
}
else 
{
    throw new Wire404Exception();
}
?>

<?= $body ?>

<? 
if($numPages > 1) { 
?>
<div id="pagination-center-1">
<div id="pagination-center-2">
<ul id="pagination">
         
<li <? if($currentPage > 1) { echo 'class="previous"'; } else { echo 'class="previous-off"'; } ?>>
<? if($currentPage > 1) { echo '<a href="page'. ($currentPage - 1) .'">« Previous</a>'; } else { echo '« Previous'; } ?>
    </li>
         
<? 
for($i=1; $i <= $numPages; $i++) {
?>
<li>
<a href="page<?= $i ?>" <? if ($currentPage == $i) { echo 'class="active"'; } ?>><?= $i ?></a>
</li>
<?
    }
    ?>
                        
<li <? if($currentPage < $numPages) { echo 'class="next"'; } else { echo 'class="next-off"'; } ?>>
<? if($currentPage < $numPages) { echo '<a href="page'. ($currentPage + 1) .'">Next »</a>'; } else { echo 'Next »'; } ?>
</li>
     
</ul>
</div>
</div>
<? 
} 
?>
 

And for complete "plug-and-play", here's my CSS for the pagination:

ul#pagination {
	list-style:none;
	position:relative;
	float:left;
	left:-50%;
	margin-top:10px;
}

#pagination li {
	display:block;
	float:left;
	border:0; 
	font-size:11px;
	margin-right:2px;
}

#pagination a {
	border:solid 1px #9aafe5;
	margin-right:2px;
	display:block;
	float:left;
}

#pagination .previous-off,
#pagination .next-off {
	border:solid 1px #DEDEDE;
	color:#888888;
	font-weight:bold;
	margin-right:2px;
	padding:3px 4px;
}

#pagination .next a,
#pagination .previous a {
	font-weight:bold;
} 

#pagination .active {
	background:#2e6ab1;
	color:#FFFFFF;
	font-weight:bold;
	padding:4px 6px;
}

#pagination a:link,
#pagination a:visited {
	color:#0e509e;
	padding:3px 6px;
	text-decoration:none;
}

#pagination a:hover{
	border:solid 1px #0e509e;
}

#pagination-center-1 {
	overflow:hidden;
	z-index:-1;
	height:45px;
}

#pagination-center-2 {
	position:relative;
	float:left;
	left:50%;
}

#pagination a.active {
	color:#FFFFFF;

EDIT 3:  I recently revisited this on one of my new ProcessWire sites where I was using the built in PW pagination as well as this custom TinyMCE pagination system, and I wanted to get the pagination to look exactly like the standard PW pagination instead of what I posted above, which is a bit different. If you want it to use the exact same look & CSS classes as ProcessWire, here is the code:

<? 
if($numPages > 1) { 
?>
  <ul class="MarkupPagerNav">
  	<? 
  	if($currentPage > 1) { 
  	?>
    	<li class="MarkupPagerNavPrevious">
    		<a href="page<?= $currentPage - 1 ?>">Prev</a>
    	</li>
  	<? 
  	} 
  	?>
		<? 
		for($i=1; $i <= $numPages; $i++) {
		?>
    	<li <? if ($currentPage == $i) { echo 'class="MarkupPagerNavOn"'; } ?>><a href="page<?= $i ?>"><?= $i ?></a></li>
		<?
		}
		?>	
		<? 
		if($currentPage < $numPages) { 
		?>
			<li class="MarkupPagerNavNext">
				<a href="page<?= $currentPage + 1 ?>">Next</a>
			</li>
		<? 
		} 
		?>
  </ul>
<? 
} 
?>

And the default PW pagination CSS by Ryan:

.MarkupPagerNav {
	margin: 1em 0; 
	font-family: Arial, sans-serif;
	float: right;
}
	.MarkupPagerNav li {
		float: left;
		list-style: none;
		margin: 0;
	}
	
	.MarkupPagerNav li a,
	.MarkupPagerNav li.MarkupPagerNavSeparator {
		display: block;
		float: left;
		padding: 2px 9px;                
		color: #fff;
		background: #2f4248;
		margin-left: 3px;
		font-size: 10px;
		font-weight: bold;
		text-transform: uppercase;
	}
	                
	.MarkupPagerNav li.MarkupPagerNavOn a,
	.MarkupPagerNav li a:hover {
		color: #fff;
		background: #db1174;
		text-decoration: none;
	}
	
	.MarkupPagerNav li.MarkupPagerNavSeparator {
		display: inline;
		color: #777;
		background: #d2e4ea;
		padding-left: 3px;
		padding-right: 3px;
	}
	
Edited by everfreecreative
  • Like 2
Link to comment
Share on other sites

The reason I had to add a #pagebreak# to the top of the page with the original code is that the page numbers start at 1 while the array was 0-based so there was a mismatch. If anyone else wants to do something similar, here's the final code from my template with my custom navigation:

Thanks for posting. It looks to me like you shouldn't need to have a #pagebreak# at the top with your current code, given that you are subtracting 1 from $currentPage. Also, your "} else {" condition should probably "throw Wire404Exception()" rather than defaulting to $pageBreaks[0]. 

Link to comment
Share on other sites

Thanks for posting. It looks to me like you shouldn't need to have a #pagebreak# at the top with your current code, given that you are subtracting 1 from $currentPage. Also, your "} else {" condition should probably "throw Wire404Exception()" rather than defaulting to $pageBreaks[0]. 

Yes, the -1 I added solved that issue. Sorry, my wording was a bit unclear.

I'm not sure I understand what you mean on the second point. If I understand the code correctly, the else condition sets the $body variable to the entire contents of the $page->body field in the event that no #pagebreak# exists, which is what I wanted. Maybe just doing $body = $page->body; would be better? It seems to be working fine.

Link to comment
Share on other sites

I'm not sure I understand what you mean on the second point. If I understand the code correctly, the else condition sets the $body variable to the entire contents of the $page->body field in the event that no #pagebreak# exists, which is what I wanted. Maybe just doing $body = $page->body; would be better? It seems to be working fine.
 
Your first condition would always match even if there were no page breaks. That's because $input->pageNum is always 1 or greater (1 is the lowest possible value for $input->pageNum). As a result, the if($currentPage) part is not even needed. This if() condition will match regardless of whether there are page breaks or not: 
if($currentPage && isset($pageBreaks[$currentPage-1]))

Technically your "else" condition is only executed if someone specifies a page number in the URL that is out of bounds. Try page99 in the URL, and you will likely get the entire text. Instead, you probably want a 404 in that situation. That's why I think your else condition should throw a 404. 

Link to comment
Share on other sites

Hi Ryan - You were right. Except the throw Wire404Exception() is giving me "Internal Server Error" instead of a 404 page. Is that correct? Here is my new code:

<? 
$pageBreaks = explode('<p>#pagebreak#</p>', $page->body);
$numPages = count($pageBreaks);
$currentPage = $input->pageNum;

if(array_key_exists($currentPage-1, $pageBreaks))
{
	$body = $pageBreaks[$currentPage-1];
}
else 
{
	throw Wire404Exception();
}
?>

Link to comment
Share on other sites

If the internal server error is coming from ProcessWire (as opposed to Apache), then you can enable debug mode or check your /site/assets/logs/errors.txt to see what the actual error message is. 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...