ProcessWire - Ajax
Aus Wikizone
Version vom 11. Februar 2019, 11:16 Uhr von 93.208.103.149 (Diskussion)
Man kann mit PW relativ einfach dynamische Webseiten erzeugen. Dabei werden nur die benötigten Teile der Webseite ausgetauscht, anstatt die Seite nach jedem Klick neu zu laden. So entsteht sehr schnell ein "App-Feeling". ProcessWire unterstützt einen dabei.
Links:
https://webdesign.tutsplus.com/tutorials/how-to-create-an-ajax-driven-theme-for-processwire--cms-26579 (Kurzanleitung) https://github.com/tutsplus/how-to-create-an-ajax-driven-theme-for-processwire (ProcessWire Profile mit AJAX)
Allgemeines Vorgehen
- Links mit der Klasse ajax-link werden über JavaScript (meist jQuery) abgefangen und über AJAX an den Server geschickt.
- ProcessWire erkennt anhand der internen System-Variable $ajax dass ein AJAX Request vorliegt
- Mit einfachen Ifs kann man ProcessWire dazu bringen nur den gewünschten Content zu generieren
- Den zurückgegebenen HTML Inhalt mit jQuery austauschen.
Natürlich sind auch JSON Antworten denkbar. Das kann man dann alles über JavaScript verarbeiten
Vereinfachtes Beispiel (bessere Struktur wäre wohl die Teile der Seiten in Variablen zu laden und dann die if Statements kompakt zu halten.
<?php
// include page structure if not an ajax request
if(!$ajax):
include("./head.inc");
?>
<!-- ... -->
<?php echo $pages->get('/')->title; ?>
<nav><!-- ... --></nav>
<div class="content-container cf">
<div class="content current-content">
<?php endif; // end if ajax ?>
<?php
// if ajax then only return $content
echo $content;
?>
<?php if(!$ajax): ?>
</div>
</div>
<?php
include("./foot.inc");
endif; // end if ajax
?>
JavaScript
$(function() {
var href;
var title;
$('body').on('click','a.ajax-link',function(e) { // nav link clicked
href = $(this).attr("href");
title = $(this).attr("name");
// load content via AJAX
loadContent(href);
// prevent click and reload
e.preventDefault();
});
function loadContent(url){ // Load content
// variable for page data
$pageData = '';
// send Ajax request
$.ajax({
type: "POST",
url: url,
data: { ajax: true },
success: function(data,status){
$pageData = data;
}
}).done(function(){ // when finished and successful
// construct new content
$pageData = '<div class="content no-opacity ajax">' + $pageData + '</div>';
// add content to page
$('.content-container').append($pageData);
// remove old content
$('.content.current-content').remove();
// show new content and clean up classes
$(this).removeClass('no-opacity').removeClass('ajax').addClass('current-content');
}); // end of ajax().done()
} // end of loadContent()
});
Komplexeres Beispiel mit Einbeziehen der Browser History, verhindern von doppeltem Laden bereits vorhandener Inhalte...
PHP bleibt gleich.
JavaScript
$(function() {
// fitvids for responsivce videos
$(".content .video").fitVids();
// light box
$('.gallery').Chocolat();
// flexslider
$('.flexslider').flexslider({
pauseOnHover: true,
controlNav: false,
prevText: "",
nextText: "",
});
/*
* HTML5 pushstate and ajax content
*/
var href;
var title;
$('body').on('click','a.ajax-link',function(e) { // nav link clicked
// check to see it contents already accessed
if($(this).hasClass('current')){
console.log('current page');
// prevent click through
e.preventDefault();
// exist click function (dont load new content)
return true;
}
$('.current').removeClass('current'); // remove .current from active link
$('.parent').removeClass('parent'); // remove .current from active link
$(this).addClass('current'); // add .current
var parent = $(this).attr('parent');
if(parent){ // if link page has parent nav
$('nav a[name="'+parent+'"]').addClass('parent'); // add .current
}
// add progress spinner on cursor
$('body').css('cursor','progress');
// remove cusor spinner
var pointerTimeout = setTimeout(function () {
$('body').css('cursor','auto'); // progress spinner on cursor
}, 1000);
href = $(this).attr("href");
title = $(this).attr("name");
// load content via AJAX
loadContent(href);
// add new url to html5 history
history.pushState('', +href, href); // push url to history
// change title to new page
$('title').html(title);
// send GA pageview
ga('send', 'pageview', href);
// prevent click and reload
e.preventDefault();
});
// for back / forwards browser navigation
var toggleHistoryVisitNum = 0;
function toggleHistory(){
window.onpopstate = function(event) {
if(window.location.hash == ""){
loadContent(location.pathname);
}
};
}
function loadContent(url){ // Load content
// variable for page data
$pageData = '';
// send Ajax request
$.ajax({
type: "POST",
url: url,
data: { ajax: true },
success: function(data,status){
$pageData = data;
}
}).done(function(){ // when finished and successful
// construct new content
$pageData = '<div class="content no-opacity ajax">' + $pageData + '</div>';
// add content to page
$('.content-container').append($pageData);
// animate the requested content
$('.content.current-content').animate({
// animate out old content
opacity: 0
}, 400, function(){
$('.content.current-content').slideUp(400);
// content animation finished
$('.content.ajax').animate({
// animate in new content
opacity: 1
}, 400, function(){
// remove old content
$('.content.current-content').remove();
// show new content and clean up classes
$(this).removeClass('no-opacity').removeClass('ajax').addClass('current-content');
/*
* run js functions for new content
*/
// fitvids for responsivce videos
$(".content .video").fitVids();
// light box
$('.gallery').Chocolat();
});
});
// toggle use of back and forward buttons on browser
if(!toggleHistoryVisitNum){
toggleHistory();
}
// keep track of number of Ajax requests
toggleHistoryVisitNum++;
}); // end of ajax().done()
} // end of loadContent()
});