> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# Materialien FACT-Finder Suggest-Layer

> Die Vorlagen für den FACT-Finder Suggest-Layer in beiden Ausbaustufen: JavaScript und CSS für die einfache Vorschlagsliste und für den erweiterten Layer mit Produktbildern.

Der Suggest-Layer zeigt Suchvorschläge, während der Besucher tippt. Er spricht FACT-Finder direkt an, unabhängig von der Suchergebnisseite. Diese Seite enthält die Vorlagen dafür in beiden Ausbaustufen.

> [!WARNING]
>
> **Die Direktanbindung ist veraltet und wird nicht mehr unterstützt.** Sie steht nur bis FACT-Finder 6.9 zur Verfügung und wird von WEBSALE weder gepflegt noch weiterentwickelt. Für neue Integrationen verwenden Sie die FACT-Finder WebComponents nach der offiziellen Dokumentation von FACT-Finder.
>
> Diese Seite ist für bestehende Shops gedacht, die noch mit der Direktanbindung arbeiten.

Wegweiser: [FACT-Finder-Integration](https://dokumentation.websale.de/v8s/integration-von-fact-finder/integration-von-fact-finder.md) · Materialien: FACT-Finder-Templates

## Zwei Ausbaustufen

| | einfacher Layer | erweiterter Layer |
| - | - | - |
| Dateien | `ff_suggest.js`, `ff_suggest.css` | `ff_big_suggest.js`, `ff_big_suggest.css` |
| Darstellung | eine Tabelle mit Vorschlag, Typ und Trefferzahl | zwei Spalten, Produktvorschläge mit Bild neben Suchbegriffen |
| Voraussetzung | keine, reines JavaScript | jQuery |
| Antwortformat | Text, zeilenweise, Felder mit `###` getrennt | JSONP |
| Tastatur | hoch und runter | hoch, runter, links, rechts und Tabulator |
| Rückmeldefunktionen | zwei | vier |

Beide verwenden dieselben CSS-Klassennamen für die Zeilen, die Stylesheets sind aber nicht austauschbar. Der einfache Layer baut eine Tabelle, der erweiterte Listen in zwei Spalten.

## Der einfache Suggest-Layer

### ff\_suggest.js

Die Datei definiert einen Konstruktor `FFSuggest`. Sie legen eine Instanz an und rufen `init()` mit acht Parametern auf.

| Parameter | Bedeutung |
| - | - |
| `searchURL` | die Adresse der FACT-Finder-Suggest-Schnittstelle |
| `formname` | der Name des Suchformulars im Dokument |
| `queryParamName` | der Name des Sucheingabefelds |
| `divLayername` | die ID des `div`, in das der Layer geschrieben wird |
| `instanceName` | der Name Ihrer Instanz, als Zeichenkette. Das Modul baut daraus die `onMouseOver`-Aufrufe im erzeugten HTML |
| `debugMode` | `true` zeigt Fehler als Meldungsfenster an |
| `channelParamName` | der Name des Kanalparameters |
| `channel` | der Kanal selbst |

> [!WARNING]
>
> `instanceName` muss genau dem Namen der Variablen entsprechen, unter der Sie die Instanz angelegt haben. Das Modul setzt diesen Namen als Text in die erzeugten `onMouseOver`- und `onMouseDown`-Attribute ein. Stimmt er nicht, bleibt der Layer stumm, ohne dass eine Fehlermeldung erscheint.

> [accordion] ff\_suggest.js
>
> ```js theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
> function FFSuggest() {
>
> 	var pRequest;
> 	var pLayer;
> 	var pDebug			= false;
> 	var pInstanceName		= '';
> 	var pSearchURL			= '';
> 	var pQueryParamName		= '';
> 	var pFormname 			= '';
> 	var pLayerName			= '';
> 	var pQueryInput;
> 	var pSuggest			= new Array();
> 	var pLastQuery;
> 	var pCurrentSelection		= -1;
> 	var submitted			= false;
>
> 	var pSuggestQueryClass 		= 'suggestTextQuery';
> 	var pSuggestTypeClass 		= 'suggestTextType';
> 	var pSuggestAmountClass         = 'suggestTextAmount';
> 	var pSuggestQueryTypedClass     = 'suggestTextQueryTyped';
> 	var pSuggestFooterClass         = 'suggestFooter';
> 	var pSuggestHeaderClass         = 'suggestHeader';
> 	var pSuggestRowClass	        = 'suggestRow';
> 	var pSuggestHighlightClass      = 'suggestHighlight';
>
> 	this.init = function(searchURL, formname, queryParamName, divLayername, instanceName, debugMode, channelParamName, channel) {
> 		pSearchURL		= searchURL;
> 		pFormname		= formname;
> 		pQueryParamName		= queryParamName;
> 		pChannelParamName	= channelParamName;
> 		pChannel		= channel;
> 		pLayerName		= divLayername;
> 		pInstanceName		= instanceName;
> 		pDebug			= debugMode;
> 		if (pSearchURL == '') {
> 			if (pDebug) alert('no searchurl defined');
> 			return null;
> 		} else if (pInstanceName == '') {
> 			if (pDebug) alert('no instancename defined');
> 			return null;
> 		} else if (pFormname == '') {
> 			if (pDebug) alert('no formname defined');
> 			return null;
> 		} else if (pQueryParamName == '') {
> 			if (pDebug) alert('no queryparamname defined');
> 			return null;
> 		} else if (pLayerName == '') {
> 			if (pDebug) alert('need a layer for output');
> 		}
> 		pQueryInput = document[pFormname][pQueryParamName];
> 		pQueryInput.onkeyup	= handleKeyPress;
> 		pQueryInput.onfocus	= showLayer;
> 		pQueryInput.onblur	= hideLayer;
> 		document[pFormname].onsubmit = handleSubmit;
> 	}
>
> 	function handleSubmit() {
> 		submitted = true;
> 		if (pSuggest[pCurrentSelection] != undefined) {
> 			document[pFormname][pQueryParamName].value = pSuggest[pCurrentSelection].split('###')[0];
> 			if(document[pFormname]['queryFromSuggest'] != null){
> 				document[pFormname]['queryFromSuggest'].value = true;
> 			}
> 		}
> 	}
>
> 	this.handleClick = function() {
> 		if (pSuggest[pCurrentSelection] != undefined) {
> 			document[pFormname][pQueryParamName].value = pSuggest[pCurrentSelection].split('###')[0];
> 			if(document[pFormname]['queryFromSuggest'] != null){
> 				document[pFormname]['queryFromSuggest'].value = true;
> 			}
> 			document[pFormname].submit();
> 		}
> 	}
>
> 	this.handleMouseOver = function(pos) {
> 		var tblCell = getTableCell(pos);
> 		unmarkAll();
> 		if (tblCell != null) {
> 			highlightSuggest(tblCell);
> 			pCurrentSelection = pos;
> 		}
> 	}
>
> 	this.handleMouseOut = function(pos) {
> 		var tblCell = getTableCell(pos);
> 		if (tblCell != null) {
> 			unmarkSuggest(tblCell);
> 			pCurrentSelection = -1;
> 		}
> 	}
>
> 	function handleKeyPress(evt) {
> 		evt = (evt) ? evt : ((event) ? event : null);
> 		var keyCode = evt.keyCode;
> 		if (keyCode == 38) {
> 			moveSelection('up')
> 		} else if (keyCode == 27) {
> 			hideLayer();
> 		} else if (keyCode == 40) {
> 			moveSelection('down');
> 		} else {
> 			if (pQueryInput.value == '') {
> 				hideLayer();
> 				if (pLayer != null){ pLayer.innerHTML = ''; }
> 				return null;
> 			}
> 			if (pLastQuery != pQueryInput.value){ startAjax(); }
> 			pLastQuery = pQueryInput.value;
> 		}
> 	}
>
> 	function moveSelection(direction) {
> 		var pos = pCurrentSelection;
> 		if (direction == 'up'){	pos--; }
> 		else{					pos += 1; }
>
> 		if (pos < 0) {
> 			unmarkAll();
> 			pQueryInput.focus();
> 			pCurrentSelection	= -1;
> 		} else {
> 			var tblCell = getTableCell(pos);
> 			if (tblCell != null) {
> 				unmarkAll();
> 				highlightSuggest(tblCell);
> 				pCurrentSelection = pos;
> 			}
> 		}
>
> 		var query = pQueryInput.value;
> 		pQueryInput.value = '';
> 		pQueryInput.focus();
> 		pQueryInput.value = query;
> 	}
>
> 	function startAjax() {
> 		var query = pQueryInput.value;
> 		if(query.length > 50 ){ return; }
>
> 		var requestURL = pSearchURL +'?query='+ encodeURIComponent(query) +'&'+ pChannelParamName +'='+ pChannel;
>
> 		try {
> 			if( window.XMLHttpRequest ) {
> 				pRequest = new XMLHttpRequest();
> 			} else if( window.ActiveXObject ) {
> 				pRequest = new ActiveXObject( "Microsoft.XMLHTTP" );
> 			} else {
> 				if (pDebug) alert( 'no ajax connection' );
> 			}
>
> 			pLayer = document.getElementById(pLayerName);
> 			if (pLayer != null) {
> 				if (query != '') {
>
> 					pRequest.open( "GET", requestURL, true );
> 					pRequest.onreadystatechange = callbackAjax;
> 					pRequest.send( null );
> 				} else {
> 					hideLayer();
> 				}
> 			} else {
> 				if (pDebug) alert( 'no layer for output found' );
> 			}
> 		} catch( ex ) {
> 			hideLayer();
> 			if (ex != undefined) {
> 				if (pDebug) alert( 'Error: ' + ex );
> 			} else {
> 				if (pDebug) alert( 'Error: unbekannter Fehler' );
> 			}
> 		}
> 	}
>
> 	function hideLayer() {
> 		if (pLayer != null) {
> 			pLayer.style.display = 'none';
> 			fireSuggestLayerHidden();
> 		}
> 	}
>
> 	this.hideLayerOutsideCall = function() {
> 		if (pLayer != null) {
> 			pLayer.style.display = 'none';
> 			fireSuggestLayerHidden();
> 		}
> 	}
>
> 	function showLayer() {
> 		if (pLayer != null && pSuggest != null && pSuggest.length >= 1) {
> 			pLayer.style.display = 'block';
> 		}
> 	}
>
> 	function callbackAjax() {
> 		if (submitted == false) {
> 			if (pRequest.readyState == 4) {
> 				if (pRequest.status != 200) {
> 					hideLayer();
> 					if (pDebug) alert( 'Error (' + pRequest.status + '): ' + pRequest.statusText );
> 				} else {
> 					handleResponse(pRequest.responseText);
> 				}
> 			}
> 		}
> 	}
>
> 	// calls the callback for "outside" listeners if the callback is implemented
> 	function fireSuggestCompleted(suggestLayerIsVisible) {
> 		if (typeof(onSuggestCompleted) == 'function') {
> 			onSuggestCompleted(suggestLayerIsVisible);
> 		}
> 	}
>
> 	// calls the callback for "outside" listeners if the callback is implemented
> 	function fireSuggestLayerHidden() {
> 		if (typeof(onSuggestLayerHidden) == 'function') {
> 			onSuggestLayerHidden();
> 		}
> 	}
>
> 	function handleResponse(text) {
> 		pCurrentSelection = -1;
> 		pSuggest = new Array();
> 		pSuggest = text.split('\n');
> 		var outputText = '<table cellpadding="0" cellspacing="0" class="' + pLayerName + '" width="100%" border="0" onMouseDown="' + pInstanceName + '.handleClick();">';
> 		outputText += '<tr class="'+pSuggestHeaderClass+'" ><td nowrap="nowrap" colspan="3">Vorschläge zu Ihrer Suche...</td></tr>';
>
> 		var pNewSuggest = new Array();
> 		for (var i = 0; i < pSuggest.length; i++) {
> 			var firstChar = pSuggest[i].charCodeAt(0);
>
> 			if (firstChar != 13 && firstChar != 10 && pSuggest[i].length >= 1) {
> 				pNewSuggest.push(pSuggest[i]);
> 			}
> 		}
> 		pSuggest = pNewSuggest;
> 		var query = pQueryInput.value;
>
> 		for (var i = 0; i < pSuggest.length; i++) {
> 			pSuggestParts = new Array();
> 			pSuggestParts = pSuggest[i].split("###");
>
> 			outputText += '<tr id="' + pLayerName + '_' + i + '" class="'+pSuggestRowClass+'" onMouseOver="' + pInstanceName + '.handleMouseOver(' + i + ');" onMouseOut="' + pInstanceName + '.handleMouseOut(' + i + ');">'
> 								+'<td nowrap="nowrap" class="'+ pSuggestQueryClass +'">' + pSuggestParts[0].replace(new RegExp("("+query+")","ig"),'<span class="'+pSuggestQueryTypedClass+'">$1</span>') + '</td>'
> 								+'<td nowrap="nowrap" class="'+ pSuggestTypeClass +'">' + pSuggestParts[2] + '</td>'
> 								+'<td nowrap="nowrap" class="'+ pSuggestAmountClass +'">' + pSuggestParts[1] + '</td>'
> 						+'</tr>';
> 		}
> 		outputText += '<tr><td class="'+pSuggestFooterClass+'" colspan="3"> </td></tr></table>';
> 		if (pSuggest.length >= 1) {
> 			showLayer();
> 			pLayer.innerHTML = outputText;
>
> 			// callback for "outside" listeners
> 			fireSuggestCompleted(true);
> 		} else {
> 			hideLayer();
> 			pLayer.innerHTML = '';
>
> 			// callback for "outside" listeners
> 			fireSuggestCompleted(false);
> 		}
>
> 	}
>
> 	function highlightSuggest(tblCell) {
> 		tblCell.className = pSuggestHighlightClass;
> 	}
>
> 	function unmarkSuggest(tblCell) {
> 		tblCell.className = pSuggestRowClass;
> 	}
>
> 	function unmarkAll() {
> 		var tblCell;
> 		for (var i = 0; i < pSuggest.length; i++) {
> 			tblCell = getTableCell(i);
> 			if (tblCell != null) {
> 				unmarkSuggest(tblCell);
> 			}
> 		}
> 	}
>
> 	function getTableCell(pos) {
> 		var tblCell;
> 		tblCell = document.getElementById(pLayerName + '_' + pos);
> 		return tblCell;
> 	}
> }
> ```

> [!NOTE]
>
> Das Modul fragt FACT-Finder nicht bei jedem Tastendruck. Es vergleicht vorher mit der letzten Anfrage und überspringt Suchbegriffe über 50 Zeichen ganz.
>
> Die Antwort ist reiner Text: eine Zeile je Vorschlag, darin drei mit `###` getrennte Felder in der Reihenfolge Vorschlag, Trefferzahl, Typ. Im erzeugten HTML stehen sie in der Reihenfolge Vorschlag, Typ, Trefferzahl.

> [!WARNING]
>
> Die Überschrift "Vorschläge zu Ihrer Suche..." steht fest im JavaScript. Wenn Ihr Shop mehrsprachig ist, ziehen Sie diesen Text heraus und übergeben ihn von außen.

### ff\_suggest.css

> [accordion] ff\_suggest.css
>
> ```css theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
> /*****************************************************************************/
> /*** FACT-FINDER SUGGEST ***/
> /*****************************************************************************/
>
> /* needed otherwise the searchBoxLine will pop-up in IE */
> div.suggestFormWrap{
>    position:absolute;
>    z-index: 999;
> }
> div.suggestLayer{
>    position: absolute;
>    z-index: 999;
>    top: 125px;
>    left: 291px;
>    width: 1px;
>    height: 1px;
>    display: none;
>    padding: 0;
>    margin: 0;
>    font-family: Arial,Helvetica,sans-serif;
> }
> table.suggestLayer{
>    z-index:999;
>    position:absolute;
>    font-size: 11px;
>    width: 297px;
>    border-right: 1px solid #85B916;
>    border-bottom: 1px solid #85B916;
>    border-left: 1px solid #85B916;
>    height: 12px;
>    background-color: white;
>    color: black;
>    cursor: pointer;
>    text-align: left;
> }
> tr.suggestLayer{
>    height: 12px;
> }
> td.suggestLayer{
>    padding: 0;
>    height: 12px;
> }
> tr.suggestHeader{
>    font-weight: normal;
>    font-size: 11px;
> }
> tr.suggestHeader td{
>    background-color: #eeeeee;
>    border-bottom:1px solid #fff;
>    padding: 5px 10px;
>    color: #393939;
>    font-weight: normal;
> }
> td.suggestFooter{
>    height:1px;
> }
> td.suggestTextQuery{
>    font-weight: bold;
>    padding: 2px 15px 2px 10px;
> }
> span.suggestTextQueryTyped{
>    color: #85B916;
>    text-decoration: underline;
> }
> td.suggestTextType{
>    padding: 2px 5px 2px 15px;
>    width: 30%;
>    background-color: #85B916;
> }
> td.suggestTextAmount{
>    padding: 2px 5px 2px 15px;
>    width: 30%;
>    text-align: right;
>    background-color: #85B916;
> }
> tr.suggestRow{
>    padding: 2px 2px 2px 0px;
>    background-color: #FCFCFC;
> }
> tr.suggestHighlight{
>    color: black;
>    background-color: #85B916;
> }
> tr.suggestHighlight span.suggestTextQueryTyped{
>    color: #fff;
> }
> ```

Die Werte für `top` und `left` an `div.suggestLayer` sind auf ein bestimmtes Shopdesign gemünzt. Passen Sie sie an Ihre Kopfzeile an, oder positionieren Sie den Layer relativ zum Suchfeld.

## Der erweiterte Suggest-Layer

Der erweiterte Layer teilt die Vorschläge in zwei Spalten: links Produktvorschläge mit Bild, rechts die übrigen Suchbegriffe. Er braucht jQuery, holt die Vorschläge per JSONP und reagiert auf mehr Tasten.

### Welche Fassung Sie brauchen

Sie unterscheiden sich zusammen in dreizehn Zeilen. Diese Seite zeigt deshalb eine Fassung und beschreibt die beiden Abweichungen.

| Ihre Umgebung | Was zu tun ist |
| - | - |
| jQuery 3, FACT-Finder 6.8 oder 6.9 | die Vorlage unverändert übernehmen |
| jQuery 2, FACT-Finder 6.8 oder 6.9 | eine Zeile ändern, siehe unten |
| FACT-Finder 6.10 | eine Zeile ergänzen, siehe unten |

Welche FACT-Finder-Version Sie einsetzen, klären Sie mit Omikron.

### Die Abweichung für jQuery 2

jQuery 3 hat `.error()` entfernt. Die Vorlage verwendet deshalb `.fail()`. Für jQuery 2 ändern Sie diese eine Zeile am Ende von `getSuggestions()` zurück:

```js theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
.error(function (e, xhr, settings, exception) {
```

### Die Abweichung für FACT-Finder 6.10

Ab 6.10 liefert FACT-Finder die Vorschläge nicht mehr als blankes Array, sondern verpackt in ein Objekt mit der Eigenschaft `suggestions`.

Das geht einfacher. Ergänzen Sie in der Antwortfunktion von `getSuggestions()` direkt nach `pCurrentSelection = -1;` eine Zeile:

```js theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
$.getJSON(requestURL,
	function (jsonObj, textStatus) {
			pCurrentSelection = -1;
			if (jsonObj && jsonObj.suggestions) { jsonObj = jsonObj.suggestions; }
			if (jsonObj != null && jsonObj.length > 0) {
```

Danach ist `jsonObj` in beiden FACT-Finder-Versionen das Array der Vorschläge, und der Rest der Datei bleibt unverändert.

> [!WARNING]
>
> Sie folgt aus dem Vergleich der beiden Originaldateien, deren einziger sachlicher Unterschied dieses Auspacken ist. Prüfen Sie sie in einem Testshop, bevor Sie sie übernehmen.
>
> Die Originaldatei für 6.10 enthält an einer Stelle `pSuggest[i] = pSuggest[i];`, eine Zuweisung ohne Wirkung. Sie ist beim Umbenennen aus `pSuggest[i] = jsonObj[i];` entstanden und ein weiteres Zeichen dafür, dass die vier Dateien mechanisch auseinander hervorgegangen sind.

### Die Parameter von init()

`init()` nimmt hier vierzehn Parameter statt acht. Die ersten acht sind dieselben wie beim einfachen Layer.

| Parameter | Bedeutung |
| - | - |
| `showImages` | `true` zeigt Produktbilder in der linken Spalte |
| `sid` | die Sitzungskennung des Besuchers, wird an FACT-Finder weitergereicht |
| `uid` | die Kundenkennung |
| `site` | eine Kennung der Umgebung, beispielsweise der Shopname |
| `displayElementCallback` | eine Funktion, die für jeden angezeigten Vorschlag aufgerufen wird |
| `translation` | ein Objekt mit den Beschriftungen, siehe unten |

`sid`, `uid` und `site` werden nur angehängt, wenn sie gefüllt sind. Sie landen sowohl in der Suggest-Anfrage als auch im Ziel-Link, den ein angeklickter Vorschlag ansteuert. FACT-Finder wertet sie für seine Statistik aus.

### Das Übersetzungsobjekt

Anders als der einfache Layer enthält der erweiterte keine fest eingebauten Texte. Er erwartet sie im Parameter `translation`:

| Schlüssel | Verwendung |
| - | - |
| `product` | die Einzahl hinter einer Trefferzahl von eins |
| `products` | die Mehrzahl. Der Platzhalter `{0}` wird durch die Zahl ersetzt |
| `<typ>.headline` | die Überschrift je Vorschlagstyp, beispielsweise `productName.headline` |

Fehlt eine Überschrift, verwendet das Modul den technischen Typnamen.

### Die Rückmeldefunktionen

Drei davon sind globale Funktionen, die Sie einfach definieren. Die vierte übergeben Sie an `init()`.

| Funktion | Wird aufgerufen |
| - | - |
| `onSuggestCompleted(sichtbar)` | nachdem die Vorschläge gezeichnet wurden. Der Parameter sagt, ob der Layer sichtbar ist |
| `onSuggestLayerHidden()` | nachdem der Layer ausgeblendet wurde |
| `onSubmitSuggest(vorschlag)` | wenn der Besucher einen Vorschlag auswählt. Gibt die Funktion eine Adresse zurück, springt der Browser dorthin statt auf den von FACT-Finder vorgeschlagenen Link |
| `displayElementCallback(begriff, typ, refKey)` | für jeden einzelnen angezeigten Vorschlag |

> [!NOTE]
>
> `displayElementCallback` läuft verzögert, das Modul stellt jeden Aufruf um zehn Millisekunden zurück. Verlassen Sie sich darin also nicht darauf, dass der Layer noch sichtbar ist.
>
> Mit `onSubmitSuggest` hängen Sie eigene Zielseiten an Vorschläge, beispielsweise um einen Kategorievorschlag direkt auf die Kategorieseite statt auf die Suche zu führen.

### Die Klassen, die das Modul erwartet

Das Modul setzt diese Klassen selbst in das erzeugte HTML. Ihr Stylesheet muss sie kennen.

| Klasse | Element |
| - | - |
| `suggestLayerBlockText` | die rechte Spalte mit den Suchbegriffen |
| `suggestLayerBlockImage` | die linke Spalte mit den Produktvorschlägen |
| `suggestHeader` | eine Überschrift je Vorschlagstyp |
| `suggestRow` | eine Vorschlagszeile |
| `suggestRowWithImage` | eine Vorschlagszeile mit Produktbild |
| `suggestHighlight` | die gerade ausgewählte Zeile |
| `suggestImage` | das Produktbild |
| `suggestTextQuery` | der Vorschlagstext |
| `suggestTextQueryTyped` | der Teil des Vorschlags, den der Besucher schon getippt hat |
| `suggestTextAmount` | die Trefferzahl |
| `suggestParentCategory` | die übergeordnete Kategorie eines Produktvorschlags |
| `noborder` | ergänzt die Bildspalte, wenn die Textspalte leer bleibt |

### ff\_big\_suggest.css

> [accordion] ff\_big\_suggest.css
>
> ```css theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
> /*****************************************************************************/
> /*** SUGGEST Fact Finder ***/
> /*****************************************************************************/
>
> /* Abweichungen normale Styles */
> #head {
>    position: relative;
> }
>
> #head_search {
>    position: static !important;
> }
>
> /* SUGGEST */
> div.suggestLayer{
>    display: none;
>    top: 85px;
>    right:0px;
>    padding: 0;
>    position: absolute;
>    z-index: 1000;
>    font-size: 1em;
>    font-weight:bold;
>    color: #595959;
>    border: 1px solid #486891;
>    }
>
> ul.suggestLayerList,
> ul.suggestLayerBlock,
> div.suggestLayerBlock{
>    width: 988px;
>    left:0px;
>    top: 39px;
>    cursor: pointer;
>    float: left;
>    font-size: 1em;
>    list-style: none outside none;
>    background: #ebeff3;
>    border: 1px solid #f9f8f8;
>    }
>
> .suggestLayerBlockText{
>    float: right;
>    width: 242px;
>    padding: 0px 20px 16px 20px;
>    background:#486891;
>    color:#fff;
>    height:100%;
>    }
>
> .suggestLayerBlockImage{
>    float: left;
>    width: 670px;
>    padding: 0px 0px 16px 20px;
>    }
>
> ul.suggestLayerList li,
> ul.suggestLayerBlock li,
> ul.suggestLayerBlockText li,
> ul.suggestLayerBlockImage li{
>    display: block;
>    list-style: none outside none;
>    }
>
> ul.suggestLayerBlockText li:hover span.suggestTextQuery{
>    color: #fff;
>    text-decoration:underline;
>    }
>
> ul.suggestLayerBlockImage li:hover span.suggestTextQuery{
>    color: #004287;
>    text-decoration:underline;
>    }
>
> .suggestLayerBlockText span.suggestTextQueryTyped{
>    color:#fff;
>    text-decoration:underline;
>    }
>
> .suggestLayerBlockImage span.suggestTextQueryTyped{
>    color:#004287;
>    text-decoration:underline;
>    }
>
> li.suggestHeader,
> li.suggestHeader:hover{
>    font-size: 14px;
>    text-transform:uppercase;
>    clear:both;
>    float:none;
>    color:#004287;
>    font-weight:normal;
>    text-align:left;
>    padding:20px 0px 8px 0px;
>    }
>
> .suggestLayerBlockText li.suggestHeader,
> .suggestLayerBlockText li.suggestHeader:hover{
>    color:#fff;
>    }
>
> .suggestLayerBlockText > li.suggestHeader:first-child,
> .suggestLayerBlockImage > li.suggestHeader:first-child{
>    margin-top:0px;
>    }
>
> .suggestLayerBlockImage > li.suggestHeader:first-child{
>    line-height:15px;
>    }
>
> .suggestLayerBlockImage li span.suggestTextQuery,
> .suggestLayerBlockText li span.suggestTextQuery{
>    display: block;
>    overflow: hidden;
>    font-weight:normal;
>    text-align: left;
>    font-size: 1em;
>    }
>
> .suggestLayerBlockText li.suggestRow{
>    line-height: 20px;
>    padding-left: 10px;
>    background: url(../../images/web/navi_level_2.gif) no-repeat 0px 10px;
> }
>
> span.suggestTextAmount{
>    display: block;
>    float:right;
>    margin-top: -19px;
>    font-weight: normal;
>    color: #fff;
>    width: 50px;
>    font-size: 11px;
>    }
>
> .suggestLayerBlockImage li.suggestRow{
>    padding-right: 16px;
>    margin-top: 8px;
>    float:left;
>    }
>
> li.suggestRowWithImage{
>    height: 75px;
>    width: 300px;
>    background:#ffffff;
>    margin: 0px 10px 0px 0px;
>    }
>
> span.suggestImage{
>    float: left;
>    height: 75px;
>    text-align: center;
>    width: 75px;
>    background-color: #fff;
>    }
>
> ul.suggestLayerBlockImage li span.suggestTextQuery{
>    height: 70px;
>    }
>
> .suggestLayerBlockImage li span.suggestTextQuery,
> .suggestLayerBlockText li span.suggestTextQuery{
>    display: block;
>    overflow: hidden;
>    width: 190px;
>    }
>
> .suggestLayerBlockImage li span.suggestTextQuery{
>    width: 210px;
>    padding: 15px 0px 0px 15px;
>    }
>
> span.suggestImage img{
>    max-height: 75px;
>    max-width: 75px;
>    }
>
> .suggestParentCategory{
>    display:none;
>    }
>
> .search_noresult{
>    margin:40px 0;
>    }
> .search_noresult p{
>    font-size:14px;
>    font-weight:bold;
>    }
> .search_noresult ul{
>    margin:20px 0;
>    }
> ```

> [!WARNING]
>
> Dieses Stylesheet stammt aus einem konkreten Shopdesign. Die festen Breiten von 988, 670 und 242 Pixeln, die Auswahl `#head_search` und das Hintergrundbild `navi_level_2.gif` passen nur dort. Nehmen Sie es als Gerüst, nicht als fertige Gestaltung.
>
> `.suggestParentCategory` ist auf `display: none` gesetzt. Das Modul liefert die übergeordnete Kategorie eines Produktvorschlags also mit, das Beispiel blendet sie nur aus. Entfernen Sie die Regel, wenn Sie sie zeigen wollen.

### Woher Sie ff\_big\_suggest.js bekommen

Die Datei selbst ist hier nicht abgedruckt. Sie ist 509 Zeilen lang und besteht fast vollständig aus Ablauflogik, die Sie unverändert übernehmen: Tastatursteuerung, Auf- und Abbau des Layers, Zusammenbau der Links. Alles, was Sie daran einstellen, steht oben auf dieser Seite.

| | |
| - | - |
| Dateiname im Shop | `ff_big_suggest.js` |
| Fassung | jQuery 3 mit FACT-Finder 6.8 und 6.9 |
| Bezugsquelle | WEBSALE, zusammen mit der übrigen FACT-Finder-Direktanbindung |

Für die beiden Abweichungen bei jQuery 2 und FACT-Finder 6.10 ändern Sie je eine Zeile, wie oben beschrieben.

Falls Sie die Datei nicht zur Hand haben, fragen Sie bei WEBSALE nach. Weil die Direktanbindung nicht mehr weiterentwickelt wird, ändert sich an ihr nichts mehr.

## Was beide Stufen gemeinsam haben

Beide erwarten ein Suchformular mit einem Namen und ein leeres `div` für den Layer. Beide hängen sich an das Eingabefeld und nicht an einen Knopf. Und beide bieten eine Funktion, mit der Sie den Layer von außen schließen können:

```js theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
meineInstanz.hideLayerOutsideCall();
```

Das brauchen Sie, wenn Ihr Shop den Layer bei einem Klick an anderer Stelle schließen soll, etwa beim Öffnen der Warenkorbvorschau.


## Related topics

- [Materialien FACT-Finder-Templates](https://dokumentation.websale.de/v8s/materialien/materialien-fact-finder-templates.md)
- [Integration von FACT-Finder](https://dokumentation.websale.de/v8s/integration-von-fact-finder/integration-von-fact-finder.md)
- [Materialien FINDOLOGIC-Dateien](https://dokumentation.websale.de/v8s/materialien/materialien-findologic-dateien.md)
- [Hinweise zur Fehlerbehebung](https://dokumentation.websale.de/v8s/fehlerbehebung.md)
- [FactFinder WebComponents](https://dokumentation.websale.de/v8s/integration-von-fact-finder/factfinder-webcomponents.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.