Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

glossary type script 1

Status
Not open for further replies.

ThomasJSmart

Programmer
Sep 16, 2002
634
a while ago i got lots of help from jpadie to make a dictionary script resulting in this lovely function:


Code:
function dictionary($string){

	global $db;
	$result = mysql_query("SELECT * FROM cms_dictionary ORDER BY dictionary_word",$db);
	while ($myrow = mysql_fetch_array($result)){
			
		$GLOBALS['BC_DDI'] = 0;	
		$GLOBALS['BC_DID'] = $myrow['dictionary_id'];
		$GLOBALS['BC_DIN'] = $myrow['dictionary_info'];
		$GLOBALS['BC_DWO'] = $dictionary_word	 	= $myrow['dictionary_word'];
		
		// set up the patterns
		$pattern[0] = '/(=["\'].*)('.$dictionary_word.')(.*["\'])/';
		$uid = uniqid("tmp_");
		$replace[0] = "$1".$uid."$3";
		$pattern[1] = '/'.$dictionary_word.'/i';
			
		//do the replacements
		$tmp = preg_replace($pattern[0], $replace[0], $string);	// changes all D-words that should not be changed to a tmp var.
		$tmp = preg_replace_callback($pattern[1], "Dreplace", $tmp); //use callback because we need an incrementing id, changes alowable D-words to the replace.
		$string = str_replace($uid, $dictionary_word, $tmp); // using str_replace as it is quicker. changes all tmp vars back to D-word.
		
		
	}

	return $string; 
}






	
function Dreplace($matches){
	static $di = 0; $dictionary_id = $GLOBALS['BC_DID']; $dictionary_word = $GLOBALS['BC_DWO']; $dictionary_info = $GLOBALS['BC_DIN'];
	$dictionary_window		= '<div class="dictionary" id="dDiv'.$dictionary_id.'_'.$di.'" name="dDiv'.$dictionary_id.'_'.$di.'" style="display:none" onMouseOver="showDictionary(\'dDiv'.$dictionary_id.'_'.$di.'\',1)" onMouseOut="showDictionary(\'dDiv'.$dictionary_id.'_'.$di.'\',0)">'.$dictionary_info.'</div>';
	$dictionary_link 		= '<a href="javascript:void(0)" onMouseOver="showDictionary(\'dDiv'.$dictionary_id.'_'.$di.'\',1)" onMouseOut="showDictionary(\'dDiv'.$dictionary_id.'_'.$di.'\',0)">'.$dictionary_word.'</a>';
	$result = $dictionary_window.$dictionary_link;
	$di++;
	return $result;
}

it essentially goes through a large body of text adding a DIV window mouseover to all given words from the DB. thus resulting in a glossary/dictionary type script.

this seems to be giving a problem tho. It is also replacing words that are in HTML links.

Say we want to replace the word "CMS"

string:

a CMS is a lovely thing. click <a href="cms.html">here for more CMS info</a>


now all 3 of these words is being updated with a DIV mouseover when ofcourse only the first should be done...

been fiddeling with it for a while but regex is not realy my thing :/

anyone got any ideas?

Thanks!



I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
that's strange. it should not.

the first pattern is not a paragon of virtue though. for one thing, it is case sensitive whereas the second pattern is not case sensitive. assuming that you are using a web server that does not care about case sensitivity, try adding an i at the end of the pattern[0] and let us know whether you see the same behaviour.


 
still the same effect with the /i

the second one didnt have the /i either but that was one of the things i was fiddeling with trying to fix it :)


I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
on re-reading your post I see the issue. the pattern only stubs out the words that are in the _attributes_ of an html tag. not within the tag itself.

however, using the same code as you have I only get the first and third changed. the second, by design, does not change at all. I am surprised that you do not see the same behaviour.

here is some changed code that fixes the third example
Code:
<?php

$string = 'a CMS is a lovely thing. click <a href="cms.html">here for more CMS info</a>';
echo htmlspecialchars($string);
echo '<hr/>';
echo htmlspecialchars(dictionary($string));

function dictionary($string){
		$dictionary_word = 'cms';
        // set up the patterns
        $pattern[0] = '/(=\\s*(["\']).*)('.$dictionary_word.')(.*\\2)/i';
		$pattern[1] = '/(<a.*>.*)(\b'.$dictionary_word.'\b)(.*<\/a>)/i'; 
        $uid = uniqid("tmp_");
        $replace[0] = '$1'.$uid.'$4';
		$replace[1] = '$1'.$uid.'$3';
        $_pattern = '/\b'.$dictionary_word.'\b/i';
            
        //do the replacements
        $tmp = preg_replace($pattern, $replace, $string);    // changes all D-words that should not be changed to a tmp var.
		//echo "<hr/>after first replace<br/>$tmp<hr/>";
        $tmp = preg_replace_callback($_pattern, "Dreplace", $tmp); //use callback because we need an incrementing id, changes alowable D-words to the replace.
        $string = str_replace($uid, $dictionary_word, $tmp); // using str_replace as it is quicker. changes all tmp vars back to D-word.
        
		return $string; 
}


    
function Dreplace($matches){
    static $di = 0; 
	$dictionary_id = 'dictionary_id'; 
	$dictionary_word = 'cms'; 
	$dictionary_info = 'Click me for some good info';
    $dictionary_window        = <<< HTML
<div class="dictionary" 
	id="dDiv{$dictionary_id}_{$di}" 
	name="dDiv{$dictionary_id}_{$di}" 
	style="display:none" 
	onMouseOver="showDictionary('dDiv{$dictionary_id}_{$di}\',1);" 
	onMouseOut="showDictionary('dDiv{$dictionary_id}_{$di}\',0);" >
	$dictionary_info
</div>
HTML;
	$dictionary_link = <<<HTML
<a 	href="javascript:void(0)" 
	onMouseOver="showDictionary('dDiv{$dictionary_id}_{$di}\',1);" 
	onMouseOut="showDictionary('dDiv{$dictionary_id}_{$di}\',0);">
	$dictionary_word
</a>
HTML;
    
	$result = $dictionary_window.$dictionary_link;
    $di++;
    return $result;
}    
?>
 
Hi jpadie, this totally solved the link problem thank you very much!! :D


I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
ok, dragging up this old topic again :)


There seems to be a little problem with $pattern;

i dont know what it is tho :(

regex is to complicated.. sometimes a word will not work, then i make a small change in the text around it and then it does work ???



the dictionary word is BHV

string 1:
Code:
Ook <A href="Consultancy_diensten_Productoverzicht.html" target=_top>bedrijfshulpverlening</A> BHV en ontruiming vloeien <BR><STRONG>kan u helpen</STRONG><BR>professioneel te begeleiden. <A href="Brand_Veiligheid_Productoverzicht.html" target=_top>brandveiligheidfuncties</A>.

does not work (BHV stays regular text).


String 2:
Code:
BHV en ontruiming vloeien <BR><STRONG>kan u helpen</STRONG><BR>professioneel te begeleiden. <A href="Brand_Veiligheid_Productoverzicht.html" target=_top>brandveiligheidfuncties</A>.

does work (BHV becomes a dictionary link)

String 3:
Code:
Ook <A href="Consultancy_diensten_Productoverzicht.html" target=_top>bedrijfshulpverlening</A> BHV en ontruiming vloeien <BR>

Also works



strange yes? ^^

I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
hmmm. the regex is clearly the proglem but i can't see immediately why. i think we'll have to restructure the regex completely to make it work (and focus more on the angle braces than the attributes). i'll have a ponder.
 
hmmm. the regex is clearly the problem but i can't see immediately why. i think we'll have to restructure the regex completely to make it work (and focus more on the angle braces than the attributes). i'll have a ponder.
 
have you been able to ponder it? ^_^

I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
Does anyone have a solution for this or another way to do it?

in short:

i have a big page of text, website content, with html, images, links etc. etc.

in this content there are words that need a mouseover hover info.

the words that need to have the info are stored in a database along with the information that needs to be shown.

only words in plain text should get the info window, not words in link hrefs or link text.

YES <a href="NO">NO</a> YES

Neither should any words that are tags be give info

width(yes) <div style="width(no):100"></div>


please help..

thank you.


I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
have you thought of doing this in javascript instead? by traversing the DOM and searching only insideHTML? that might be a neater solution.

but it should be possible to do this as a regex within php and i have some time this afternoon, so i will give it some thought. sorry for not replying to your previous nudge.
 
I have looked into a javascript version but at the time for some reason php seemed easier and more stable :-/

i still think >if< it will work it will be better in php tho.. :)

I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
i haven't forgotten. i've been playing with lookbehinds to see whether i could get a single solution.

i still think that a js solution would be best.
 
does the one on this site with the advertising on certain words work with js ? do you know of a ready made JS class that gets close to this that i could work on to make it like this.

I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
been trying to find a JS variant of this but not much luck,,, "javascript dictionary / glossary" just returns javascript help pages.. any ideas for a class that does this or something similer i can modify to work?



I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
Hi There

Would like to drag this topic up again.. i dont realy want to do javascript, but i understand that that is easier than php in this case. However iv decided to try a double aproach.

Im using a javascript tooltip class. this very much simplifies the replace script down to:



Code:
function dictionary($string){
    global $db;
	$dbresult = mysql_query("SELECT * FROM cms_dictionary ORDER BY dictionary_word",$db);
	while ($myrow = mysql_fetch_array($dbresult)){
	
		$dictionary_info 	= str_replace("'","\\'",str_replace('"',"'",$myrow['dictionary_info']));
		$dictionary_word	= $myrow['dictionary_word'];
		
		if(trim($dictionary_word)!=''){		
			// set up the patterns
			$pattern[0] = '/(=\\s*(["\']).*)('.$dictionary_word.')(.*\\2)/';
			$pattern[1] = '/(<a.*>.*)(\b'.$dictionary_word.'\b)(.*<\/a>)/'; 
			$uid = uniqid("tmp_");
			$replace[0] = '$1'.$uid.'$4';
			$replace[1] = '$1'.$uid.'$3';
			
			$_pattern = '/\b'.$dictionary_word.'\b/';
			
			$result 		= ' <a href="#" onMouseOver="Tip(\''.$dictionary_info.'\')" onMouseOut="UnTip()" style="cursor:help; border-bottom:2px dotted #999999;">'.$dictionary_word.'</a> ';
			
			//do the replacements
			$string = preg_replace($pattern, $replace, $string);    // changes all D-words that should not be changed to a tmp var.
			$string = preg_replace($_pattern, $result, $string); // replace remaining with link
			$string = str_replace($uid, $dictionary_word, $string); // change d-words back to previous
		}
	}
	return $string; 
}


Now the toolip looks great with this class and is always on the right location. There are still some remaining issues tho.

is there a way to skip step 1 and 3, replacing all the words that shouldnt be replaced with a unique id and later replacing them back? Cant we just replace the words that are supposed to be replaced?

also it still seems to be skipping some words, now that im using the javascript class to simplify the replace can the whole replace script be tweaked to perform better?

Thanks a bunch!
Thomas

I learned a bit yesterday, today i learned a lot, imagine what i'll learn tomorrow!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top