Page 1 of 1

Autocomplete zoeken met jquery ui via php

Posted: Mon Jan 30, 2012 5:40 pm
by stv
Voor de (eenvoudige) xml variant van deze tutorial: http://forum.cmsmadesimple.org/viewtopi ... 2&p=271601

LET OP! Deze tutorial is op eigen risico!! Test het dan ook eerst in een 'leeg' cms!!!

Op verzoek van Rolf:

Veel van jullie zullen het wellicht wel eens tegenkomen. Een zoekveld met autocomplete (http://jqueryui.com/demos/autocomplete/
en
http://www.imdb.com/.

Dit is een leuke optie voor je website, maar bovenal erg gebruiksvriendelijk voor je bezoekers. Deze tutorial laat je zien hoe je dit met cmsms kan realiseren via php. Je kan dit combineren met vrijwel elke module. In deze tutorial gaan we een variant maken van de autocomplete die imdb.com momenteel gebruikt. Voor deze tutorial maak ik gebruik van de module Products.

Wat heb je nodig voor deze tutorial?

CMSMS
- Module Products
* Met een velddefinitie (voor afbeeldingen) genaamd afbeelding1
- sitemapms

Javascript/jQuery
- Laatste versie van jQuery (http://jquery.com/)
- Laatste versie van jQuery ui (http://jqueryui.com/download)
Download de pack met --> core, widget en position (onder UI Core) samen met autocomplete (onder widget). Selecteer onder 'theme' no theme.

----------------------------------------
Stap 1. Voorbereiding
Plaats de jquery files in je template samen met een leeg bestand genaamd functions.js (deze gebruiken we later):

Code: Select all

<__script__ src="js/jquery-1.7.1.js"></__script>
<__script__ src="js/jquery-ui-1.8.17.min.js"></__script>
<__script__ src="js/functions.js"></__script>
Plaats de tag {Products action="search"} in je template.

Maak in de Productmodule een velddefinitie aan voor een afbeelding. Onder naam 'afbeelding1' en onder promp 'Hoofdafbeelding'. Kies type 'afbeelding' en zorg dat het vinkje voor publiek veld geselecteerd is.

Stap 2. Searchtemplate aanpassen
Om jquery autocomplete werkend te krijgen dienen we de search template aan te passen:
Vervang

Code: Select all

<div class="row">
  <p class="row_prompt">{$mod->Lang('search_name')}:</p>
  <p class="row_input">
    <input type="text" name="{$actionid}cd_prodname" size="40" maxlength="255"/>
  </p>
</div>
met

Code: Select all

<div class="row ui-widget">
  <p class="row_prompt">{$mod->Lang('search_name')}</p>
  <p class="row_input">
    <input type="text" id="zoek_veld" name="{$actionid}cd_prodname" size="40" maxlength="255" />
  </p>
</div>
In de template geef je nu aan waar de jquery autocomplete toegepast moet worden. In de eerste div is de class 'ui-widget' toegevoegd en in de input is een ID toegevoegd.


Stap 3. Voorbereiding php bestand
De gegevens die worden weergegeven in de autocomplete zoekresultaten worden gehaald uit een php bestand. In het geval van imdb.com zal dit zijn
- een afbeelding,
- een titel,
- een onderschrift.

Aangezien we met Products werken, zal ik het onderschrift vervangen voor de prijs. Zorg er voor dat je in de instelling van de Products Module onder 'instellingen afbeelding afhandeling' automatisch een miniatuur afbeelding maakt. Ik heb hier 60 ingevuld.


Stap 4. php bestand opbouwen
Via Sitemapms gaan we een php bestand maken waar alle producten in komen te staan met de velden die genoemd zijn in stap 3. Sitemapms genereert standaard een xml bestand. Aangezien we een php bestand nodig hebben, moeten we de module dus enigszins aanpassen. Het is namelijk van belang voor deze tutorial dat er een fysiek php bestand op de server staat, anders krijg je een foutmelding. Omdat vele van jullie sitemapms waarschijnlijk al gebruiken voor je sitemap.xml, zal ik de module zodanig aanpassen dat deze gewoon naast elkaar gebruikt kunnen worden.

Download Sitemapms (SiteMapMadeSimple), ik gebruik versie 1.2.5 in deze tutorial.
Unpack het bestand.
1. Verander de naam van de hoofdmap van SiteMapMadeSimple naar AutoComplete
2. Verander de naam van SiteMapMadeSimple.module.php naar AutoComplete.module.php
3. Verander de naam SiteMapMadeSimple op regel 40 (class SitemapMadeSimple extends etc) en 48 (function GetName () {return 'SiteMapMadeSimple' etc) in AutoComplete.module.php naar AutoComplete
4. Verander alle sitemap.xml termen naar search.php in de volgende bestanden: action.default.php, function.admin_info_tab.php
5. Verander [sS]itemap.xml naar [sS]earch.php in AutoComplete.module.php
6. Tot slot, zoek in lang/ext/nl_NL.php de friendlyname en verander dit naar AutoComplete

Upload de module map en installeer 'm.
Maak een bestand aan genaamd search.php en plaats deze in de root map van je server. Wijzig de permissie naar 777

Als het goed is staat er nu onder uitbreidingen de module 'AutoComplete'
Wijzig het sample sjabloon in deze module naar het volgende:

Code: Select all

{literal}<?php

$producten = array(
{/literal}
{capture assign='producten_lijst'}{Products pagelimit="9999999"}{/capture}
{foreach from=$items item='entry'}
{capture name=thumbafbeelding assign=thumbafbeelding}{assign var='field' value=$entry->fields}{$entry->file_location}/{$field.afbeelding1->thumbnail}{/capture}
   {literal}array('titel'=>'{/literal}{$entry->product_name|cms_html_entity_decode}{literal}', prijs=>'{/literal}{$entry->price}{literal}', afbeelding=>'{/literal}{$thumbafbeelding}{literal}',url=>'{/literal}{$entry->detail_url}{literal}'),{/literal}
{/foreach}

);
{literal}
$term = trim(strip_tags($_GET['term']));

$matches = array();
foreach($producten as $titel){
   if(stripos($titel['titel'], $term) !== false){
      $titel['value'] = $titel['titel'];
      $titel['label'] = "{$titel['titel']}";
      $matches[] = $titel;
   }
}

$matches = array_slice($matches, 0, 5);
print json_encode($matches);


?>{/literal}
Controleer of de search.php goed wordt weergegeven zonder fouten: http://www.jouwdomein.nl/search.php
Als het goed is zie je alleen '[]'. Als dit niet het geval is, maak dan een wijziging in een van je producten. Selecteer een product en druk gelijk op toepassen. Dan wordt de search.php bijgewerkt.

Stap 5. functions.js instellen met gewenste html
Standaard ondersteunt jQuery UI autocomplete geen afbeeldingen in de zoekresultaten lijst. De standaard html die gegenereerd wordt door jQuery UI is als volgt:

Code: Select all

<ul class="ui-autocomplete">
  <li><a>Tekst</a></li>
</ul>
Dit is natuurlijk niet zoals wij het willen. De ouput die ik voor ogen heb is als volgt

Code: Select all

<ul class="ui-autocomplete">
  <li>
     <a>
       <div class="zoek-item-wrapper">
          <div class="zoek-item-img"><img src="http://voorbeeld.nl/uploads/product_1/afbeelding.jpg" /></div>
          <div class="zoek-item-tekst">
              <div class="zoek-item-naam">Productnaam XX</div>
              <div class="zoek-item-prijs">€ 25</div>
          </div>
       </div>
       <div class="clear"></div>
    </a>
  </li>
</ul>
Nu denken veel van jullie.. 'hey.. een <a> is een inline element en hier mogen geen divs in': Dat weet ik, alleen is die <a> nodig anders komt de gewenste naam niet in je search input.

Vervolgens moet er nog wat jquery in de functions.js worden gestopt om de boel werkend te krijgen. Om de output te krijgen die ik voor ogen heb, heb ik de standaard jquery aangepast. Plak het volgende in de functions.js

Code: Select all

$(document).ready(function(){
	var ac_config = {
		source: "search.php",
		minLength:1,
		select: function (event, ui) {
			var bestemming = ui.item.url
			window.location = bestemming
		}
	};
	$("#zoek_veld").autocomplete(ac_config).data( "autocomplete" )._renderItem = function( ul, item ) {
					var inner_html = '<a><div class="zoek-item-wrapper"><div class="zoek-item-img"><img src="' + item.afbeelding + '"></div><div class="zoek-item-tekst"><div class="zoek-item-naam">' + item.value + '</div><div class="zoek-item-prijs">&euro; ' + item.prijs + '</div></div><div class="clear"></div></div></a>';
					return $( '<li></li>' )
						.data( "item.autocomplete", item )
						.append(inner_html)
						.appendTo( ul );
					};
});	

Stap 6. Css opmaak
Plak het volgende in je ccs:

Code: Select all

ul.ui-autocomplete {list-style:none; background:#fff; width:350px; /*height:400px; overflow:hidden*/}
	ul.ui-autocomplete li { border-bottom:1px solid #e8e8e8}
	ul.ui-autocomplete li a {border:1px solid #fff; color:#999; display:block; cursor:pointer !important}
		ul.ui-autocomplete li a:hover {background:#f1f1f1; border:1px solid #db9300}

.zoek-item-wrapper {padding:5px}
	.zoek-item-img {float:left; padding:0 10px 0 0}
	.zoek-item-tekst {float:left}
		.zoek-item-naam {font-size:14px; font-weight:bold; padding:0 0 3px 0}
		.zoek-item-prijs {font-size:12px}
.clear {clear:both}
-----------------------------------------
Als je bovenstaande goed gevolgd hebt, dan moet alles nu werken! If not, ask!

Succes!