create dynamic read more when the info is coming from WYSIWYG
So I have a ton of content that is already set up through ti开发者_C百科nyMCE and I need to somehow grab x number of characters or the first <p>
tag then add a 'read more' link that will show the rest of the content. I have looked online, but I cant seem to find one that would work. And the ones I did find only really work if I strip all the html out of the string.
Does anyone have any ideas?
I kinda answered in code and ramblings at first, as this turned out to be more complex than I thought... But here's a more coherent version of what I had said before :)
My proposed solution is to take the substring of characters 0-100 in the original string. That's the dangerous string that might contain unterminated HTML tags.
Then, only if this chopped String is shorter than the input string (there's no point in further processing if this didn't actually cut the string), start magic:
/**
* 1. Loop from char 0 to 100, at each character, check if
* it might be an open tag "<"
* 2. Check if it's a "<TAG>" or "</TAG>"
* 3. Each time "<TAG>" occurs, add to array of
* "tags to close" Strings
* 4. Each time "</TAG>" occurs, pop the last entered "<TAG>"
* from the array
* 5. Once all the string is examined, foreach "tags to close",
* write "</".TAG.">"
**/
working example on this page: Concatenate a string, and terminate html within
Possible problems that are only partially resolved (see if(!$endloop){
section of track_tag()
):
- The last HTML tag is chopped by initial
substr()
method. For example, string ends with:<di
or<div
or</h
, etc... - The input HTML string is not valid HTML, e.g.
<div><h1>invalid html</div></h1>
or</p><p>what's with the random </p> before this <p>, man?</p>
Unforutnately that opens a whole can of worms I won't get into, and you are likely to see them in a WYSIWYG-generated string...
<?php
$killer = new tagEndingConcatMachine ();
$killer->summaryLength = $length;
$killer->end = "...";
$killer->chop_and_append($input)."Read more";
class tagEndingConcatMachine {
public $end = '...';
public $summaryLength = 100;
private $tags_to_end = array();
public function chop_and_append($x){
$summary = substr($x, 0 ,$this->summaryLength);
if($summary !== $x){
$this->end_tags($summary);
return $summary . $this->end;
}
return $summary;
}
private function end_tags(&$summary){ ;
for($i = 0; $i<=$this->summaryLength; $i++){
if($summary[$i]=='<'){
$this->track_tag($summary, $i);
}
}
for($i = count($this->tags_to_end); $i>=0; $i--){
if($this->tags_to_end != '' && isset($this->tags_to_end[$i]))
$this->end .= '</'.$this->tags_to_end[$i].">";
}
}
private function track_tag(&$summary, $i){
$this_tag = '';
$endloop = false;
$ending = false;
$k = $i+1;
do{
$thischar = $summary[$k];
if($thischar=='/' && $summary[$k-1]== '<'){
$ending = true;
}elseif($thischar=='>'){
if($this_tag!=''){
if($ending)
array_pop($this->tags_to_end);
else
$this->tags_to_end[] = strtolower($this_tag);
}
$endloop = true;
}else{
$this_tag .= $thischar;
}
$k++;
}while($k<=$this->summaryLength && !$endloop);
if(!$endloop){
if($ending){
//opened end tag, never closed
//could be trouble... but tags_to_end knows which to close
$this->end = '>'.$this->end;
}else{
//open opening tag... remove it from the end of the summary
$summary = substr($summary, 0, strlen($summary)-strlen($this_tag)-1);
}
}
}
}
?>
Let's say $x
is the content you received from the WYSIWYG.
echo substr($x, 0, 100) . '... <a href="[your post url here]">Read More</a>';
This will echo out the first 100 chars of $x
and concatenate the read more link to the end.
Hope this helps, also check this out.
精彩评论