Translations
Info
All page names need to be in English.
en da  de  fr  it  ja  km  nl  ru  zh

GTMENU

From TYPO3Wiki
Jump to: navigation, search
This page belongs to the Content Rendering - Team (category ContentRenderingTeam)

A GTMENU is a combination of GMENU and TMENU - by applying the following IProcFunc to your GMENU it gets rendered as a normal TMENU with the graphics loaded as CSS background-images. Very nice for screenreaders et. al. This type of menu has been successfully testet with the following browsers:

Win - IE5+, all Geckoes incl. NN 7.1+, Op. 7+

MAC - IE5, Safari, all Geckoes, Op

Linux - all Geckoes (could sb. try Konqueror and tell? works perfectly here with konqueror 3.4.3 on ubuntu)

To make things happen, you need to include the following IProcFunc. Copy the function to a textfile and save it somewhere in your fileadmin directory:

GTMENU IProcFunc

<?php
	
class user_gtmenu {
	/**
	 * Renders a GMENU like a TMENU with CSS background images
	 * best regards to the Content Rendering Group
	 *
	 * @author Stefan Beylen for http://we-make.net <intsys@swissinfo.org>
	 * @author Torsten Schrade <t.schrade@connecta.ag>
	 * date: 2005-01-12
	 */

	function GTMenu($I,$conf){
	
		//kill unneccessary JS
		unset($I["linkHREF"]["onMouseover"]);
		unset($I["linkHREF"]["onMouseout"]);
		unset($GLOBALS['TSFE']->additionalJavaScript);	

		$uniqueString=substr(md5(microtime()),0,10);

		$I["linkHREF"]["class"]="gt-menu gt-".$uniqueString;

		$I["parts"]["image"]=$I["title"];
		$conf["parentObj"]->I = $I;
		$conf["parentObj"]->setATagParts();
		$I = $conf["parentObj"]->I;
		$I["parts"]["ATag_begin"]=$I["A1"]."<span>";
		$I["parts"]["ATag_end"]="</span>".$I["A2"];

		preg_match("/[^>]*alt=\"(.*?)\"[^>]*/",$I['IMG'],$match['alt']);
		preg_match("/[^>]*src=\"(.*?)\"[^>]*/",$I['IMG'],$match['src']);
		preg_match("/[^>]*width=\"(.*?)\"[^>]*/",$I['IMG'],$match['width']);
		preg_match("/[^>]*height=\"(.*?)\"[^>]*/",$I['IMG'],$match['height']);

		if($conf[parentObj]->mconf['css2TempFile']) {
				
				// writing css to an external stylesheet / start a temporary global register for that
				$GLOBALS['TSFE']->register['GTMenu_csstemp']['1'] = 'a.gt-menu{display:block;text-decoration:none;background-repeat:no-repeat;background-position: top left;vertical-align:bottom;}';
				$GLOBALS['TSFE']->register['GTMenu_csstemp']['2'] = 'a.gt-menu span{display:block;height:1px;width:1px;overflow:hidden;}';	
				
				// insert additional styles in case $imgPreload = img
				if($conf[parentObj]->mconf['imgPreload'] == 'img') {
					$GLOBALS['TSFE']->register['GTMenu_csstemp']['3'] = 'p.hidden{position:absolute;left:-2000px;display:block;width:1px;height:1px;overflow:hidden;margin-top:1px;margin-left:1px;}';
				}
								
				// write the different <a> tag styles to this register
				$aStyles = 'a.gt-'.$uniqueString.'{background-image:url(../'.$match['src'][1].');width:'.$match['width'][1].'px;height:'.$match['height'][1].'px;}';
				$GLOBALS['TSFE']->register['GTMenu_csstemp'][] = $aStyles;				
				
				// RO states
				if(is_array($conf[parentObj]->result['RO'])) {
					$GLOBALS['TSFE']->register['GTMenu_csstemp'][] = "a.gt-".$uniqueString.":hover{background-image:url(../".$conf[parentObj]->result['RO'][$I['key']]['output_file'].");}";
				}				
				
				// implode the temporary register to the final register and write the resulting string to an external stylesheet
				$GLOBALS['TSFE']->register['GTMenu_css'] = implode("\n", $GLOBALS['TSFE']->register['GTMenu_csstemp']);
				$GLOBALS['TSFE']->additionalHeaderData["25041"] = TSpagegen::inline2TempFile($GLOBALS['TSFE']->register['GTMenu_css'], 'css');
						
		} else {					
				
				// write css as embedded styles (default behaviour)
				$GLOBALS['TSFE']->additionalHeaderData['25041']= "\t<style type=\"text/css\">\n\t\t/** GTMenu Styles **/\n\t\ta.gt-menu{display:block;text-decoration:none;background-repeat:no-repeat;vertical-align:bottom;}\n\t\ta.gt-menu SPAN{display:block;width:1px;height:1px;overflow:hidden;text-indent:-9999px;}";
				$GLOBALS['TSFE']->additionalHeaderData['25045'].= "\t\ta.gt-".$uniqueString."{background-image:url(".$match['src'][1].");width:".$match['width'][1]."px;height:".$match['height'][1]."px;}\n";						
				
				// RO states
				if(is_array($conf[parentObj]->result['RO'])) {
					$GLOBALS['TSFE']->additionalHeaderData['25043'] = "\t\t".'img.hidden{position:absolute;left:-2000px;display:block;width:1px;height:1px;overflow:hidden;margin-top:1px;margin-left:1px;}'."\n";									
					$GLOBALS['TSFE']->additionalHeaderData['25045'].= "\t\ta.gt-".$uniqueString.":hover{background-image:url(".$conf[parentObj]->result['RO'][$I['key']]['output_file'].");}\n";
				}		
				$GLOBALS['TSFE']->additionalHeaderData['25049'] = "\t</style>";
		}		
		
		// doing the image preload stuff:
		switch($conf[parentObj]->mconf['imgPreload']) {
		
			case 'js': 
				// $GLOBALS['TSFE']->JSImgCode is left intact
			break;		
		
			case 'external':							
				// use a temporary register that is imploded like above
				$GLOBALS['TSFE']->register['GTMenu_jstemp'][] = $GLOBALS['TSFE']->JSImgCode;
				
				// imploding to register and writing external file
				$GLOBALS['TSFE']->register['GTMenu_js'] = implode("", $GLOBALS['TSFE']->register['GTMenu_jstemp']);				
				$GLOBALS['TSFE']->additionalHeaderData["25050"]=TSpagegen::inline2TempFile($GLOBALS['TSFE']->register['GTMenu_js'], 'js');
				unset($GLOBALS['TSFE']->JSImgCode);				
			break;			
		
			case 'img':
				// writing hidden <img>'s just after the body tag - has to be wrapped with <p></p> for XHTML Strict							
				if(!is_array($conf[parentObj]->result['RO'])) {
					$GLOBALS['TSFE']->pSetup['bodyTagAdd'].= '>'."\n".'<p class="hidden"><img src="'.$match['src'][1].'" class="hidden" width="'.$match['width'][1].'" height="'.$match['height'][1].'" /></p';
				}
				// RO states				
				if(is_array($conf[parentObj]->result['RO'])) {
					$GLOBALS['TSFE']->pSetup['bodyTagAdd'].= '>'."\n".'<p class="hidden"><img src="'.$match['src'][1].'" width="'.$match['width'][1].'" height="'.$match['height'][1].'" />'."\n".'<img src="'.$conf[parentObj]->result['RO'][$I['key']]['output_file'].'" width="'.$match['width'][1].'" height="'.$match['height'][1].'" /></p';
				}
				unset($GLOBALS['TSFE']->JSImgCode);		
			break;			
		
			default:
				unset($GLOBALS['TSFE']->JSImgCode);
			break;
		}	
		return $I;
	}
}
?>

Making it work

After you've saved the IProcFunc to your fileadmin, do the following steps:

1) Go to your root template and include the library:

page.includeLibs.gtmenu = fileadmin/path/to/the/function/gtmenu.txt

2) Add the function to your TypoScript GMENU

temp.myGMENU.IProcFunc = user_gtmenu->GTMenu

TypoScript

There are 2 new TypoScript Options for a GTMENU:

1) css2TempFile -> if this is set to 1, the menustyles are written to an external stylesheet

2) imgPreload -> you can set this to 'js', 'external' or 'img'.

- 'js' = renders some JavaScript for preloading images into the page header

- 'external' = renders the JavaScript for preloading images into an external file

- 'img' = renders hidden <img>'s that correspond to the background-images just after the <body> tag

The default setting is imgPreload (not set) / css2TempFile (not set) which results in just the CSS written to the pageHeader and nothing else.

Especially with :hover enabled (RO state), there are settings where you might notice "flickers". It's always good to preload images if you have RO enabled. On the other hand, if you're just using ACT, IFSUB or CUR states, you might not need this.

Some Benchmarks

Here are some basic benchmarks that might help you finding the setting of your choice

1. no imgPreload / no css2TempFile: Parsetime - 722 ms, big flicker on :hover

2. imgPreload=img / no css2TempFile: Parsetime - 771 ms, no flicker on :hover!

3. imgPreload=js / no css2TempFile: Parsetime: 766 ms, flicker on :hover

4. imgPreload=external / no css2TempFile: Parsetime: 539 ms, no flicker on :hover!!

5. imgPreload=external / css2TempFile=1: Parsetime: 742 ms, no flicker on :hover!

6. imgPreload=js / css2TempFile=1: Parsetime: 756 ms, flicker on :hover

7. imgPreload=img / css2TempFile=1: Parsetime: 765 ms, no flicker on :hover

Of course parsetime is a rather relative value. Also, some users have found that they don't have flickers on the settings we had. So best thing might be to test for yourself. Anyway, 4. seems to be the quickest and 5. the cleanest/best choice in our opinion.

Examples

You can find a working example here: http://www.stdwarp.org/?83

Cache Problem?

whenever i use imgPreload=external or css2TempFile=1 the typo3temp/ folder fills up with 10000's of css and js files ! Hello, thanks for this remark. Plz have a look on the GTMENU discussion page (second tab above)...