- Úvodní stránka
- » Obecná diskuse
- » {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
#1 10. 3. 2010 21:01
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
{!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Ahoj, problém je asi jasný z předmětu.
Proměnna $htmlConent obsahuje naformátovaný text pomocí HTML
tagů (práce CKEditoru), který pak v šabloně zobrazuji takto:
{!$htmlConent}
Nyní bych chtěl tento text ořezat. Problém je ovšem v tom, že tato konstukce
{!$htmlConent|truncate:30}
k počtu znaků, které mají být ořezány započítává také HTML tagy. Tedy nejen, že může být způsobeno, že se nezobrazí vůbec nic z text, protože po ořezání zbydou jen HTML tagy, ale také nejsou tagy dokončeny, což může rozhodit layout webu.
Jak to udělat, aniž bych ztratil formátování textu (odstraněním HTML tagů) a mohl ořezat jen text? Přitom, by se všchny nedokončené HTML tagy uzavřely?
PS: nebyl jsem si jistý zda to mám hlásit jako chybu (když tak to tam přesuňte), protože možna takové použití nebylo ani zamýšleno. Nicméně něco takového by bylo docela užitečné. Řešili jste to už někdo? Jde to nějak udělat s pomocí Nette?
EDIT: Když jsem před přidáním tohoto tématu hledal na foru, zda tu už
někdo něco podobného neřešil, tak jsem narazil na něco takového:
{!$htmlConent|html|truncate:30}. To ale nefunguje (ani jsem
nezjišťoval co ten parametr html dělá..) a vyhazuje to chybu:
MemberAccessException - Call to undefined method
Template::html().
Osobně mě napadlo, jak by se to dalo zhruba implementovat, ale nechci předbíhat pokud něco takového už je. Musel bych projít celý htmlContent s tím, že bych si do pomocné proměnné ukládal text, který jsem už prošel a inkrementoval bych čítač znaků jen když bych narazil na text, který není v HTML tagu (text který se na stránce zobrazuje). Až bych narazil na limit, tak bych buď musel nějak dokončit HTML tagy a nebo dojet až do konce s tím, že bych ignoroval text a bral jen HTML tagy.
Editoval Endrju (10. 3. 2010 21:24)
Offline
#2 10. 3. 2010 21:18
- redhead
- Nette guru
- Registrovaný: 2. 5. 2009
- Příspěvky: 630
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Žádné defaultní řešení asi není. Takže napsat si vlastní helper?
Offline
#3 10. 3. 2010 21:27
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Aha, odpověděl jsi dřív než jsem stihl editovat post.. No, to nerad slyším :-/. Neznáte nějaký efektivní způsob na identifikaci HTML tagů (pro případ, že to budu muset impelmentovat)?
Nebo nemáte nekdo ještě lepší řešení, než to které jsem popsal ve svém předchozím příspěvku?
Offline
#4 10. 3. 2010 21:28
- Mikulas Dite
- Nette guru

- Místo: Praha
- Registrovaný: 18. 11. 2009
- Příspěvky: 320
- Web
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
No, html neni regulární, takže to přes regexp pude asi složitě. Ale zkusim z hlavy:
Do toho helperu dej něco na styl
<?php
function helperClip($subject, $limit)
{
$elements = preg_match_all('~<.*?>~s', $subject, $matches);
$raw_text = preg_replace('~<.*?>~s', '&__splitter;', $subject);
$raw_text_array = explode('&__splitter;', $raw_text);
$shortened_by = 0;
while($shortened_by < $limit)
{
if (strlen($raw_text_array[-1]) > $limit) {
$raw_text_array[-1] = substr($raw_text_array[-1], 0, $limit);
break;
} else {
$shortened_by += strlen($raw_text_array[-1]);
unset($raw_text_array[-1]);
}
}
return /*tady střídavě poskádat $raw_text_array a $elements (začínat podle počtu prvků)*/;
}
?>
Jo tak to sem se docela rozepsal, to sem ani nečekal. Netestoval sem to, takže tam určitě bude nějaké to typo. Plus závěr sem nedodělal, ale to by neměl být problém, viz. comment v kódu.
//Edit: jo, ty záporné indexy nejdou, je to
end($raw_text_array)
Editoval Mikulas Dite (10. 3. 2010 21:32)
Offline
#5 10. 3. 2010 22:27
- toka
- Člen

- Místo: Kostelec nad Orlicí
- Registrovaný: 5. 8. 2009
- Příspěvky: 173
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Používám tento helper:
class MyString {
public static function truncate($string, $length, $e = '…', $isHTML = TRUE){
$i = 0;
$tags = array();
if($isHTML) {
preg_match_all('/<[^>]+>([^<]*)/', $string, $match, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
foreach($match as $object) {
if($object[0][1] - $i >= $length) break;
$tag = substr(strtok($object[0][0], " \t\n\r\0\x0B>"), 1);
if($tag[0] != '/') $tags[] = $tag;
elseif(end($tags) == substr($tag, 1)) array_pop($tags);
$i += $object[1][1] - $object[0][1];
}
}
return substr($string, 0, $length = min(strlen($string), $length + $i)) . (count($tags = array_reverse($tags)) ? '</' . implode('></', $tags) . '>' : '') . (strlen($string) > $length ? $e : '');
}
}
Offline
#6 11. 3. 2010 0:32
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
to Mikulas Dite: diky :). V hlave me napadalo trochu jine reseni, protze jsem pred par mesici delal Crawler v .NET a tam jsem podobne veci resil. To co poslal toka funguje, takze uz to dale nezkoumam.
to toka: Parada, odzkousel jsem to a funguje (je tam jen jedna drobnost..). Byl bys prosim te jeste laskavy a zkusil trosku okomentovat jednotlive casti kodu, abych vedel co to presne dela? Mohl bych si to samozrejmne pozjistovat nastudovanim tech funkci ktere jsi pouzil, ale takto to bude snazsi.
Pouziti:
<div id="content"><?php echo MyString::truncate($htmlConent, 27); ?></div>
K te male drobnosti.. Vstupni text:
<p style="text-align: justify;">Vážení fotbaloví fanoušci,</p>
<p style="text-align: justify;">vítejte ....</p>
Vystup (text je dlouhý 23 znaků, ale zadával jsem 27):
Vážení fotbaloví fanou�
…
Výstup v HTML:
<p>Vážení fotbaloví fanou�</p>
…
Nevím jak to je s kódováním a jak se převedou znaky s diakritikou, protže to vypdadá, že ta funkce počíta znak s diakritikou jako více znaků a nebo tam je někde renonc… :). Když bych to chtěl zkrátit na 28 znaků, tak se znak ‚š‘ vypíše „celý“
No a pak bych ještě chtěl, aby se ty tři tečky zobrazily hned za zkráceným slovem (ještě v tom odstavci). Vypadá to takhle nejasně..
Myslíš, že by jsi to dokázal takto upravit?
Jiank moc děkuji za ušetřenou práci a čas. Fakt moc dík!
Offline
#7 11. 3. 2010 0:41
- Ondřej Mirtes
- Moderator

- Místo: Praha
- Registrovaný: 8. 1. 2009
- Příspěvky: 1357
- Web
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Používáš multibyte string metody? Např. mb_substr.
Offline
#8 11. 3. 2010 1:05
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Pokud je to otázka na mě Ondro, tak bych řekl, že ne. Zatím jsem si
vystačil s Nette funkcemi, takže pokud není něco přímo tam, tak ne.
Nevím jak jinak mám přijít na to, zda nějakou takovou funkci používám.
Text vkladám pomocí CKEditoru, ten je pak v databázi uložen jako
utf8_bin a zde se přes phpMyAdmina také v pořádku zobrazuje
(žádné podivné znaky).
Zkusil jsem s malou improvizací* předhodit stejný text helperu
truncate. Ten funguje tak, že zkracuje celá slova, dokud mu
nezbyde jediné slovo, to pak zkracuje po znacích a pak přidá trojtečku.
Jinak zanechává celá slova.
Ta improvizace tedy spočívala v tom, že jsem musel slovo se znakem ‚š‘ dát jako první slovo textu (jinak by mi to zkrátilo celé slovo) a pak postupně jsem zkracoval, až jsem narazil na místo, kde by měl být odebrán znak ‚š‘. Po jeho odebrání (zkrácení) tam nezbyde zádný balast.. Čili helper truncate to dělá vpořádku.
Podle mě je to způsobeno tou funkcí, kterou dodal „toca“. Když tu funkci nepoužiju, tak se znaky zobrazí správně. Když ji použiju, tak ne.
Bohužel jsem jetě neanalyzoval, jak přesně ta funkce od toca funguje, tak nevím co s tím textem ta funkce provede.. Any idea?
EDIT: přidávám funkci truncate z Nette.. třeba by šla nějak upravit..
/**
* Truncates string to maximal length.
* @param string UTF-8 encoding
* @param int
* @param string UTF-8 encoding
* @return string
*/
public static function truncate($s, $maxLen, $append = "\xE2\x80\xA6")
{
if (iconv_strlen($s, 'UTF-8') > $maxLen) {
$maxLen = $maxLen - iconv_strlen($append, 'UTF-8');
if ($maxLen < 1) {
return $append;
} elseif (preg_match('#^.{1,'.$maxLen.'}(?=[\s\x00-@\[-`{-~])#us', $s, $matches)) {
return $matches[0] . $append;
} else {
return iconv_substr($s, 0, $maxLen, 'UTF-8') . $append;
}
}
return $s;
}
Editoval Endrju (11. 3. 2010 1:14)
Offline
#9 11. 3. 2010 1:24
- Ondřej Mirtes
- Moderator

- Místo: Praha
- Registrovaný: 8. 1. 2009
- Příspěvky: 1357
- Web
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Aha, nevšim jsem si, že toka tady uveřejnil svůj helper. Změnil bych v něm tuto řádku:
$tag = substr(strtok($object[0][0], " \t\n\r\0\x0B>"), 1);
na tuto:
$tag = mb_substr(strtok($object[0][0], " \t\n\r\0\x0B>"), 1, 1024, 'UTF-8');
Ta hodnota 1024 je maximální možná délka vraceného stringu, kdyžtak si to prodluž. Musel jsem jsem jí tam napsat, protože kýžené kódování je až čtvrtý parametr :o)
Třeba to pomůže.
Offline
#10 11. 3. 2010 1:47
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Diky Ondro, zkusil jsem a ee, pořád stejný problémek..
Jinak ten škaredý znak se zobrazí, i když použiju
iconv_substr s kódováním místo mb_substr.
Nebylo by lepší nějak předělat původní Nette String::truncate? Chtěl bych totiž, aby mi to zachovávalo celá slova (pokud je k dispozici více než jedno slovo) jako to dělá Nettovský truncate. Pokuším se tomu trchu porozumět, ale zadím jsem v podstatě na bodu mrazu. Nevím jak na to.
Editoval Endrju (11. 3. 2010 1:52)
Offline
#11 11. 3. 2010 2:09
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Hm, trochu jsem zkoušel analyzovat ten kód od toca.. jetě ne úplně, ale napadla mě pak jedna věc a zatím jsem nenašel žádnou chybu.
na posledním řádku jsem také zaměnil substr za mb_substr tedy na posledním řádku zaměnit tohle:
return substr($string, 0, $length = min(strlen($string), $length + $i))
za tohle:
return mb_substr($string, 0, $length = min(strlen($string), $length + $i), 'UTF-8')
- ten zbytek na tom řádku tam samozřejmě nechat.
Editoval Endrju (11. 3. 2010 23:49)
Offline
#12 11. 3. 2010 2:18
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Ondřej Mirtes napsal(a): Ta hodnota 1024 je maximální možná délka vraceného stringu, kdyžtak si to prodluž. Musel jsem jsem jí tam napsat, protože kýžené kódování je až čtvrtý parametr :o)
Teď mě napadlo – zkoušel jsem hledat max. délku stringu v proměnné.. – Ondro jsi si jistý, že maximální délka stringu je 1024? http://cz.php.net/…s.string.php
It is no problem for a string to become very large. PHP imposes no boundary on the size of a string; the only limit is the available memory of the computer on which PHP is running.
No a když už je tam třeba dávat nějakou délku, tak možná než tam cpát nějaké vymyšlené číslo a případně si zkrátit vstup by bylo lepší tam dát aspoň délku toho vstupního stringu.
Editoval Endrju (11. 3. 2010 2:21)
Offline
#13 11. 3. 2010 2:46
- iguana007
- Nette guru

- Místo: Praha
- Registrovaný: 3. 11. 2009
- Příspěvky: 265
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
A není možné, že v proměnné $htmlContent uchováváš obsah v nějakém jiném kódóvání než v UTF-8?
Omne Principium Grave
Offline
#14 11. 3. 2010 2:50
- Ondřej Mirtes
- Moderator

- Místo: Praha
- Registrovaný: 8. 1. 2009
- Příspěvky: 1357
- Web
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Endrju: Však jsem řekl, můžeš si tam dát jaké číslo chceš, klidně i vypočtené :)
Offline
#15 11. 3. 2010 3:45
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
okej :).
Jinak to prevedeni na UTF-8 staci pouze na konci u toho return.
public static function truncate($string, $length, $e = "\xE2\x80\xA6", $isHTML = TRUE){
$i = 0;
$tags = array();
if($isHTML) {
preg_match_all('/<[^>]+>([^<]*)/', $string, $match, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
foreach($match as $object) {
if($object[0][1] - $i >= $length) break;
$token = strtok($object[0][0], " \t\n\r\0\x0B>");
$tag = substr($token, 1);
if($tag[0] != '/') $tags[] = $tag;
elseif(end($tags) == substr($tag, 1)) array_pop($tags);
$i += $object[1][1] - $object[0][1];
}
}
return iconv_substr($string, 0, $length = min(strlen($string), $length + $i), 'UTF-8') . (count($tags = array_reverse($tags)) ? '</' . implode('></', $tags) . '>' : '') . (strlen($string) > $length ? $e : '');
}
Asi (dle meho usudku) nebude úplně v pořádku ten regulární výraz. Můžete to někdo zkontrolovat? Nejlépe i odzkoušet?
Nevím proč se mi ve výstupu zobrazuje ten znak ‚<‘? Je to 27. znak ve výstupnímm textu, ale ve vstupním nic takového není! Za čárkou ve vstupním textu následuje rovnou ukonční odstavce..
Pro odzkoušení použijte toto:
<?php echo MyString::truncate($htmlConent, 27); ?>
A jako vstup $htmlConent:
<p style="text-align: justify;">Vážení fotbaloví fanoušci,</p>
<p style="text-align: justify;">vítejte ....</p>
Měli by jste dostat výstup (v prohlížeči):
Vážení fotbaloví fanoušci,<
…
Výstup v HTML:
<p style="text-align: justify;">Vážení fotbaloví fanoušci,<</p>
…
Když zadám zkrácení na 26 znaků, tak se zobrazí Vážení
fotbaloví fanoušci, a ten znak ‚<‘ už tam není, což je
prozměnu v pořádku.
Pak se mi nelíbí, že se trojtečka zobrazuje někdy mimo odstavec. Třeba když zadám 26 znaků a méně, tak se trojtečka zobrazí až za ukončeným odstavcem (předpokládám, že to je problém někde v tom uzavírání nedokončených tagů). Když zadám ale 28 znaků, tak se trojtečka zobrazí hned za textem ještě než se ukončí odstavec:
Vážení fotbaloví fanoušci,…
Html:
<p style="text-align: justify;">Vážení fotbaloví fanoušci,…</p>
Zkuste na to prosím někdo mrknout, trápím se tu s tím už pěkně dlouho a nevím co s tím.
Editoval Endrju (11. 3. 2010 3:57)
Offline
#16 11. 3. 2010 18:58
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Chalani chalani asi malo citate Jakuba Vranu, on uz to riesil a riesil aj problem kodovania.
developing on Arch linux, Apache 2.2.15, PHP-5.3.2 (mod_php5), Mysql 5.1.47 :: www.twitter.com/srigi
Offline
#17 11. 3. 2010 20:15
- Mikulas Dite
- Nette guru

- Místo: Praha
- Registrovaný: 18. 11. 2009
- Příspěvky: 320
- Web
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Nedalo mi to a napsal jsem vylepšenou verzi toho svého helperu. Nyní
perfektrně zvládá rozeznávat html tagy, neselže ani na <p
id=">">, používá mb knihovny, započítává
délku suffixu do limitu a hlavně, maže prázdné hmtl tagy a
vkládá suffix před poslední element.
<?php
public function truncate($string, $limit)
{
$suffix = ' …';
$tag_pattern = '</?\w+(?:(?:\s+\w+(?:\s*=\s*(?:".*?"|\'.*?\'|[^\'">\s]+))?)+\s*|\s*)/?>';
preg_match_all('~' . $tag_pattern . '~s', $string, $elements);
$text_array = preg_split('~' . $tag_pattern . '~s', $string);
$truncated_by = 0;
while (mb_strlen(implode('', $text_array)) > $limit - mb_strlen($suffix)){
$len = mb_strlen(end($text_array));
$truncated_by += $len;
if ($len < $limit - $truncated_by) {
unset( $text_array[count($text_array)-1] );
unset( $elements[0][count($text_array)-1] );
} else {
$text_array[count($text_array)-1] = mb_substr(end($text_array), 0, $limit - $truncated_by);
}
}
$output = '';
for ($i = 0; $i <= max(array_keys($elements)) || $i <= max(array_keys($text_array)); $i++) {
if (isset ($text_array[$i]))
$output .= $text_array[$i];
if ($i + 1 == max(array_keys($text_array)))
$output .= $suffix;
if (isset($elements[0][$i]))
$output .= $elements[0][$i];
}
return trim($output);
}
?>
Tedy z
<p id=">" style="text-align: justify;">Vážení fotbaloví fanoušci,</p>
<p style="text-align: justify;">vítejte ....</p>
udělá při truncate:30
<p id=">" style="text-align: justify;">Vážení fotbaloví fanoušci, …</p>
Editoval Mikulas Dite (11. 3. 2010 20:17)
Offline
#18 11. 3. 2010 22:36
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Mikulas Dite napsal(a):
Nedalo mi to a napsal jsem vylepšenou verzi toho svého helperu. …
Pekna prace :). Ma to ale asi jeste neco nedoreseneho.. Jednak magicke cislo 27 :)… Zkrat text na 27 znaku a 3 tecky se zobrazi pred zkracovanym textem – pred odstavcem.
…
<p style="text-align: justify;">Vážení fotbaloví fanoušci,</p>
Pro delku 20 prozmenu dostanu: Fatal Error: Maximum execution time of
30 seconds exceeded. Ale jinak pekna prace, ja si zatim netroufnul to
zkusit napsat, takze smekam..
Offline
#19 12. 3. 2010 3:57
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
srigi, diky za ten link.
Zkousel jsem pouzit nejake funkce, ktere tam Jakub Vrana. Konkretne jsem se
rozhodl pouzivat a nasledne upravit (vysledek nebyl 100%) tu „function
xhtml_cut($s, $limit) { ... }“ a „function html_cut($s, $limit)
{ ... }“. Nezobrazoval se ale presny pocet znaku, jaky jsem zadal
(samozrejme jsem odkomentoval tu cast kodu, ktera zpracovava UTF-8). Tudiz jsem
debugoval a zjistil, ze i kdyz budu pouzivat multibyte string funkce, tak pri
prochazeni po znacich budou znaky s diakritikou tak jako tak pocitany jako vice
znaku. Zkusil jsem tedy vsupni retezec preformatovat z UTF-8 na
Windows-1250 pomoci funkce iconv
(jen si ted nejsem jisty, zda je mozne, aby se nejaky UTF-8 znak neprevedl
korektne na Windows-1250 a naopak – nemate nejakou
zkusenost?). Po preformatovani, se pak znaky s diakritikou pocitaji
jako jeden celistvy znak (a i pri debugovani – prochazeni znak po znaku –
se zobrazuji spravne).
Pridana funkcionalita:
- Na zacatku funkce je vstupni retezec preveden z
UTF-8naWindows-1250 - Pridan append (defaultne trojtecka) za zkraceny text (nepovinny parametr
funkce)
- je pridan jeste pred vsemi ukoncovacimi tagy a ostatnimi tagy, ktere jsou za zobrazenym textem. Tedy by se nemelo stat, ze by se append zobrzil za ukoncenym odstavcem, odradkovanim nebo treba vodorovnou carou misto za textem v odstavci.
- Vysledna delka textu je zkracena o delku retezce append, aby sedela maximalni pozdadovana delka zobrazeneho textu
- Pokud je adpped ponechan defaultne na trojtecku, tak jsou z konce retezce odmazany vsechny ostatni tecky, aby nevzniklo treba neco jako „A tak tomu tedy bylo .....“ + trojtecka.
- Nakonec je text preveden zase zpet z Windows-1250 do UTF-8.
Tridu jsem umistil do slozky app/helpers/MyStringHelper.php:
/**
* MyString Helper
*
* @author Endrju
* @package Application
*/
abstract class MyString {
/**
* Truncates string containing XHTML tags to maximal length
* @param string UTF-8 encoding
* @param int
* @param string UTF-8 encoding
* @return string
* @copyright Jakub Vrána, http://php.vrana.cz/
* @author Endrju (modifications)
*/
public static function xhtmlTruncate($s, $maxLen, $append = "\xE2\x80\xA6")
{
// ma vubec smysl retezec zkracovat?
if (iconv_strlen($s, 'UTF-8') > $maxLen) {
// prekodujeme z UTF-8 do windows-1250,
// znaky s diakritikou atp pak budou pocitany jako jeden cely znak
$s = iconv('UTF-8', 'windows-1250//TRANSLIT', $s);
$append = iconv('UTF-8', 'windows-1250//TRANSLIT', $append);
$length = 0;
$tags = array(); // dosud neuzavřené značky
for ($i=0; $i < strlen($s) && $length < $maxLen; $i++) {
switch ($s[$i]) {
case '<':
// načtení značky
$start = $i+1;
while ($i < strlen($s) && $s[$i] != '>' && !ctype_space($s[$i])) {
$i++;
}
$tag = substr($s, $start, $i - $start);
// přeskočení případných atributů
$in_quote = '';
while ($i < strlen($s) && ($in_quote || $s[$i] != '>')) {
if (($s[$i] == '"' || $s[$i] == "'") && !$in_quote) {
$in_quote = $s[$i];
} elseif ($in_quote == $s[$i]) {
$in_quote = '';
}
$i++;
}
if ($s[$start] == '/') { // uzavírací značka
array_shift($tags); // v XHTML dokumentu musí být vždy uzavřena poslední neuzavřená značka
} elseif ($s[$i-1] != '/') { // otevírací značka
array_unshift($tags, $tag);
}
break;
case '&':
$length++;
while ($i < strlen($s) && $s[$i] != ';') {
$i++;
}
break;
default:
$length++;
// V případě kódování UTF-8:
while ($i+1 < strlen($s) && ord($s[$i+1]) > 127 && ord($s[$i+1]) < 192) {
$i++;
}
}
}
// zkratime reztezec o delku $append, pokud neni $apped delsi nez samotny retezec
$s = ($length > strlen($append)) ? substr($s, 0, $i - strlen($append)) : substr($s, 0, $i);
// uzavreme vsechny tagy
$enclosingTags = "";
if ($tags) {
$enclosingTags .= "</" . implode("></", $tags) . ">";
}
// Nyni potrebujeme probublat od konce pres vsechny tagy na konci textu $s,
$s_beforeInnerEnclosingTags = $s;
$innerEnclosingTags = "";
while (substr(rtrim($s_beforeInnerEnclosingTags), - 1, 1) == ">") {
$innerEnclosingTags = strrchr($s_beforeInnerEnclosingTags, "<");
$s_beforeInnerEnclosingTags = substr($s_beforeInnerEnclosingTags, 0, strlen($s_beforeInnerEnclosingTags) - strlen($innerEnclosingTags));
}
// Pokud je nastaven $append na trojtecku,
// orezeme jeste samotne tecky na konci rezce (pokud nejake jsou)
if ($append == iconv('UTF-8', 'windows-1250//TRANSLIT', "\xE2\x80\xA6")) {
$s_beforeInnerEnclosingTags = rtrim($s_beforeInnerEnclosingTags, '.');
}
// Nyni vse spojime dohromady a pridame $append
$s = $s_beforeInnerEnclosingTags . $append . $innerEnclosingTags . $enclosingTags;
// Vystupni retezec prekodovany zpet z windows-1250 do UTF-8
$s = iconv('windows-1250', 'UTF-8//TRANSLIT', $s);
}
return $s;
}
/**
* Truncates string containing HTML tags to maximal length
* @param string UTF-8 encoding
* @param int
* @param string UTF-8 encoding
* @return string
* @copyright Jakub Vrána, http://php.vrana.cz/
* @author Endrju (modifications)
*/
public static function htmlTruncate($s, $maxLen, $append = "\xE2\x80\xA6")
{
// ma vubec smysl retezec zkracovat?
if (iconv_strlen($s, 'UTF-8') > $maxLen) {
static $empty_tags = array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param');
// prekodujeme z UTF-8 do windows-1250,
// znaky s diakritikou atp pak budou pocitany jako jeden cely znak
$s = iconv('UTF-8', 'windows-1250//TRANSLIT', $s);
$append = iconv('UTF-8', 'windows-1250//TRANSLIT', $append);
$length = 0;
$tags = array(); // dosud neuzavřené značky
for ($i=0; $i < strlen($s) && $length < $maxLen; $i++) {
switch ($s{$i}) {
case '<':
// načtení značky
$start = $i+1;
while ($i < strlen($s) && $s{$i} != '>' && !ctype_space($s{$i})) {
$i++;
}
$tag = strtolower(substr($s, $start, $i - $start));
// přeskočení případných atributů
$in_quote = '';
while ($i < strlen($s) && ($in_quote || $s{$i} != '>')) {
if (($s{$i} == '"' || $s{$i} == "'") && !$in_quote) {
$in_quote = $s{$i};
} elseif ($in_quote == $s{$i}) {
$in_quote = '';
}
$i++;
}
if ($s{$start} == '/') { // uzavírací značka
$tags = array_slice($tags, array_search(substr($tag, 1), $tags) + 1);
} elseif ($s{$i-1} != '/' && !in_array($tag, $empty_tags)) { // otevírací značka
array_unshift($tags, $tag);
}
break;
case '&':
$length++;
while ($i < strlen($s) && $s{$i} != ';') {
$i++;
}
break;
default:
$length++;
// V případě kódování UTF-8:
while ($i+1 < strlen($s) && ord($s[$i+1]) > 127 && ord($s[$i+1]) < 192) {
$i++;
}
}
}
// zkratime reztezec o delku $append, pokud neni $apped delsi nez samotny retezec
$s = ($length > strlen($append)) ? substr($s, 0, $i - strlen($append)) : substr($s, 0, $i);
// uzavreme vsechny tagy
$enclosingTags = "";
if ($tags) {
$enclosingTags .= "</" . implode("></", $tags) . ">";
}
// Nyni potrebujeme probublat od konce pres vsechny tagy na konci textu $s,
$s_beforeInnerEnclosingTags = $s;
$innerEnclosingTags = "";
while (substr(rtrim($s_beforeInnerEnclosingTags), - 1, 1) == ">") {
$innerEnclosingTags = strrchr($s_beforeInnerEnclosingTags, "<");
$s_beforeInnerEnclosingTags = substr($s_beforeInnerEnclosingTags, 0, strlen($s_beforeInnerEnclosingTags) - strlen($innerEnclosingTags));
}
// Pokud je nastaven $append na trojtecku,
// orezeme jeste samotne tecky na konci rezce (pokud nejake jsou)
if ($append == iconv('UTF-8', 'windows-1250//TRANSLIT', "\xE2\x80\xA6")) {
$s_beforeInnerEnclosingTags = rtrim($s_beforeInnerEnclosingTags, '.');
}
// Nyni vse spojime dohromady a pridame $append
$s = $s_beforeInnerEnclosingTags . $append . $innerEnclosingTags . $enclosingTags;
// Vystupni retezec prekodovany zpet z windows-1250 do UTF-8
$s = iconv('windows-1250', 'UTF-8//TRANSLIT', $s);
}
return $s;
}
}
Do app/presenters/BasePresenter.php jsem zaregistroval
helpery:
abstract class BasePresenter extends Presenter
{
public $oldLayoutMode = FALSE;
public $oldModuleMode = FALSE;
protected function beforeRender()
{
$this->template->registerHelper('xhtmlTruncate', array('MyString', 'xhtmlTruncate'));
$this->template->registerHelper('htmlTruncate', array('MyString', 'htmlTruncate'));
}
}
Pouziti pak v jakekoli sablone napr:
{block content}
<div id="xhtmlContent">{!$newsItem->content|xhtmlTruncate:300}</div>
<div id="htmlContent">{!$newsItem->content|htmlTruncate:300}</div>
{/block}
Premyslel jsem taky jak docilit toho, aby se zkracovala cela slova – aby to nezkracovalo v pulce slova (pokud v retezci teda neni jen jedine slovo). Tedy presne tak, jak funguje Nette\String::truncate()
Bohuzel jsem narazil na problem, ze kdyz jsem zkracoval text o zbytky slov, tak se napriklad stalo, ze nebyly odstraneny tagy, ktere to slovo obaluji a pak mi to rozhodilo layout nebo narusilo jine tagy.. Kdyby jste si s tim nekdo zkusili pohrat a prijit na to, tak by to bylo strasne fajn :).
Jinak diky vsem za pomoc :)
Editoval Endrju (12. 3. 2010 18:28)
Offline
#20 12. 3. 2010 8:00
- zacatecnik
- Člen
- Registrovaný: 27. 10. 2009
- Příspěvky: 81
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
uff, todle je už pro mě vyšší dívčí… Ale záleží na html vs xhtml.. Dobře to popsal Jakub Vrána. http://php.vrana.cz/…znackami.php
Offline
#21 12. 3. 2010 18:24
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Editoval jsem svuj predchozi post + znacne upravil kod a pridal tam i upravenou funkci pro HtmlTruncate. Testoval jsem obe funkce na vstupech, ktere vygeneroval CKEditor a vysledek byl naprosto stejny.
zacatecnik: Funkce kterou zde v komentarich postnul „Mike“ nefunguje. On na zacatku funkce zkrati cely text na pozadovanou delku (nebere v potazt to, ze tam muzou byt HTML znacky a ze tim prichazi o zobrazovany text. Pak v tom co mu zbylo najde posledni mezeru v domeni ze je to posledni slovo zobrazeneho textu, tak to co predchazi te mezere pak pusti dal do funkce. No a v nejhorsim pripade pusti do funkce jen cast nejake HTML znacky s parametry a zadny text..
Editoval Endrju (12. 3. 2010 18:26)
Offline
#22 13. 3. 2010 3:02
- Endrju
- Člen

- Místo: Ostrava
- Registrovaný: 31. 10. 2009
- Příspěvky: 131
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
No nedalo mi to a do ted jsem na tom sedel… :-). Jednak tam byly jeste nejake nedostatky a ja to chtel funkcni v podstate uplne stejne jako Nette\String::truncate(), coz se mi nakonec, huraaaa, povedlo :-).
Mozna se budu castecne opakovat, ale kdyz uz je to (doufam) funkcni, tak at
je to pohromade.. Funkce ma tri parametry, stejne jako jste zvykli u
String::truncate($s, $maxLen, $append = "\xE2\x80\xA6") a funguje
to uplne stejne, s tim rozdilem, ze jako vstup nedavate plain text, ale (X)HTML
text. Odzkousene to mam na vstupech, ktere generuje CKEditor (ver. 3.1) a pak na pár
co jsem si jen tak zkoušel…
Na pocet radku je to mozna dlouhe, ale hodne delaji ty komentare (zvyk). Coz mi ale za rok treba pomuze rozpomenout jak jsem to delal nebo kdyz by to po me nekdo cetl :-).
Obe metody xhtmlTruncate a htmlTruncate funguji
stejne:
- Pridan
append(defaultne trojtecka) za zkraceny text (nepovinny parametr funkce).- je pridan jeste pred vsechny ukoncovaci tagy a ostatnimi tagy, ktere jsou za
zobrazenym textem. Tedy by se nemelo stat, ze by se
appendzobrzil za ukoncenym odstavcem, odradkovanim nebo treba vodorovnou carou misto za textem v odstavci.
- je pridan jeste pred vsechny ukoncovaci tagy a ostatnimi tagy, ktere jsou za
zobrazenym textem. Tedy by se nemelo stat, ze by se
- Vysledna delka textu je zkracena o delku retezce
append, aby sedela maximalni pozdadovana delka zobrazeneho textu. - Pokud je
appendponechan defaultne na trojtecku, tak jsou z konce retezce odmazany vsechny ostatni tecky, aby nevzniklo treba neco jako „A tak tomu tedy bylo .....“ + trojtecka. - Zkracovana jsou cela slova, ale tak aby nebyla prekrocena maximalni
pozadovana delka textu.
- Jako separatory pro oddelovani slov jsem zvolil tyto (muzete si je
upravit):
$separators = array (' ', ',', '.', ';', '?', '!', ':');- Dva a vice stejnych separatoru bezprostredne za sebou nejsou brany jako separatory (zduvodneno je to v kodu v komentarich)
- Pokud zustava jen posledni slovo k zobrazeni, je zkracovano po znacich.
- Jako separatory pro oddelovani slov jsem zvolil tyto (muzete si je
upravit):
To je asi vsechno, pokud jsem na neco nezapomel.
Tridu jsem umistil do slozky app/helpers/MyStringHelper.php:
/**
* MyString Helper
*
* @author Endrju
* @package Application
*/
abstract class MyString {
/**
* Truncates string containing XHTML tags to maximal length
* @param string UTF-8 encoding
* @param int
* @param string UTF-8 encoding
* @return string
* @copyright Jakub Vrána, http://php.vrana.cz/
* @author Endrju (modifications)
*/
public static function xhtmlTruncate($s, $maxLen, $append = "\xE2\x80\xA6")
{
// ma vubec smysl retezec zkracovat?
if (iconv_strlen($s, 'UTF-8') > $maxLen) {
// zkratime $maxLen o delku $append
$maxLen = $maxLen - iconv_strlen($append, 'UTF-8');
// pokud je nyni $maxLen kratsi bez $appedm vratime samotonty $append
if ($maxLen < iconv_strlen($append, 'UTF-8')) {
return $append;
}
// vybrane znaky, ktere muzou ukoncovat vetu nebo vyznam casti vety
$separators = array (' ', ',', '.', ';', '?', '!', ':');
$pos = 0; // pozice posledniho nalezeneho separatoru
// prekodujeme z UTF-8 do windows-1250,
// znaky s diakritikou atp pak budou pocitany jako jeden cely znak
$s = iconv('UTF-8', 'windows-1250//TRANSLIT', $s);
$INITAL_S = $s; // originalni vstupni retezec $s, ktery nebude po dobu behu programu zmenen.
$append = iconv('UTF-8', 'windows-1250//TRANSLIT', $append);
// odstranime neviditelne znaky,
// ktere se ve vygenerovanem a zobrazenem HTML textu stejne nezobrazi
$customWhitespaces = array("\0x09", "\0x0A", "\0x0D", "\0x00", "\0x0B");
foreach ($customWhitespaces AS $customWhitespace) {
$s = trim($s, $customWhitespace);
}
$length = 0;
$tags = array(); // dosud neuzavřené značky
for ($i=0; $i < strlen($s) && $length < $maxLen; $i++) {
switch ($s[$i]) {
case '<':
// načtení značky
$start = $i+1;
while ($i < strlen($s) && $s[$i] != '>' && !ctype_space($s[$i])) {
$i++;
}
$tag = strtolower(substr($s, $start, $i - $start));
// přeskočení případných atributů
$in_quote = '';
while ($i < strlen($s) && ($in_quote || $s[$i] != '>')) {
if (($s[$i] == '"' || $s[$i] == "'") && !$in_quote) {
$in_quote = $s[$i];
} elseif ($in_quote == $s[$i]) {
$in_quote = '';
}
$i++;
}
if ($s[$start] == '/') { // uzavírací značka
array_shift($tags); // v XHTML dokumentu musí být vždy uzavřena poslední neuzavřená značka
} elseif ($s[$i-1] != '/') { // otevírací značka
array_unshift($tags, $tag);
}
break;
case '&':
$length++;
while ($i < strlen($s) && $s[$i] != ';') {
$i++;
}
break;
default:
$length++;
/* V případě kódování UTF-8:
while ($i+1 < strlen($s) && ord($s[$i+1]) > 127 && ord($s[$i+1]) < 192) {
$i++;
}*/
// je znak separatorem?
if (in_array($s[$i], $separators)) {
// * a neni nasledujici (nebo predchozi) znak totozny,
// jako nyni nacteny separator?
if (($s[$i] != $s[$i+1]) && ($s[$i-1] != $s[$i])) {
$pos = $i; // pak ulozime pozici separatoru
} // nakonec tak ziskame pozici posledniho separatoru
// * tou druhou podminkou chceme zachytit pripady, kdy je v textu
// nekolik separatotu (napr. tecek) za sebou, pak to nebudeme povazovat za separator,
// ale jako vyznam k predchazejicimu slovu (vete).
// Navic pokud by takovy separator byl na konci oriznuteho textu, bude tak v podstate
// nahrazen volitelnym retezcem $append (defaultne trojtecka).
}
}
}
// pokud nenalezneme hledany pocet znaku, obsah je nejspis slozen ciste z HTML tagu
// (napr. flashova videa a jine medialni objekty)
if ($length >= $maxLen) {
$s = substr($s, 0, $i);
// uzavreme vsechny tagy
$enclosingTags = "";
if ($tags) {
$enclosingTags .= "</" . implode("></", $tags) . ">";
}
// Nyni potrebujeme probublat od konce pres vsechny tagy az na konec zobrazovaneho textu $s
// (tam pak budeme pridavat $append)
$s_beforeInnerEnclosingTags = $s;
$innerEnclosingTags = "";
while (substr(rtrim($s_beforeInnerEnclosingTags), - 1, 1) == ">") {
$innerEnclosingTags = strrchr($s_beforeInnerEnclosingTags, "<");
$s_beforeInnerEnclosingTags = substr($s_beforeInnerEnclosingTags, 0, strlen($s_beforeInnerEnclosingTags) - strlen($innerEnclosingTags));
}
// Pokud je nastaven $append na trojtecku,
// orezeme jeste samotne tecky na konci rezce (pokud nejake jsou)
if ($append == iconv('UTF-8', 'windows-1250//TRANSLIT', "\xE2\x80\xA6")) {
$s_beforeInnerEnclosingTags = rtrim($s_beforeInnerEnclosingTags, '.');
}
// pokud byl nejaky separator nalezen
// a zaroven znak za zkracovanym textem neni separatorem
if (($pos > 0) && (!in_array(substr($INITAL_S, strlen($s_beforeInnerEnclosingTags), 1), $separators))) {
// tak orizneme text za poslednim nalezenym separatorem
$s_beforeInnerEnclosingTags = substr($s_beforeInnerEnclosingTags, 0, $pos);
}
// nebo take pokud byl nejaky separator nalezen
// a zaroven 2 znaky za zkracovanym textem jsou 2 stejne separatory (viz. * o neco vyse - stejny pripad)
else if (($pos > 0) && (in_array(substr($INITAL_S, strlen($s_beforeInnerEnclosingTags), 1), $separators)) && ((substr($INITAL_S, strlen($s_beforeInnerEnclosingTags), 1) == ((substr($INITAL_S, strlen($s_beforeInnerEnclosingTags) + 1, 1)))))) {
// tak orizneme text za poslednim nalezenym separatorem a dva vyse zminene ignorujeme
$s_beforeInnerEnclosingTags = substr($s_beforeInnerEnclosingTags, 0, $pos);
}
// Nyni vse spojime dohromady a pripojime $append
$s = $s_beforeInnerEnclosingTags . $append . $innerEnclosingTags . $enclosingTags;
}
// Vystupni retezec prekodujeme zpet z windows-1250 do UTF-8
$s = iconv('windows-1250', 'UTF-8//TRANSLIT', $s);
}
return $s;
}
/**
* Truncates string containing HTML tags to maximal length
* @param string UTF-8 encoding
* @param int
* @param string UTF-8 encoding
* @return string
* @copyright Jakub Vrána, http://php.vrana.cz/
* @author Endrju (modifications)
*/
public static function htmlTruncate($s, $maxLen, $append = "\xE2\x80\xA6")
{
// ma vubec smysl retezec zkracovat?
if (iconv_strlen($s, 'UTF-8') > $maxLen) {
// zkratime $maxLen o delku $append
$maxLen = $maxLen - iconv_strlen($append, 'UTF-8');
// pokud je nyni $maxLen kratsi bez $appedm vratime samotonty $append
if ($maxLen < iconv_strlen($append, 'UTF-8')) {
return $append;
}
static $empty_tags = array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param');
// vybrane znaky, ktere muzou ukoncovat vetu nebo vyznam casti vety
$separators = array (' ', ',', '.', ';', '?', '!', ':');
$pos = 0; // pozice posledniho nalezeneho separatoru
// prekodujeme z UTF-8 do windows-1250,
// znaky s diakritikou atp pak budou pocitany jako jeden cely znak
$s = iconv('UTF-8', 'windows-1250//TRANSLIT', $s);
$INITAL_S = $s; // originalni vstupni retezec $s, ktery nebude po dobu behu programu zmenen.
$append = iconv('UTF-8', 'windows-1250//TRANSLIT', $append);
// odstranime neviditelne znaky,
// ktere se ve vygenerovanem a zobrazenem HTML textu stejne nezobrazi
$customWhitespaces = array("\0x09", "\0x0A", "\0x0D", "\0x00", "\0x0B");
foreach ($customWhitespaces AS $customWhitespace) {
$s = trim($s, $customWhitespace);
}
$length = 0;
$tags = array(); // dosud neuzavřené značky
for ($i=0; $i < strlen($s) && $length < $maxLen; $i++) {
switch ($s[$i]) {
case '<':
// načtení značky
$start = $i+1;
while ($i < strlen($s) && $s[$i] != '>' && !ctype_space($s[$i])) {
$i++;
}
$tag = strtolower(substr($s, $start, $i - $start));
// přeskočení případných atributů
$in_quote = '';
while ($i < strlen($s) && ($in_quote || $s[$i] != '>')) {
if (($s[$i] == '"' || $s[$i] == "'") && !$in_quote) {
$in_quote = $s[$i];
} elseif ($in_quote == $s[$i]) {
$in_quote = '';
}
$i++;
}
if ($s{$start} == '/') { // uzavírací značka
$tags = array_slice($tags, array_search(substr($tag, 1), $tags) + 1);
} elseif ($s{$i-1} != '/' && !in_array($tag, $empty_tags)) { // otevírací značka
array_unshift($tags, $tag);
}
break;
case '&':
$length++;
while ($i < strlen($s) && $s[$i] != ';') {
$i++;
}
break;
default:
$length++;
/* V případě kódování UTF-8:
while ($i+1 < strlen($s) && ord($s[$i+1]) > 127 && ord($s[$i+1]) < 192) {
$i++;
}*/
// je znak separatorem?
if (in_array($s[$i], $separators)) {
// * a neni nasledujici (nebo predchozi) znak totozny,
// jako nyni nacteny separator?
if (($s[$i] != $s[$i+1]) && ($s[$i-1] != $s[$i])) {
$pos = $i; // pak ulozime pozici separatoru
} // nakonec tak ziskame pozici posledniho separatoru
// * tou druhou podminkou chceme zachytit pripady, kdy je v textu
// nekolik separatotu (napr. tecek) za sebou, pak to nebudeme povazovat za separator,
// ale jako vyznam k predchazejicimu slovu (vete).
// Navic pokud by takovy separator byl na konci oriznuteho textu, bude tak v podstate
// nahrazen volitelnym retezcem $append (defaultne trojtecka).
}
}
}
// pokud nenalezneme hledany pocet znaku, obsah je nejspis slozen ciste z HTML tagu
// (napr. flashova videa a jine medialni objekty)
if ($length >= $maxLen) {
$s = substr($s, 0, $i);
// uzavreme vsechny tagy
$enclosingTags = "";
if ($tags) {
$enclosingTags .= "</" . implode("></", $tags) . ">";
}
// Nyni potrebujeme probublat od konce pres vsechny tagy az na konec zobrazovaneho textu $s
// (tam pak budeme pridavat $append)
$s_beforeInnerEnclosingTags = $s;
$innerEnclosingTags = "";
while (substr(rtrim($s_beforeInnerEnclosingTags), - 1, 1) == ">") {
$innerEnclosingTags = strrchr($s_beforeInnerEnclosingTags, "<");
$s_beforeInnerEnclosingTags = substr($s_beforeInnerEnclosingTags, 0, strlen($s_beforeInnerEnclosingTags) - strlen($innerEnclosingTags));
}
// Pokud je nastaven $append na trojtecku,
// orezeme jeste samotne tecky na konci rezce (pokud nejake jsou)
if ($append == iconv('UTF-8', 'windows-1250//TRANSLIT', "\xE2\x80\xA6")) {
$s_beforeInnerEnclosingTags = rtrim($s_beforeInnerEnclosingTags, '.');
}
// pokud byl nejaky separator nalezen
// a zaroven znak za zkracovanym textem neni separatorem
if (($pos > 0) && (!in_array(substr($INITAL_S, strlen($s_beforeInnerEnclosingTags), 1), $separators))) {
// tak orizneme text za poslednim nalezenym separatorem
$s_beforeInnerEnclosingTags = substr($s_beforeInnerEnclosingTags, 0, $pos);
}
// nebo take pokud byl nejaky separator nalezen
// a zaroven 2 znaky za zkracovanym textem jsou 2 stejne separatory (viz. * o neco vyse - stejny pripad)
else if (($pos > 0) && (in_array(substr($INITAL_S, strlen($s_beforeInnerEnclosingTags), 1), $separators)) && ((substr($INITAL_S, strlen($s_beforeInnerEnclosingTags), 1) == ((substr($INITAL_S, strlen($s_beforeInnerEnclosingTags) + 1, 1)))))) {
// tak orizneme text za poslednim nalezenym separatorem a dva vyse zminene ignorujeme
$s_beforeInnerEnclosingTags = substr($s_beforeInnerEnclosingTags, 0, $pos);
}
// Nyni vse spojime dohromady a pripojime $append
$s = $s_beforeInnerEnclosingTags . $append . $innerEnclosingTags . $enclosingTags;
}
// Vystupni retezec prekodujeme zpet z windows-1250 do UTF-8
$s = iconv('windows-1250', 'UTF-8//TRANSLIT', $s);
}
return $s;
}
}
Do app/presenters/BasePresenter.php jsem zaregistroval
helpery:
abstract class BasePresenter extends Presenter
{
public $oldLayoutMode = FALSE;
public $oldModuleMode = FALSE;
protected function beforeRender()
{
$this->template->registerHelper('xhtmlTruncate', array('MyString', 'xhtmlTruncate'));
$this->template->registerHelper('htmlTruncate', array('MyString', 'htmlTruncate'));
}
}
No a pak v sablonach (ted uz z vesela :-)) lze pouzivat:
{block content}
<div id="content">{!$newsItem->content|xhtmlTruncate:400}</div>
<!-- nebo -->
<div id="content">{!$newsItem->content|htmlTruncate:400}</div>
{/block}
Tak.. a je to, diky vsem za spolupraci a popostuchovani :-). Bylo by dobre, kdyby jste to otestovali a chyby pripadne napsali.
Offline
#23 16. 4. 2010 19:30
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
hoj, stalo se vam nekomu, ze vam to orezava prvni znak? mam zdrojovy texy v texy, ten prozenu parserem a na vyplivnute xHTML aplikuju truncate… akorat ze v nekterych pripadech mi to odrizne prvni pismeno… zkusim vysledovat nejaky duvod…
Offline
#24 16. 4. 2010 20:26
- Honza Kuchař
- Moderator

- Místo: Brno
- Registrovaný: 12. 8. 2007
- Příspěvky: 1285
- Web
Re: {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)
Endrju napsal(a): …
Vypadá to dobře. Nechceš to přidat do extras? :-)
Offline
- Úvodní stránka
- » Obecná diskuse
- » {!$htmlConent|truncate:30} Jak ořezat jen text (ignorovat HTML tagy)


