Dynamic page update by AJAX - javascript

I've got a problem.
I'm using AJAX to load pages and it works correctly, but I can't escape a bug.
When I load page, first time it works correctly but then I go to another page, AJAX loads the page I want, but it has double tags like <head> and <footer>.
I mean when I load page a second time, the page loads the same page in <div>.
It's like picture in picture.
I use in templates code like this:
<?php echo $header ?>
My content
<?php echo $footer ?>
And every page load the same code after I get back to previous page by link.
My ajax code:
function showContent(link) {
var cont = document.getElementById('content');
var loading = document.getElementById('loading');
window.history.replaceState('', 'Title', link);
cont.innerHTML = loading.innerHTML;
var http = createRequestObject(); // создаем ajax-объект
if( http ) {
http.open('get', link); // инициируем загрузку страницы
http.onreadystatechange = function () { // назначаем асинхронный обработчик события
if(http.readyState == 4) {
cont.innerHTML = http.responseText; // присваиваем содержимое
}
}
http.send(null);
} else {
document.location = link; // если ajax-объект не удается создать, просто перенаправляем на адрес
}
}
// создание ajax объекта
function createRequestObject() {
try { return new XMLHttpRequest() }
catch(e) {
try { return new ActiveXObject('Msxml2.XMLHTTP') }
catch(e) {
try { return new ActiveXObject('Microsoft.XMLHTTP') }
catch(e) { return null; }
}
}
}
What Can I do?
Because if I delete Tags header and footer my page doesn't have design at all.
And as u see, I change URL (important for me).
I need solution which will help me load templates without double-tagging.

In your template, be sure that you have something like
<?php echo $header ?>
<div id="content">My content</div>
<?php echo $footer ?>
And that id="content" is unique, only there and not in your $header or $footer.

This can happen if you are not clearing the previous content and the new content is being "appended" to the existing DOM.
So following points could be your solution.
In each ajax call, before updating the container element, clear the existing element, eg. cont.innerHTML = '';
Remember to keep track of any event bindings that are coming with the incoming response.
Move this line var cont = document.getElementById('content'); inside the ajax call.

If the pages you're pulling in with the JavaScript XHR (Ajax) also contain the PHP header and footer code, then you'll need to replace those also with your XHR:
<div id="content">
<?php echo $header ?>
My content
<?php echo $footer ?>
</div>
Wrap your content div tag around the header and footer in order to overwrite them rather than duplicate them.
Alternatively, the way I've implemented a PHP template system is like this:
index.php
<?php
// GET PAGE
if ( isset($_GET['page'])
&& '' != $_GET['page']
&& !preg_match('!^(/|\.|(ht|f)tp://)!', $_GET['page'])
) $page = $_GET['page'];
else $page = 'home.html';
// EXECUTE TEMPLATE
require('template.php');
?>
template.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title of the document</title>
</head>
<body>
<!-- plain HTML header goes here -->
<!-- RETRIEVE PAGE -->
<?php require('pages/' . $page); ?>
<!-- plain HTML footer goes here -->
</body>
</html>
samplepage.html
<h2>Sample Page Header</h2>
<p>Sample page content goes here.</p>
phppage.php
<h2>PHP Page Header</h2>
<p><?php echo 'PHP page content goes here.'; ?></p>
Everything goes to the index.php file. You can use PHP to block direct access to page files, or if using Apache web server you can use .htaccess to redirect all requests to the index.php file.
The technical URL looks like http://example.net/index.php?page=samplepage.html. But, using .htaccess can be effectively converted to http://example.net/samplepage.html with:
RewriteRule ^(.*)$ index.php?page=$1&%{QUERY_STRING} [L]

Related

How can I load the page before PHP starts creating an archive of photos?

I'm trying to allow users to create an archive of photos located on the server side and download this archive without waiting in the meantime on a white page without knowing whats happening until PHP finishes to execute.
I've got a list of photos inside an html form on say index.html.
<form action="include/download_archive.php" method="POST" id="downloadForm">
<input type="hidden" name="downloadForm" value="downloadForm">
<ul id="photos">
//JavaScript populates this list with photos once the document is ready.
</ul>
</form>
There is also a button that triggers a javascript function which submits the form.
document.getElementById('downloadForm').submit();
On the PHP page (say download_archive.php) that processes the form submission, I'm reading the array of images, creating an archive and then providing with a download link to the archive.
if(isset($_POST['downloadForm']) && $_POST['downloadForm']=="downloadForm"){
ignore_user_abort(true);
ini_set('max_input_vars','500000' );
set_time_limit(0);
//Checking if the zip already exists and remove it
if(file_exists('../collections/Zips/'.$collection.'.zip'))
unlink('../collections/Zips/'.$collection.'.zip');
//Get the array of images
$images = $_POST['images'];
//Push the images into a new array with the correct path
foreach($images as $image => $value) {
array_push($files, "../collections/".$collection."/".$value);
}
//Create a new archive
$zip = new ZipArchive;
$zip->open('../collections/Zips/'.$collection.'.zip', ZipArchive::CREATE);
//Add the files to the archive
foreach ($files as $file) {
$zip->addFile($file);
}
//Store the relative location to the zip file
$zipPath = '../collections/Zips/'.$collection.'.zip';
//If the zip was succesfully closed, echo a download link.
if($zip->close()){
$link = BASE_URL2."collections/Zips/".$collection.'.zip';
$link = str_replace(" ", "%20", $link);
echo "<a href='".$link."'>Download photos</a>";
}
The main problem is that once I select the photos on the main page and hit the "download" button and the form is being submitted by javascript. I'm bound to wait there, on the main page until the whole PHP script is done and only then I'm redirected to the PHP page.
I thought about having a form on the PHP page which handles the creation of the archive and I would be getting the files array through the main form submission and then when the PHP page has fully loaded, make a fetch api request to the inner form, but I'm having trouble keeping the data throughout these operations(the array of files).
I also thought about asynch PHP, but couldn't find a way to handle that other than socket-way which seems limited.
I believe I'm overcomplicating it, how can I accomplish this?
You could run the script with exec, put it in the background and then take the user to the next page. On this page, you can have ajax check for the script to finish, while the user is given a message or something so they know something is happening. Once the script is complete; your page can then update with a link to download the file.
exec('nohup /var/.../script.php > /dev/null 2> /dev/null & echo $!');
That will run the script as a background process and your page doesn't need to wait for it.
You can even get the process id when you run it using $pid = exec($command ,$op); or $pid = (int)$op[0]; which you can pass back to your page and have the next page poll for it to finish:
$command = 'ps -p '.$pid;
exec($command, $op);
if (! isset($op[1])) {
// process finished
}
else {
// still running
}
OK - here is my fully working answer:
index.php:
<?php
exec('nohup php run.php > /dev/null 2> /dev/null & echo $!', $op);
$pid = (int)$op[0];
header('location: check.php?pid='.$pid);
run.php:
<?php
sleep(5);
check_process.php:
<?php
header("HTTP/1.1 200 OK");
$pid = $_REQUEST['pid'];
$command = 'ps -p '.$pid;
exec($command, $op);
if (! isset($op[1])) {
$output = 'script finished';
}
else {
$output = 'script running';
}
print $output;
check.php:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Check</title>
</head>
<body>
<div id="result"></div>
<script>
check_process('<?=$_REQUEST['pid']?>');
function check_process(pid) {
console.log('pid: '+pid);
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
if(xmlhttp.responseText == 'script running') {
check_process(pid);
}
document.getElementById("result").innerHTML = xmlhttp.responseText;
}
else if (xmlhttp.status == 400) {
alert('There was an error 400');
}
else {
alert('something else other than 200 was returned');
}
}
};
xmlhttp.open("GET", "check_process.php?pid="+pid, true);
xmlhttp.send();
}
</script>
</body>
</html>
Put all these in the same directory and open index.php. It will spawn a background process which, as an example will sleep for five seconds. It will send you to a page where is shows the script is running. When the script dies; it will update the page to tell you it's finished. I hope this helps. Let me know if you have any questions though.

Why is my admin-ajax so slow compared to other sites that also use it?

Here is my site.
If you hover over one of the projects and click the plus icon, the Ajax call goes out and the response returns in 1-4 seconds on average. I'm not understanding why it's so slow compared to a similar site that also uses admin-ajax.php (try hovering/clicking on one of the projects on that site to compare). All of the images called by Ajax are optimized. I also optimized my database tables. I'm not sure what else I can do.
Here is a comparison of the response time of admin-ajax.php from both sites. As you can see, the other site takes 480ms while mine takes 2s:
Here is how I have my Ajax call set up. Sorry, I didn't simplify the code because I think maybe the reason for the delay can only be found in the full code. The actual Ajax call is about halfway down.
(function($) {
// Function to allow an event to fire after all images are loaded
$.fn.imagesLoaded = function () {
var imgs = this.find('img[src!=""]');
// If there are no images, just return an already resolved promise
if (!imgs.length) {
return $.Deferred().resolve().promise();
}
// For each image, add a deferred object to the array which resolves when the image is loaded
var dfds = [];
imgs.each(function(){
var dfd = $.Deferred();
dfds.push(dfd);
var img = new Image();
img.onload = function(){dfd.resolve();};
img.src = this.src;
});
// Return a master promise object which will resolve when all the deferred objects have resolved
// IE - when all the images are loaded
return $.when.apply($, dfds);
};
// Function for additional styling
function projectStyles() {
// Check the first slide input
$('#slider input:first').attr('checked', 'checked');
$('#project-wrapper').addClass('activated');
// Make the articles grey again after activation
$('article.project').addClass('grayscale grayscale-fade').css('opacity', '0.4');
// CSS effects
$('.post-container').addClass('fadeInUp');
$('.close-button').addClass('fadeInDown');
// Remove pesky, sticky 'hover' class
$('article.project').removeClass('hover');
}
// Make the max-height of the container exact for a smoother transition
function matchContainerHeight() {
var heightHandler = function() {
var containerHeight = $('#project-container').outerHeight();
$('#project-wrapper.activated').css('max-height', containerHeight);
};
setTimeout(heightHandler, 100);
$(window).on('resize', heightHandler);
}
// Open the project container
function openProject() {
var post_id = $(this).data('id'), // data-id attribute for .post-link
ajaxURL = site.ajaxURL; // Ajax URL localized from functions.php
// Add a loading icon
$('<span class="loading-icon"></span>').insertBefore(this);
// Add the 'active' class to make sure the div stays dark while loading
$(this).closest('article.project').addClass('active hover-sticky');
// Make all the articles grey when an article is clicked
$('article.project').addClass('grayscale grayscale-fade grayscale-sticky').css('opacity', '0.4');
// No hover on images while a project is loading
$('article.project img').addClass('nohover');
// Remove all corner ribbons
$('article').removeClass('current');
$('.corner-ribbon').remove();
// Add a corner ribbon to note the current activated project
$(this).closest('article.project').removeClass('active').addClass('current');
$('<div class="corner-ribbon">Current</div>').prependTo('article.current');
// Call Ajax
$.ajax({
type: 'POST',
url: ajaxURL,
data: {'action': 'load-content', post_id: post_id },
success: function(response) {
// Wait until all images are loaded
$('#project-container').html(response).imagesLoaded().then(function() {
// Fire again to rearrange the slide in the DOM
resize();
// Remove all 'hover' classes
$('article.project').removeClass('hover-sticky grayscale-sticky');
$('article.project img').removeClass('nohover');
// Remove the loading icon
$('.loading-icon').remove();
// If the user has scrolled...
if ($(window).scrollTop() !== 0) {
// First scroll the page to the top
$('html, body').animate({
scrollTop : 0
},400, function() {
matchContainerHeight();
projectStyles();
});
// If the user has not scrolled...
} else {
matchContainerHeight();
projectStyles();
}
return false;
});
}
});
}
// User event
$('#content').on('click', '.post-link', function(e) {
e.preventDefault();
var projectTitle = $(this).data('title'), // data-title attribute for .post-link
projectSlug = $(this).data('slug'); // data-slug attribute for .post-link
// Calls openProject() in context of 'this' (.post-link)
openProject.call(this);
$('head').find('title').text(projectTitle + ' | Keebs');
});
})(jQuery);
Here is the Ajax response file. I'm using the ACF plugin, but I tried the response without any of the ACF fields and the wait time was the same. I also tried removing everything within the my_load_ajax_content() function but the wait time was still the same as well. So I'm guessing something else is causing the long wait time. I also tried GET instead of POST but the response time was around the same:
<?php
/**
* Ajax functions
*/
// Return the post content to the AJAX call
function my_load_ajax_content () {
$args = array(
'p' => $_POST['post_id'],
'post_type' => 'projects'
);
$post_query = new WP_Query( $args );
while( $post_query->have_posts() ) : $post_query->the_post(); ?>
<div class="post-container">
<div id="project-left-content">
<?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
<?php the_content(); ?>
<?php if( get_field('client') ): ?>
<div class="client">
Client(s): <?php the_field('client'); ?>
</div>
<?php endif; ?>
<div class="project-cats">
<?php
$cat_names = wp_list_pluck( get_the_category(), 'cat_name');
echo join( ', ', $cat_names );
?>
</div>
<?php if( get_field('url') ): ?>
<div class="project-link">
<a class="first after" href="http://<?php the_field('url'); ?>" target="_blank"><?php the_field('url'); ?></a>
</div>
<?php endif; ?>
</div>
<div id="project-right-content">
<?php if( have_rows('slides') ): ?>
<div id="slider">
<!-- Slider Setup -->
<?php if( have_rows('slides') ):
$slideNumber = 0;
while ( have_rows('slides') ) : the_row();
$slideNumber++;
?>
<input type="radio" name="slider" id="slide<?php echo $slideNumber; ?>">
<?php endwhile;endif; ?>
<!-- Slide -->
<?php if( have_rows('slides') ): ?>
<div id="slides">
<div id="overflow">
<div class="inner">
<?php if( have_rows('slides') ):
while ( have_rows('slides') ) : the_row();
$slideImage = get_sub_field('slide_image');
?>
<article>
<img src="<?php echo $slideImage; ?>" alt="<?php the_title(); ?>">
</article>
<?php endwhile;endif; ?>
</div><!-- #inner -->
</div><!-- #overflow -->
</div><!-- #slides -->
<?php endif; ?>
<!-- Controls -->
<?php if( have_rows('slides') ):
$slideNumber = 0;
?>
<div id="active">
<?php while ( have_rows('slides') ) : the_row();
$slideNumber++;
?>
<label for="slide<?php echo $slideNumber; ?>"></label>
<?php endwhile; ?>
</div><!-- #active -->
<?php endif; ?>
</div><!-- #slider -->
<?php endif; ?>
</div><!-- #project-right-content -->
</div><!-- .post-container -->
<?php
endwhile;
wp_die();
}
add_action ( 'wp_ajax_nopriv_load-content', 'my_load_ajax_content' ); // when the user is logged in
add_action ( 'wp_ajax_load-content', 'my_load_ajax_content' ); // when the user is not logged in
Does anybody see something that I should be doing differently?
Looks like your site is hosted on dreamhost and most likely on shared hosting offering they have. The other website you mentioned looks like it is hosted on its own VPS. Shared hosting is often known for their slow database performance.
Your best option might be to use a caching solution like 'WP Super Cache' or 'W3 Total Cache' that saves the webpage to memory or disk on first request and serves from there on subsequent requests bypassing the database.
These are both wordpress plugin and can be easily installed from the admin plugins section.
https://wordpress.org/plugins/wp-super-cache/
https://wordpress.org/plugins/w3-total-cache/
Other option is trying to create indexes on the databse for faster searching. You could also look at using a small VPS (AmazonEC2 free tier or $5/month from digital ocean etc) if you know how to install Apache/mysql etc.
I would want to suggest you that rather then echoing HTML code from your php file you just return the main data(only raw information based on the click) as json response and then generate the html tags based on that and append it . Creating HTML from javascript is much faster than echoing HTML , specially during ajax call. I am sure if you do this you can get quite fast performance. Any big or large site they dont send HTML in ajax response. Majorly pure json response containing the key information is echoed. And on basis of that the divs are generated to load the section faster.
Can I make a suggestion?
Instead of defining your function like this:
(function($)
try something like this:
jQuery(document).ready(function($) {
$('selector').whatever();
})
I'm still learning Wordpress myself but I have found that defining the function as using jQuery can make a difference. I think this is because Wordpress is unsure of which library you want to use.

Echoed Javascript Code from PHP Via AJAX Not Running

My code is meant to get the author of an inputted book using the Google Books API via AJAX. If nothing is inputted it prints "Empty". What it actually does is print out the Javascript code when a book is inputted. When nothing is inputted, it prints "Empty" as it should. How could I modify my code to make the echoed Javascript execute and hence get the author of an inputted book?
Just to see, I replaced the echo part with echo "<script>document.getElementById('txtBox').innerHTML = 'Hello';</script>";. It also prints out the javascript code, so I don't think it has something to do with using the API.
getAuthor.html
<!DOCTYPE html>
<html>
<body>
<!-- Input -->
<div class="form">
<form onsubmit="makeRequest(); return false">
<input type="text" id="inputText" name="inputText">
<input type="submit">
</form>
</div>
<br>
<!-- Output -->
<div class="txtBox">
<textarea id="txtBox">
</textarea>
</div>
<!-- AJAX to create output using jEcho.php file-->
<script>
function makeRequest() {
httpRequest = new XMLHttpRequest();
console.log(httpRequest.responseText);
httpRequest.onreadystatechange = function() {
document.getElementById("txtBox").innerHTML = httpRequest.responseText;
};
httpRequest.open("POST", "jEcho.php", true);
httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");
httpRequest.send("inputText=" + document.getElementById("inputText").value);
}
</script>
</body>
</html>
jEcho.php
<?php
$input = $_POST["inputText"];
if ($input == "") {
echo "Empty";
} else {
// used to parse
// e.g. The Rosie Project -> The+Rosie+Project
$temp = str_replace(" ", "+", $input);
// create appropiate source
$scriptSource = "https://www.googleapis.com/books/v1/volumes?q=$temp&callback=handleResponse";
echo "<script>
function handleResponse(response) {
var item = response.items[0];
document.getElementById('txtBox').innerHTML = item.volumeInfo.authors[0];
}
</script>
<script src='$scriptSource'></script>";
}
?>
Links
Echoing Javascript From PHP:
How to call a JavaScript function from PHP?
Echoing javascript from PHP
Google Books API:
https://developers.google.com/books/docs/v1/getting_started
https://developers.google.com/books/docs/v1/using
<script> elements are only run when your page is first loaded. Script elements created later on, either by assigning to an element's .innerHTML, creating them using document.createElement(), or otherwise, are not executed.
If you want to have a PHP script send back code to be evaluated, you'll have to do that directly, e.g:
httpRequest.onreadystatechange = function() {
eval(httpRequest.responseText);
};
(And remove the <script> tags from the response.)
Try setting header in jEcho.php file (not tested)
header('Content-Type: application/javascript');
I'm not allowed to comment so:
I'm not certain what has caused it for but could <script src='$scriptSource'></script>"; be called before the handleResponse function. I'm not too sure what is causing it, at the moment, that is my best idea.
Also could you not just have the url already in the code like this: (jEcho.php)
<?php
$input = $_POST["inputText"];
if ($input == "") {
echo "Empty";
} else {
// used to parse
// e.g. The Rosie Project -> The+Rosie+Project
$temp = str_replace(" ", "+", $input);
// create appropiate source
//$scriptSource = "https://www.googleapis.com/books/v1/volumes?q=$temp&callback=handleResponse";
echo "
<script src='https://www.googleapis.com/books/v1/volumes?q=$temp&callback=handleResponse'></script>
<script>
function handleResponse(response) {
var item = response.items[0];
document.getElementById('txtBox').innerHTML = item.volumeInfo.authors[0];
}
</script>";
}
?>

Click counter when link is clicked PHP/JS

I have a little script here that counts clicks when link is clicked and stores it in .txt file, but it works fine when I have only "click=yes" under href. But I can't make it to track clicks when I have link to external site.
Here is my code:
<?php
if(!file_exists('counter.txt')){
file_put_contents('counter.txt', '0');
}
if($_GET['click'] == 'yes'){
file_put_contents('counter.txt', ((int) file_get_contents('counter.txt')) + 1);
header('Location: ' . $_SERVER['SCRIPT_NAME']);
die;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>counter example</title>
</head>
<body>
<h1><?php echo file_get_contents('counter.txt'); ?></h1>
clickMe
</body>
</html>
My guess is it has to do something with header('Location: ' . $_SERVER['SCRIPT_NAME']); but I can't figure it out so I could really use some help.
And is it somehow possible to have multiple links save to the same file, and when I show it on website it's sorted from largest number to smallest? I have an idea how to do it with MySQL database but I can't use it at place where this will be implemented.
Thanks in advance!
Cheers!
Your server never sees the URI being accessed as the client leaves your page. To do something like this, it may be best to set up a redirect which works like this
click me
(Make sure the external site's URL is URL encoded as you're passing it as a GET component of a URL to your own page)
Then in goto.php you store your click and send a redirect header
if(!file_exists('counter.txt')){
file_put_contents('counter.txt', '0');
}
file_put_contents('counter.txt', ((int) file_get_contents('counter.txt')) + 1);
header('Location: ' . $_GET['href']);
Now you can track these clicks, you can add your domain-specific counters in goto.php instead of your text file
You could use Javascript to catch click on a link , send data via AJAX call. Here is small sample using JQuery.
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(
function() {
$('a').click(linkClicked);
}
);
//this funciton will be called on every click on any link on page
function linkClicked() {
var url = $(this).attr('href');
//call PHP script to save URL ./saveurlclicks.php?url=CLICKEDURL
$.get('./saveurlclicks.php', {'url': url})
//be sure to return true so user can navigate further
return true;
}
</script>
</head>
<body>
<a href='/some href' >asasa</a>
<a href="www.google.com" >google</a>
</body>
</html>
<?php
//saveurlclicks.php
// here we save links in file but using serialized array
// if you need to get count of links clicked ,
// have a second script that unserializes array and sort it in revers order
$url = #$_GET['url'];
$counterFile = 'counter.ser';
if ($url) {
if(file_exist($filename))
$links = unserialize(file_get_contents($filename));
else $links=array();
if (!isset($links[$url])) {
$links[$url] = 0;
}
$links[$url] ++;
file_put_contents($counterFile, serialize($links));
}
I love the simple solution by Paul S., but if you want to track the clicks with date, you can do something like this:
03/03/2022 14
04/03/2022 2
<?php
$dateexists = false;
if(!file_exists('counter.txt'))
{ $fh = fopen('counter.txt', 'w');
fclose($fh); }
$datecounts = file('counter.txt', FILE_IGNORE_NEW_LINES);
foreach($datecounts as $key => $datecount){
list($date, $count) = explode("\t", $datecount);
$count = (int) $count;
if($date == date('d/m/Y'))
{ $datecounts[$key] = $date."\t".++$count;
$dateexists = true; }
}
if(!$dateexists)
{ $datecounts[] = date('d/m/Y')."\t1"; }
$fh = fopen('counter.txt', 'w');
if (flock($fh, LOCK_EX)) {
foreach($datecounts as $datecount)
{ fwrite($fh, $datecount.PHP_EOL); }
flock($fh, LOCK_UN);
}
else
{ //couldn't lock, might want to do stuff here }
fclose($fh);
header('Location: ' . $_GET['href']); // the redirect
?>

Graceful Javascript Degradation - external source files

Easy question for a coder well-versed in JS.
I'm building a Wordpress site that uses jQuery AJAX methods, reloading either my entire content area when a top nav link is clicked or my main content area when a sidebar nav link is clicked. I want to be sure that the AJAX call is only issued if the user's browser supports JavaScript. I found some reference material here and on other sites that said by referencing my script externally, a browser unequipped with JavaScript would simply ignore all JS files. Is this accurate? I considered using php:
$my_arr = get_browser(null,true);if $my_arr['javascript'] == 1 {
echo '<script type="text/javascript" src="path/to/script"';
}
The UX I'm going for is if JS is enabled, then fire AJAX calls; if JS is disabled, just send the user to the page they've requested.
e.g.
<?php
/**
* The template for displaying all pages.
*
$ajxy = $_GET['ajxy'];
if(!is_null($ajxy)) {
$ajax_code = $ajxy;
}
if(!$ajxy) {
get_header();
}
?>
<?php if(!$ajax_code) { ?>
<div id="primary">
<div id="content" role="main">
<div class="container_12" id="contentWrapper">
<?php } ?>
<div id="contentContainer" <?php if($ajax_code) { echo 'class="ajxn"'; } ?>>
<?php while ( have_posts() ) : the_post(); ?>
<div class="grid_8" id="contentGrid">
<?php
get_template_part( 'content', 'page' );
?>
</div>
<?php get_sidebar(); ?>
<?php endwhile; // end of the loop. ?>
</div>
<?php if(!$ajax_code) { ?>
</div>
</div><!-- #content -->
</div><!-- #primary -->
<?php } ?>
<!---My Ajax Loading Script -->
<script type="text/javascript" src="<?php echo get_template_directory_uri(); ?>/js/ajxy.js"></script><!---My Ajax Loading Script -->
<?php
if(!$ajxy) {
get_footer();
}
?>
and the script:
function ajxnOff(list, ajxnCode, wrapper, container) {
jQuery(list).click(function(e) {
e.preventDefault();
var $lnkGoz = jQuery(this).attr("href");
var $lnkGozAjx = $lnkGoz + '?ajxy=' + ajxnCode;
var $ajxyContainer = wrapper;
var $ajxyCurThing = container;
$ajxyCurThing.fadeOut(400, function() {
$ajxyContainer.html('<div id="loaderA"></div>');
jQuery("div#loaderA").fadeIn(400);
jQuery.ajax({
url: $lnkGozAjx,
success: function(data) {
jQuery("div#loaderA").delay(2000).fadeOut(400, function() {
$ajxyContainer.html(data);
jQuery("div.ajxn").fadeIn(400);
jQuery.remove("div#loaderA");
});
}
});
});
});
}
jQuery(document).ready(function() {
ajxnOff(jQuery("ul#topNavList a"), 1, jQuery("div#contentWrapper"), jQuery("div#contentContainer"));
ajxnOff(jQuery("ul#sidebarNavList a"), 2, jQuery("div#contentGrid"), jQuery("div#contentPageContainer"))
});
I've been learning to code on my own for about 6 months and don't have any books on the subject, so any help from the experts around here is greatly appreciated.
Here is a simple pattern to do unobtrusive ajax navigation with fallback to non-ajax links.
In your HTML:
<a class="ajaxnav" href="page.html">Text</a>
In your script:
$(".ajaxnav").click(function(event) {
event.preventDefault();
// do ajax nav here;
// URL is in event.currentTarget.href, modify it however necessary
});
If javascript is not supported, the script is simply not run, and you're left with standard web anchors with valid HREFs. If javascript is supported, the script replaces all "ajaxnav" link handling with your ajax click handler. Easy as pie.
Yes, if the user's browser either doesn't support JS or has JS disabled, script tags are essentially ignored. It doesn't hurt to include them no matter what, you just have to plan your site for what happens when they're not utilized.
As far as AJAX versus page reload goes, you simply code your site as if there were no AJAX, i.e. all links should have appropriate href attributes point to where they should go. If JS is enabled, you attach your AJAX to the links via its onclick handler and prevent the default action by returning false from whatever function handles the click event.

Categories