PDA

Bekijk Volledige Versie : Re: [CSS/JS] Kleuren dmv tekstherkenning



Warden Dave
02/06/06, 21:40
"Peter Hunt" <news@peterhunt.zoetermeernet.nl> wrote:

> Beste mensen,

Peter,

<knip>
> PHP moet dan (al dan niet mbv javascript) zeggen :
>
>
1234567 20:01:19 02-06-06 Het wordt vandaag 20 graden en het gaat
> sneeuwen
>
> <td class="code"><span id="item1">1234567</span> <span id="item2">20:01:19
> 02-06-06</span>
> Het wordt vandaag 20 graden en het gaat sneeuwen</td>

Dat is ook m.b.v. PHP niet zo heel lastig. als ik even vlot een voorbeeldje
geef:

<?php

$str = <<<EOD
1234567 20:01:19 02-06-06 Het wordt vandaag 20 graden in de sneeuw
2345678 20:01:19 03-06-06 Het wordt vandaag -2 graden met veel zon
EOD;

echo "<table border='1'>";

if (preg_match_all("/(\d+)\s+(\d+:\d+:\d+\s+\d+-\d+-\d+)\s+(.*)/",
$str, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match)
echo "<tr><td class='code'>",
"<span id='item1'>{$match[1]}</span> ",
"<span id='item2'>{$match[2]}</span> ",
htmlspecialchars($match[3]), "</td></tr>\n";
}

echo "</table>";

?>


Maar dit is meer een vraag voor NG nl.internet.www.server-side...
Groep toegevoegd, f'up gezet.

WD

Peter Hunt
02/06/06, 22:20
WD,

Long time ago, geen verrassing dat juist jij hier (weer) op reageert ;-)

>>
1234567 20:01:19 02-06-06 Het wordt vandaag 20 graden en het gaat sneeuwen

> Dat is ook m.b.v. PHP niet zo heel lastig. als ik even vlot een voorbeeldje geef:

> if (preg_match_all("/(\d+)\s+(\d+:\d+:\d+\s+\d+-\d+-\d+)\s+(.*)/",
> $str, $matches, PREG_SET_ORDER)) {
> foreach ($matches as $match)
> echo "<tr><td class='code'>",
> "<span id='item1'>{$match[1]}</span> ",
> "<span id='item2'>{$match[2]}</span> ",
> htmlspecialchars($match[3]), "</td></tr>\n";
> }

Ik zie dat jij uitgaat van vaste blokken op vaste plekken. Stel nu dat iemand een steek laat vallen
of een tekst plaatst die niet gekleurd hoeft te worden. Het gaat mij erom dat het script item-1
alleen detecteert indien deze :

- 7 cijferig is (geen letters)
- aan het begin van de regel staat

Item-2 (tijd/datum) is al een stuk eenvoudiger, zo'n formaat maak je niet zomaar per ongeluk.

Stel nu echter dat er zoiets wordt geplaatst :

1234567 Lekker weertje vandaag, nietwaar?

Dan is er alleen sprake van item-1 en een "rest" tekst die geen apart ID hoeft te krijgen.

Theoretisch zou er dus ook een regel kunnen verschijnen met alleen tijd/datum, niet dat
dat snel zal gebeuren, maar het zou wel voor kunnen komen. Verder kunnen er nog een
aantal standaard woorden (case sensitive) in voorkomen waaraan ik in een later stadium
ook graag een apart ID zou willen toekennen, voorbeeld : ONWEER.

1234567 20:01:19 02-06-06 Het wordt vandaag 20 graden met kans op ONWEER

In dat voorbeeld hebben we item-1, item-2 en ONWEER als laten we zeggen, item-3.
Bij het laatste item is al duidelijker te zien dat (in principe) geen enkel item een vaste
plek heeft en niet noodzakelijkerwijs in elke regel hoeft voor te komen...

Is het zo iets duidelijker?

Groeten, Peter.

Peter Hunt
03/06/06, 13:40
WD,

Ik ben even op zoek gegaan naar de juiste .php file en ik kom hier uit :

function bbencode_second_pass_code($text, $uid, $bbcode_tpl)
{
global $lang;

$code_start_html = $bbcode_tpl['code_open'];
$code_end_html = $bbcode_tpl['code_close'];

// First, do all the 1st-level matches. These need an htmlspecialchars() run,
// so they have to be handled differently.
$match_count = preg_match_all("#\[code:1:$uid\](.*?)\[/code:1:$uid\]#si", $text, $matches);

for ($i = 0; $i < $match_count; $i++)
{
$before_replace = $matches[1][$i];
$after_replace = $matches[1][$i];

// Replace 2 spaces with "&nbsp; " so non-tabbed code indents without making huge long lines.
$after_replace = str_replace(" ", "&nbsp; ", $after_replace);
// now Replace 2 spaces with " &nbsp;" to catch odd #s of spaces.
$after_replace = str_replace(" ", " &nbsp;", $after_replace);

// Replace tabs with "&nbsp; &nbsp;" so tabbed code indents sorta right without making huge long lines.
$after_replace = str_replace("\t", "&nbsp; &nbsp;", $after_replace);

// now Replace space occurring at the beginning of a line
$after_replace = preg_replace("/^ {1}/m", '&nbsp;', $after_replace);

$str_to_match = "[code:1:$uid]" . $before_replace . "[/code:1:$uid]";

$replacement = $code_start_html;
$replacement .= $after_replace;
$replacement .= $code_end_html;

$text = str_replace($str_to_match, $replacement, $text);
}

// Now, do all the non-first-level matches. These are simple.
$text = str_replace("[code:$uid]", $code_start_html, $text);
$text = str_replace("[/code:$uid]", $code_end_html, $text);

return $text;

} // bbencode_second_pass_code()

Hier worden al een paar replacements gedaan (het gaat dus om de tekst in een code-kader)
en hier zal de mod dus ook terecht moeten komen. Nogmaals, jij gaat uit van 1 lang blok,
terwijl ik elke item liever apart zoek en vervang, het zal dan +- zoiets worden :

ITEM-1 : if (preg_match_all("/^\d{7}", $str, $matches, PREG_SET_ORDER))
(7-cijferig, alleen aan het begin van de regel)

ITEM-2 : if (preg_match_all("\d{2}:\d{2}:\d{2} \d{2}-\d{2}-\d{2}", $str, $matches, PREG_SET_ORDER))
(iets aangepast, maar nog steeds HH:MM:SS DD-MM-YY als het goed is)

Deze moeten dan eveneens door een preg_replace neem ik aan, zoiets :

$after_replace = preg_replace("<span id='item1'>{$match}</span>", "{$match}", $after_replace);

Het idee wordt steeds duidelijker, maar misschien kun je me wat meer in de juiste
richting wijzen. Testen is helaas wat lastiger omdat het een forum betreft waarvan
ik zelf de admin niet ben en dus niet direkt kan uploaden en zien hoe een en ander
functioneert, maar dat moet het probleem niet zijn...

Groeten, Peter.

Peter Hunt
03/06/06, 13:40
> Hier worden al een paar replacements gedaan (het gaat dus om de tekst in een code-kader)
> en hier zal de mod dus ook terecht moeten komen.

Wellicht ten overvloede, maar ik neem aan dat de mod dan in het loopje terecht
moet komen alwaar oa ook de ' ' -> '&nbsp' replacements gedaan worden...

Groeten, Peter.

Warden Dave
04/06/06, 13:40
"Peter Hunt" <news@peterhunt.zoetermeernet.nl> wrote:

> WD,

Peter,

<knip | voorbeeld>
> Ik zie dat jij uitgaat van vaste blokken op vaste plekken.

Eh, ja, ik gaf maar een klein voorzetje voor de complete server-side
hulptroepen [...]. Ik wist al dat ik zelf dit weekeinde slechts 1 a 2 keer
achter een computer zou kruipen om wat postbusjes te legen; en weinig
meer... Maar goed, het voorbeeldje had ook 1 of 2 vervangingen kunnen zijn
in losse tekst. Bijv.:

$str = <<<EOD
Het weerbericht van de komende dagen is...
1234567 20:01:19 02-06-06 Het wordt vandaag 20 graden en het sneeuwt
2345678 20:01:19 03-06-06 Het wordt vandaag -2 graden en de zon schijnt
Vergeet dus niet sneeuwschoenen en zonnebrandolie mee te nemen!
EOD;

$count = 0;
$str = preg_replace(
"/\s*(\d{7})\s+(\d{1,2}:\d{1,2}:\d{1,2}\s+\d{1,2}-\d{1,2}-\d{1,2})\s+(.*)/",
"<tr><td class='code'>" .
"<span id='item1'>$1</span> " .
"<span id='item2'>$2</span> " .
"$3</td></tr>", htmlspecialchars($str), -1, $count);

if ($count)
$str = preg_replace(
array(
"|(?<!</tr>)\s*<tr>|m",
"|</tr>(?!\s*<tr>)|m"
),
array(
"\n<table border='1'><tr>",
"</tr>\n</table>\n"
), $str);

echo $str;

?>

> Stel nu dat iemand een steek laat vallen of een tekst plaatst die niet
> gekleurd hoeft
> te worden. Het gaat mij erom dat het script item-1 alleen detecteert
> indien deze :
>
> - 7 cijferig is (geen letters)
> - aan het begin van de regel staat
>
> Item-2 (tijd/datum) is al een stuk eenvoudiger, zo'n formaat maak je niet
> zomaar per
> ongeluk.
>
> Stel nu echter dat er zoiets wordt geplaatst :
>
> 1234567 Lekker weertje vandaag, nietwaar?
>
> Dan is er alleen sprake van item-1 en een "rest" tekst die geen apart ID
> hoeft te krijgen.
>
> Theoretisch zou er dus ook een regel kunnen verschijnen met alleen
> tijd/datum, niet
> dat dat snel zal gebeuren, maar het zou wel voor kunnen komen. Verder
> kunnen er
> nog een aantal standaard woorden (case sensitive) in voorkomen waaraan ik
> in een
> later stadium ook graag een apart ID zou willen toekennen, voorbeeld :
> ONWEER.

Ah, dan is het zo simpel als bijv. 'preg_replace' met 2 arrays los te laten
op de string. Je kunt dat in 't zojuist gegeven voorbeeld zien. Maar wat je
dan wel mag zeggen is of die elementen met CLASS- danwel ID attribuut ook
echt in een tabel moeten komen zoals je in je eerste bericht suggereerde.
Een serie losse vervangingen (bijv. "1234567" => "<span
class='theId'>1234567</span>") is iets simpeler dan een tabel met optionele
cellen. Ook mag je zeggen of de tags '
' en '' ook echt aanwezig
zullen zijn of dat dat in je bericht slechts was om voor de lezer de string
te markeren (ik zie die tags ook in script in 1 van je andere berichten).
Met deze extra informatie is het simpel een passend voorbeeld te geven...

WD

Peter Hunt
04/06/06, 14:20
WD,

No offense, maar volgens mij wil jij het mooier maken dan noodzakelijk
en daarmee ook iets ingewikkelder. Want als ik kijk naar de voorbeelden
die ik op het WWW kan vinden en de bestaande PHP code dan denk ik
aardig in de richting te kunnen komen, maar jouw code gaat mij vervolgens
een paar stappen te ver.

Ik denk dus (ja sorry, zelfs dat weet ik niet zeker) te weten waar deze
aanpassing moet komen, op het punt waar de
* gecheckt
wordt op htmlspecialchars :

// First, do all the 1st-level matches. These need an htmlspecialchars() run,
// so they have to be handled differently.
$match_count = preg_match_all("#\[code:1:$uid\](.*?)\[/code:1:$uid\]#si", $text, $matches);

$matches gaat vervolgens door een loopje heen zoals in mijn vorige posting te zien was,
als ik het goed begrijp handelt dit loopje alle blokken
* af met de daarin
aanwezige tekst.

for ($i = 0; $i < $match_count; $i++)

Elke $match_count betreft dus een code-blok als ik me niet vergis en in feite
zou er dan in die loop NOG een loop moeten komen die scant naar de items
die ik wil aanpassen. Elk item kan er immers meerdere malen in voorkomen.

Wat ik vervolgens wil is niet meer dan :

Zoeken naar $string (bijvoorbeeld "/^\d{7}" -> 7 getallen aan het begin van de regel?)
Vervang $string door "<span id="item1">$string</span>, dus jouw TD's en TR's zijn
in dit geval overbodig.

Hopelijk is het zo weer wat duidelijker :)

Groeten, Peter.

Warden Dave
04/06/06, 15:00
"Peter Hunt" <news@peterhunt.zoetermeernet.nl> wrote:

(Even kort nu...)

> Zoeken naar $string (bijvoorbeeld "/^\d{7}" -> 7 getallen aan het begin
> van de regel?)
> Vervang $string door "<span id="item1">$string</span>, dus jouw TD's en
> TR's zijn
> in dit geval overbodig.
>
> Hopelijk is het zo weer wat duidelijker :)

Jawel, en zoals ik zei kun je dan wellicht ook toe met wat losse
vervangingen. Je kunt aan het einde van die string-bewerkings-functie dan
ook iets toevoegen als (als test bijv. na '// Now, do all the
non-first-level matches....'):

$text = preg_replace(
array(
"/\n(\d{7})/",
"/(\d{1,2}:\d{1,2}:\d{1,2}\s+\d{1,2}-\d{1,2}-\d{1,2})/"
),
array(
"<span class='theId'>$1</span>",
"<span class='theDate'>$1</span>"
), $text);

... om wellicht al een resultaat te verkrijgen dat goed genoeg is. Je kunt
naar believen zoekpatronen+vervangstrings toevoegen. Je kunt zoekpatronen
laten beginnen met bijv. iets als "\n\d{7}.+?" als je regels die niet
beginnen met de 7-cijferige code wilt laten overslaan.

groet,
WD

Peter Hunt
04/06/06, 15:00
> $text = preg_replace(
> array(
> "/\n(\d{7})/",
> "/(\d{1,2}:\d{1,2}:\d{1,2}\s+\d{1,2}-\d{1,2}-\d{1,2})/"
> ),
> array(
> "<span class='theId'>$1</span>",
> "<span class='theDate'>$1</span>"
> ), $text);

Ok dit ziet er al wat (voor mij) begrijpelijker uit, ik ga ermee aan de slag.

Nog wel even een vraagje over de tijd+datum. Het getal wat tussen accolades
staat, dat geeft toch het aantal karakters aan? Betekent 1,2 dat het 1 of 2
karakters kan zijn? In mijn geval zou dit altijd 2 kunnen zijn, want als het
9 uur in de ochtend is, dan wordt daar altijd netjes 09:00:00 van gemaakt,
9:00:00 zal in principe nooit voorkomen...

Groeten, Peter.

Warden Dave
04/06/06, 15:00
"Peter Hunt" <news@peterhunt.zoetermeernet.nl> wrote:
> WD:

>> $text = preg_replace(
>> array(
>> "/\n(\d{7})/",
>> "/(\d{1,2}:\d{1,2}:\d{1,2}\s+\d{1,2}-\d{1,2}-\d{1,2})/"
>> ),
>> array(
>> "<span class='theId'>$1</span>",
>> "<span class='theDate'>$1</span>"
>> ), $text);
>
> Ok dit ziet er al wat (voor mij) begrijpelijker uit, ik ga ermee aan de
> slag.
>
> Nog wel even een vraagje over de tijd+datum. Het getal wat tussen
> accolades staat, dat geeft toch het aantal karakters aan? Betekent 1,2
> dat het 1 of 2 karakters kan zijn?

Inderdaad.

> In mijn geval zou dit altijd 2 kunnen zijn, want als het 9 uur in de
> ochtend is, dan wordt daar altijd netjes 09:00:00 van gemaakt,
> 9:00:00 zal in principe nooit voorkomen...

Met die zekerheid kun je er "\d{2}" of bijv. "\d\d" van maken.

groet,
WD

Peter Hunt
04/06/06, 15:00
> Met die zekerheid kun je er "\d{2}" of bijv. "\d\d" van maken.

Heel mooi. Nog een vraagje, ik word lastig (als ik dat niet al was) :

Wat is het verschil tussen jouw "/\n(\d{7})/" en "/^\d{7}" ?

Groeten, Peter.

Warden Dave
04/06/06, 15:00
"Peter Hunt" <news@peterhunt.zoetermeernet.nl> wrote:
> WD:

>> Met die zekerheid kun je er "\d{2}" of bijv. "\d\d" van maken.
> Heel mooi. Nog een vraagje, ik word lastig (als ik dat niet al was) :

Je boft dat ik wat post 'moet' beantwoorden met weer andere codevoorbeelden,
anders was ik al weg. ;)

> Wat is het verschil tussen jouw "/\n(\d{7})/" en "/^\d{7}" ?

Zie o.a. http://www.php.net/manual/en/reference.pcre.pattern.syntax.php Er
hoeft geen verschil te zijn (multiline modus) al kan '^' dus ook het begin
van de String aanduiden i.p.v. het begin van een regel.

groet,
WD

Warden Dave
04/06/06, 15:00
"Warden Dave" <warden_dave@mnsys.invalid> wrote:
> Peter Hunt:

>> Wat is het verschil tussen jouw "/\n(\d{7})/" en "/^\d{7}" ?

> Zie o.a. http://www.php.net/manual/en/reference.pcre.pattern.syntax.php
> Er hoeft geen verschil te zijn (zie multiline modus) al kan '^' dus ook
> het
> begin van de String aanduiden i.p.v. het begin van een regel.

btw: Als de code ook helemaal aan het begin van de string komen kan gebruik
je liever '^'.

WD

Peter Hunt
04/06/06, 16:20
> btw: Als de code ook helemaal aan het begin van de string komen kan gebruik je liever '^'.

Ja dat idee had ik al, want dat 7-cijferige getal kan inderdaad aan het begin van de string staan,
bedankt voor de aanvulling!

Groeten, Peter.