ProcessWire - Ajax

Aus Wikizone
Wechseln zu: Navigation, Suche

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()
});