VirtueMart 1.1: aggiornare il carrello via Ajax
In VirtueMart 1.1, quando siamo nella pagina del carrello possiamo modificarne il contenuto:
- aumentare o diminuire la quantità di un prodotto
- eliminare interamente uno prodotto dal carrello
Solitamente questa operazione ricarica la pagina, vediamo invece come realizzare la stessa funzionalità via Ajax.
Pagina del carrello
Dopo aver navigato su un e-commerce realizzato con VirtueMart e aggiunto uno o più prodotti al carrello, a un certo punto decidiamo che è ora di concludere l’acquisto.
Un bravo webmaster avrà quindi reso ben visibile il link per andare alla pagina del carrello, dove vediamo il riepilogo completo dei nostri prodotti con la possibilità di effettuare delle modifiche.
Ecco un dettaglio della pagina che ci si presenta.
Nota: ovviamente questa è la pagina standard priva di personalizzazioni grafiche; su altri e-commerce potrebbe essere leggermente diversa.
Modifica del carrello
Solitamente, anche dopo gli adattamenti grafici la colonna delle azioni rimane visibile.
Come si può facilmente intuire, i pulsanti in questione servono per aggiornare la quantità o eliminare una intera riga dal carrello.
Il comportamento di default di VirtueMart, se usiamo uno di questi pulsanti, è quello di effettuare la modifica e ricaricare la pagina.
Modifica Ajax
Nel libro “Joomla! VirtueMart 1.1 Theme and Template Design“, di cui abbiamo già avuto modo di parlare in passato, viene presentata una soluzione per modificare il comportamento di base e rendere tali modifiche dinamiche tramite l’uso di Ajax.
Facciamo prima una piccola parentesi.
Non è raccomandabile mettere mano al codice senza sapere quello che si sta facendo. Copiare e incollare del codice in un certo file solo perchè lo vedere scritto su un blog è una pessima idea. Per cui, se non avete idea di cos’è Ajax, se non sapete nulla o quasi di PHP e JavaScript, e il codice sotto riportato è totalmente incomprensibile per voi, non consigliamo di applicare le modifiche.
Detto questo, ecco come si fa.
1. Modifica della form
Nel caso stiate usando il tema di default di VirtueMart, il file da modificare si trova all’interno della cartella
/components/com_virtuemart/themes/default/templates/basket/
Altrimenti, sostituite “default” con il nome del vostro tema.
Qui dovete modificare il file basket_b2c.html.php nel caso mostriate i prezzi con IVA, o il file basket_b2b.html.php nel caso mostriate i prezzi senza IVA.
Oppure modificateli entrambi, in modo che siate coperti in entrambi i casi.
Dopo la riga che dice
<?php foreach( $product_rows as $product ) { ?>
fate spazio e inserite il seguente codice:
<?php // use ajax to update cart if on shop cart page if ($_REQUEST['page']=='shop.cart') { $product['update_form'] = str_replace( '<form ', '<form onsubmit="handleUpdateCart( this );return false;"', $product['update_form'] ); } ?>
Il codice sopra riportato inserisce nella form il comando JavaScript che richiama la funzione handleUpdateCart() e annulla la sottomissione effettiva della form (quindi evita che venga ricaricata la pagina).
La funzione handleUpdateCart() non esiste ancora ma la andremo a creare tra un momento.
2. Funzione JavaScript
Nella cartella principale del vostro tema trovate il file theme.js. Quindi, supponendo che stiate usando il tema di default dovrete aprire il file
/components/com_virtuemart/themes/default/theme.js
altrimenti sostituite “default” con il nome del vostro tema.
Alla fine del file aggiungete il seguente codice
function updateCart() { var callbackCart = function(responseText) { $("vmMainPage").innerHTML=responseText; } var option = { method: 'post', onComplete: callbackCart, data: { only_page: 1, page: "shop.cart", option: "com_virtuemart" } } new Ajax( live_site + '/index2.php', option).request(); } function handleUpdateCart( frm ) { formCartAdd = $( frm ); var callback = function(responseText) { updateCart(); updateMiniCarts(); } var opt = { method: 'post', data: $(frm), onComplete: callback, evalScripts: true } new Ajax(formCartAdd.action, opt).request(); }
Tutto questo aggiunge nello script di supporto anche la funzione che gestisce l’aggiornamento della pagina in modalità dinamica.
Nota: str_replace
In VirtueMart 1.1 molto del codice HTML viene generato direttamente nelle classi o nelle pagine anziche nei template come sarebbe più corretto. Per cui anche una piccola modifica, quale aggiungere un attributo HTML a un elemento, rischia di diventare complicata.
Innanzitutto, i file del sistema VirtueMart (tutto quanto contenuto in /administrator/components/com_virtuemart) non andrebbero mai modificati per evitare problemi successivi durante gli aggiornamenti.
Tramite le user_class o le user_pages possiamo estendere o sovrascrivere classi e pagine, ma a volte diventa scomodo riscrivere un’intero file solo per modificare un ID o un attributo HTML.
Nel libro che abbiamo citato sopra questo problema viene aggirato tramite un frequente uso della funzione PHP str_replace: l’HTML già generato viene successivamente modificato andando a cercare una stringa e sostituendola con un altra. Nel caso visto sopra, alla form di modifica del carrello viene aggiunto l’attributo onsubmit per poter inserire la gestione Ajax.
Da un punto di vista del mantenimento del codice, questa è una buona idea: ci consente di inserire la personalizzazione direttamente nel template, dove è giusto che stia, e dove è più facile da individuare.
Tuttavia questo introduce una elaborazione aggiuntiva che, a seconda della complessità della sostituzione e del numero di volte che deve essere effettuata, può andare a interferire leggermente con le prestazioni del sito.
E’ vero che in proporzione ai tempi di accesso al database e ai tempi di scaricamento della pagina questo ritardo può essere marginale, ma se ci tenete alle prestazioni – e se avete un e-commerce dovete tenerci per forza – il consiglio è di usare str_replace solo se siete sicuri che sia l’unico metodo disponibile.
Umbobabo
Ciao,
complimenti molto interessante il tuo articolo.
Sto cercando un modo per permettere all’utente di aggiornare un prodotto non solo nella quantità ma anche nella scelta di eventuali attributi selezionati sul prodotto.
Lato form nessun problem però penso di dover fare la funzione di controllo sull’oggetto $cart ad-hoc.
Hai qualche consiglio da darmi?
Francesco
@umbobabo:
se stai cercando una soluzione anche commerciale ti suggerisco di dare un’occhiata alla nostra estensione Precart: http://www.gibilogic.com/precart-dettaglio-prodotto (o, se sei nel campo della stampa digitale, anche http://www.gibilogic.com/digital-printing-shop).