Προγραμματισμός

Φορτώνοντας μια sidebar του WordPress με AJAX

Στο προηγούμενο άρθρο έγραψα λίγα πράγματα για το redesign αυτού του ιστοχώρου, ο οποίος είναι πλέον responsive. Ωστόσο, το ελαστικό design είναι ένα μόνο βήμα προς τη δημιουργία ενός φιλικού προς τις φορητές συσκευές website (που ήταν η αρχική ιδέα του RWD) αφού η μικρή οθόνη δεν είναι το μοναδικό «πρόβλημα» ενός smartphone. Πρέπει να λάβουμε υπόψιν την περιορισμένη μνήμη (και αποθηκευτικό χώρο, προσωρινό ή μόνιμο) και τον αργό επεξεργαστή, που οι δυνατότητές του συνήθως απέχουν πολύ από τις δυνατότητες ενός desktop ή φορητού υπολογιστή. Ξεκινάω την προσπάθεια περαιτέρω βελτίωσης φορτώνοντας την δεξιά πλαϊνή μπάρα μόνο αν υπάρχει χώρος να την δείξω.

Θα πρέπει να γνωρίζεις λίγα πράγματα για το WordPress για να παρακολουθήσεις το άρθρο γιατί δεν θα παρουσιάσω κάτι που μπορείς να το κάνεις copy-paste στο δικό σου site — εκτός κι αν έχεις μια sidebar σαν τη δική μου, την οποία θέλεις να φορτώνεις μόνο όταν πρόκειται να την δείξεις, όπως εγώ! Παρεπιπτόντως, αν δεν βλέπεις τη δεξιά στήλη για την οποία γίνεται όλη η συζήτηση θα πρέπει να ανοίξεις το παράθυρο του browser σου σε πλάτος μεγαλύτερο από 1280 pixels. Για αρχή, θα υπενθυμίσω πως ορίζουμε μία sidebar και πως τη χρησιμοποιούμε.

register_sidebar(
	array(
		'id' => 'sidebar',
		'name' => __( 'Main Sidebar', $text_domain )
	)
);

Ο παραπάνω κώδικας μπαίνει στο functions.php του theme μας και δημιουργεί μία θέση για widgets -όχι απαραίτητα sidebar, το όνομα είναι παραπλανητικό- με id sidebar (θα πρέπει να διαλέξεις κάποιο id που να σημαίνει κάτι σχετικό με το δικό σου theme) και με το όνομα Main Sidebar, το οποίο το περνάω από τη συνάρτηση __() για λόγους localization και δεν θα μας απασχολήσει στο συγκεκριμένο άρθρο. Τα περιεχόμενα αυτής της θέσης είναι διαχειρίσιμα από το administration του WordPress και παρουσιάζονται στον χρήση με τη συνάρτηση dynamic_sidebar( 'sidebar' ) σε κάποιο από τα templates του theme. Στο συγκεκριμένο theme, η sidebar εμφανίζεται όντως στο πλάι, δεξιά, αν υπάρχει αρκετός χώρος, περιλαμβάνει 2 widgets που θεώρησα πως δεν είναι απαραίτητο να εμφανίζονται παντού και κρατάω τον χώρο με ένα <div id="secondary-sidebar"></div> στο footer.php (αυτό είναι το template όπου εμφανίζω αυτή την μπάρα). Τώρα θα πρέπει να προσθέσω μερικές γραμμές στο functions.php:

wp_enqueue_script( 'prince_v8_js', get_template_directory_uri() . '/js/prince_v8.js', array( 'jquery' ), false, true );
wp_localize_script( 'prince_v8_js', 'ajaxObject', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );

add_action('wp_ajax_sidebar_visible', 'prince_v8_sidebar_visible_callback');
add_action('wp_ajax_nopriv_sidebar_visible', 'prince_v8_sidebar_visible_callback');
function prince_v8_sidebar_visible_callback() {
	global $wpdb;
	dynamic_sidebar('sidebar');
	die();
}

Η συνάρτηση wp_enqueue_script() είναι ο ενδεδειγμένος τρόπος να φορτώνω αρχεία Javascript στο theme. Το WordPress θα φροντίσει να φορτώσει το prince_v8.js μετά την jQuery, πριν από το </body>. Η συνάρτηση wp_localize_script() στη συγκεκριμένη περίπτωση χρησιμοποιείται για να μου δώσει το ακριβές path προς το αρχείο admin-ajax.php, που -αν και περιέχει τη λέξη admin- μπορεί να διαχειριστεί οποιαδήποτε λειτουργία AJAX ζητήσω. Η δεύτερη παράμετρος (ajaxObject) είναι πολύ σημαντική! Έπειτα χρησιμοποιώ δύο action hooks του WordPress, τα wp_ajax_ και wp_ajax_nopriv_ στα οποία προσθέτω το event sidebar_visible, που θα προγραμματίσω σύντομα. Φροντίζω και τα δύο hooks να καλούν την ίδια συνάρτηση prince_v8_sidebar_visible_callback που ακολουθεί. Ο λόγος που χρειάζομαι και τα δύο hooks είναι πως το ένα ενεργοποιείται για logged-in χρήστες ενώ το άλλο για τους απλούς επισκέπτες. Τέλος, η συνάρτηση prince_v8_sidebar_visible_callback που θα «τρέξει» όταν προκύψει ένα από τα δύο παραπάνω events κάνει μόνο μία δουλειά: καλεί τη sidebar με το id που επέλεξα νωρίτερα, σα να είχα αυτόν τον κώδικα μέσα σε template.

( function( $ ){
	var data = { action: 'sidebar_visible' },		// this is used in add_action('wp_ajax_', ) and add_action('wp_ajax_nopriv_', );
		$sidebar = $( '#secondary-sidebar' ),		// find the (initially) empty DIV
		loadSidebar = function() {
			$sidebar.addClass( 'spinner' );		// add a .spinner class, to show an animated .GIF
			$.post( ajaxObject.ajaxurl, data,		// ajaxObject is my namespace, assigned in wp_localize_script()
				function( response ) {				// success
					if ( response.length > 2 )		// the ajax request might return -1 or 0
						$sidebar.html( response ).addClass( 'loaded' ); // render the HTML and add the .loaded class to let us know
				}
			).always( function() {
				$sidebar.removeClass( 'spinner' );	// remove the .spinner class, whether we got data or not
			} );
		}

	$( function(){								// document ready
		if ( $sidebar.is( ':visible' ) && !$sidebar.hasClass( 'loaded' ) ) // if the sidebar is not display:none and if we have not already loaded the data
			loadSidebar();						// load!
	} );

	$(window).resize( function() {
		if ( $sidebar.is( ':visible' ) && !$sidebar.hasClass( 'loaded' ) )
			loadSidebar();						// load again!
	} );
} )( jQuery );

Ο κώδικας Javascript βρίσκεται στο αρχείο prince_v8.js, το οποίο το έχω φορτώσει νωρίτερα με wp_enqueue_script. Αρχικά ορίζω ένα data object το οποίο παρακάτω θα το περάσω σαν παράμετρο στο admin-ajax.php και πρόκειται για το event που όρισα νωρίτερα. Μετά βρίσκω το #secondary-sidebar με jQuery και το βάζω σε μια μεταβλητή και εν συνεχεία φτιάχνω μια συνάρτηση που θα κάνει όλη τη δουλειά. Την ονομάζω loadSidebar και σκοπεύω να την καλέσω 1-2 φορές. Στην αρχή, προσθέτω ένα class .spinner στο #secondary-sidebar το οποίο εμφανίζει ένα animated gif.

#secondary-sidebar.spinner { background:url(../img/spinner.gif) center top no-repeat; height:32px; }

Έπειτα καλώ τη συνάρτηση post() της jQuery δίνοντας το URL προς το αρχείο admin-ajax.php (ajaxObject.ajaxurl) που θα αναλάβει να εκτελέσει το event μου, το όνομα του event (data) ώστε να ενεργοποιηθεί το κατάλληλο action (sidebar_visible) και τα hooks (wp_ajax_ και wp_ajax_nopriv_), μία ανώνυμη συνάρτηση που θα τρέξει σε περίπτωση επιτυχίας, και προσθέτω ακόμα μία ανώνυμη function στο event always που τρέχει είτε πάρω τα δεδομένα που ζήτησα είτε όχι, και απλώς αφαιρεί το animated gif από το #secondary-sidebar. Η function που εκτελείται στην περίπτωση success πρώτα ελέγχει αν η απάντηση του server έχει μήκος μεγαλύτερο από 2 χαρακτήρες και είναι ένας εύκολος (αλλά όχι απαραίτητα ο καλύτερος) τρόπος για να ελένξω αν όντως έχω τα δεδομένα των widget, αφού, σε περίπτωση λάθους ο server στέλνει είτε -1 είτε 0. Αν δεν υπάρξει πρόβλημα, ο κώδικας των widget μπαίνει σαν περιεχόμενο στο #secondary-sidebar και προσθέτω κι ένα class .loaded που θα το χρησιμοποιήσω λίγο παρακάτω.

Η συνάρτηση loadSidebar καλείται αρχικά στο document ready event της jQuery και έπειτα, κάθε φορά που γίνεται resize το παράθυρο του browser. Και στις δύο περιπτώσεις πρώτα ελέγχω αν όντως εμφανίστηκε η μπάρα #secondary-sidebar χρησιμοποιώντας το is( ':visible' ) φίλτρο της jQuery. Αρχικά, η κολώνα έχει display:none και επομένως, δεν είναι :visible αλλά αν το πλάτος του παραθύρου είναι μεγαλύτερο από 1280 pixels, τότε εφαρμόζεται το κατάλληλο CSS media query και αλλάζει σε display:block. Τέλος, ελέγχω αν έχει ήδη το class .loaded που σημαίνει πως έχω ήδη φέρει τα περιεχόμενα της sidebar και δεν υπάρχει λόγος να το ξανακάνω.

Με την πρώτη ματιά μπορεί να φαίνεται πολύ κακό για το τίποτα αλλά η δυνατότητα να φορτώνεις widgets με AJAX, κάτω από συνθήκες που μπορείς να προγραμματίσεις εσύ ο ίδιος, προσφέρει μεγάλες δυνατότητες προσαρμογής ενός website στο περιβάλλον του επισκέπτη. Οι δυνατότητες είναι απεριόριστες, όρεξη να'χεις!

Σχολιάστε

Η ηλ. διεύθυνσή σας δεν κοινοποιείται. Τα υποχρεωτικά πεδία σημειώνονται με *