Page 1 of 1

Str_replace static text with dynamic text for each result

Posted: Thu Jul 17, 2008 3:59 pm
by enatefox
Hello,

I've yet to find a suitable answer for this:

I have a page that prints from a DB and has active text that a user can modify inline. When the user mouses over, there's a tooltip window with some options and the selected one updates the text in the paragraph

Ex: The patient hurt his (left/right/both) hand.
The tooltip for the parentheses lets the user click one of the three and the sentence updates with the choice.

My problem is this: the text from the DB column has that parenthetical statement and I want to use 'str_replace' to replace the text with a span that activates the tooltip. The trouble is that I need an unique ID for each replacement but 'str_replace' only does one iteration.


The most basic form:

Code: Select all

 
$DB_Column_Text = str_replace("(A/B/C)" , "<span class=ttipshower onmouseover=showtool(this.id) >(A/B/C)</span>" , $DB_Column_Text);
 
My trials and tribulations:

Code: Select all

 
function produceavalue($what) {
     return "<span class=ttipshower onmouseover=showtool(this.id) id=".rand().">$what</span>"
}
$DB_Column_Text = str_replace("(A/B/C)" , produceavalue("(A/B/C)"); , $DB_Column_Text);
 

The bottom example actually does work in that it generates a random element ID however, the 2nd and 3rd elements for some weird reason (user error?) have the same ID but the rest are ok.


Any ideas?

Re: Str_replace static text with dynamic text for each result

Posted: Thu Jul 17, 2008 6:21 pm
by WebbieDave
  1. I'm not sure which platform your using but generating randomness can be troublesome at times. You can try mt_rand() which is superior to rand().
  2. Why must the id's be random numbers? Could you use the primary key of the row as the id? If that's not feasible, what about just using sequential id's?

Re: Str_replace static text with dynamic text for each result

Posted: Fri Jul 18, 2008 7:39 am
by enatefox
I'm not asking this correctly I don't think:

I've got a row from a database that prints a title and body text (2 columns). Some of the rows have body text that I need to find&replace keywords with some HTML goodness. The problem is that 'str_replace' does this in one step. Therefore, I cannot make the replaced code have anything unique (like the element IDs).

So here is an example row of body text:
"Motor nerve conduction studies of (left/right/bilateral) median and ulnar nerves reveal normal distal latencies. Sensory nerve conduction studies of (left/right/bilateral) median and ulnar nerves reveal normal peak latencies "

I need to replace:
"(left/right/bilateral)"
with:
"<span onmouseover=showtooltip(this.id) id=ttip_someunique# >(left/right/bilateral)</span>"

The problem is that all occurences will be replaced with the same text including IDs. I tried to make a function that will return the <span> text with a randomly generated number for the ID (first post) but that's not very reliable for a couple of reasons. I know this isn't best practice anyways.

I tried 'preg_replace' and 'substr_count' to do a FOR loop but since I'm surrounding the search term with code, the next iteration through the loop will find the same string again and again. The problem with that was:

Code: Select all

 
$replaceme = "(left/right/bilateral)";
$withme     = "<span onmouseover=showtooltip(this.id) id=ttip_someunique# >(left/right/bilateral)</span>";
$thecount = substr_count($item_text, $replaceme);
 
for ($p = 0; $p < $thecount; $p++) {
     $item_text = preg_replace($replaceme, $withme, $item_text);
}
 
which will clearly keep running on the first match over and over again. I ended up with a set of parentheses for each occurence plus one recursively.
For example, if there were 3 matches, I would have ((((first match)))) (((second match))) ((third match)) since there was already a set of parentheses to start with. This is insane.


I just need an unique ID for each replacement string so that the tooltip will be able to reach that particualr SPAN to update the text. If there are 3 matches, then all three would be updated since their IDs match.

Re: Str_replace static text with dynamic text for each result

Posted: Fri Jul 18, 2008 9:35 am
by enatefox
I'm still hoping for a solution but I thought I would post what I did in the meantime. Negative on PHP because I just don't see a function that would be suitable so here's the javascript version:

Code: Select all

 
function grabttips(){
    var x=document.getElementsByTagName("span")
    for (b=0;b<x.length;b++){
        if(x[b].id=='') {
            x[b].id = 'ttip'+b
        }
        else{}
    }
}
 
Yea, I know it's not the best but oh well. If anyone wants to use this I should also mention a couple of quirks with it:

I'm loading menus dynamically via AJAX and when the response comes through, you'd think you could run the script but it seems to just freeze the response or something because the elements will not populate.
If I have a link that runs the script and click that only once the whole document is available from the request it will work.
I instead made it so that when the tooltip function is called it will run the script which only changes IDs if they're null. I did not specify an ID originally so it should only run on the first tooltip.

Please let me know what else would work (PHP preferably)

Re: Str_replace static text with dynamic text for each result

Posted: Sat Jul 19, 2008 8:09 pm
by WebbieDave
enatefox wrote:Negative on PHP because I just don't see a function that would be suitable
8O ??? PHP has one of the richest library sets ever

Regex is the way to go. If you need different replacements for multiple occurrences of a pattern, try a callback function:

Code: Select all

function getSpan($matches) {
    global $spanIdNum;
    return '<span id="tip_' . $spanIdNum++ . '>' . $matches[0] . '</span>';
}
$pattern = '/\(left\/right\/bilateral\)/';
$body = 'Motor nerve conduction studies of (left/right/bilateral) median and ulnar nerves reveal normal distal latencies. Sensory nerve conduction studies of (left/right/bilateral) median and ulnar nerves reveal normal peak latencies';
$spanIdNum = 1;
 
$body = preg_replace_callback($pattern, 'getSpan', $body);

Re: Str_replace static text with dynamic text for each result

Posted: Mon Jul 21, 2008 7:18 am
by enatefox
Thanks for the reply.
That's more of what I was looking for. I've never even dabbled with that though...


Code: Select all

 
function getSpan($matches) {
   global $spanIdNum;
   return '<span id="tip_' . $spanIdNum++ . '>' . $matches[0] . '</span>';
}
   $pattern = '/\(left\/right\/bilateral\)/';
   $body = 'Motor nerve conduction studies of (left/right/bilateral) median and ulnar nerves reveal normal distal latencies. Sensory nerve conduction studies of (left/right/bilateral) median and ulnar nerves reveal normal peak latencies';
   $spanIdNum = 1;
 
   $body = preg_replace_callback($pattern, 'getSpan', $body);
 
Sorry if it's noobish but I'm not used to callback functions.
As my first post stated, the best idea I had that was similar was to call a function that adds a random number to the end of the static replacement text. This was beyond unreliable so how would I implement this?



What I don't get:
Can you explain what $matches would have that the [0] index is always returned in the function?
Also, the $spanIdNum would be what when I need it to generate on the fly. I don't know if there are 3,5,20 replacements and I don't want to have to count first... Am I supposed to define an array of numbers to feed getSpan()? That seems counterproductive.

Re: Str_replace static text with dynamic text for each result

Posted: Mon Jul 21, 2008 7:32 am
by VladSun
Example #2 at http://bg2.php.net/manual/en/function.p ... llback.php will make it clear for you.

Re: Str_replace static text with dynamic text for each result

Posted: Mon Jul 21, 2008 2:01 pm
by enatefox
Thanks for the feedback. All is working as desired for the most part.

I did this:

Code: Select all

 
$ttiparray = array("/\(left\/right\/bilateral\)/","/\(median\/ulnar\)/");
$item_text =  preg_replace_callback($ttiparray[0],"proc_tooltips_TYPE1",$item_text[$a]);
$item_text =  preg_replace_callback($ttiparray[1],"proc_tooltips_TYPE2",$item_text[$a]);
....
 
function proc_tooltips_TYPE1($matches){
  return "<span class=spncls onmouseover=\"showtool(this,'TYPE1')\" id='".rand()."' >[LEFT/RIGHT/BILATERAL]</span>";
}
 

Ok, now I'm up to my next set of problems...
There are multiple types of replacements depending on the search string (around 15 so far...).
I do not see a way of passing this to the new function proc_tooltips(); although I tried.

What I need is for the proc_tooltips() function to be able to tell the text it found (even the array index for $ttiparray would work) so that the text inside the span that I'm inserting has the same keywords it had originally:

As a non-working example:

Code: Select all

 
$ttiparray = array("one","fish","two");
$item_text = preg_replace_callback($ttiparray[0],"proc_tooltips($ttiparray[0])",$item_text);
...
 
function proc_tooltips($matches,$orig_text) {
     return "<span id='".rand()."' >" .$orig_text. "</span>";
}
 

So that:
"the original keyword"
Becomes:
<span>"the original keyword"</span>


How about that?