Snapshot management
Pugpig presents your content using a web view, but during navigation it shows a captured image (or snapshot) of the web view instead. If your content changes over time, you must ensure that the web view matches the snapshot or you will see an unpleasant transition when Pugpig switches between the image of the web view and the web view itself.
Waiting for a snapshot
Ideally you should wait for the snapshot to complete before you start changing the page (e.g. starting CSS animations). Pugpig can trigger a Javascript function once the snapshot is taken like this:
<meta name="callbackWhenSnapshotFinished" content="yourJavascriptFunctionName"/>
Basic example below
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Callback when snapshot finished</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<meta name="callbackWhenSnapshotFinished" content="snapshotCallback" />
<style>
.test-status {
background: maroon;
color: white;
font-size: 24px;
padding: 20px;
}
.has-run {
background: green;
}
</style>
</head>
<body>
<h1>Callback when snapshot finished</h1>
<p>This page should run the specified JavaScript callback when the snapshot is removed.</p>
<div class="test-status">Callback has not fired - I should be in the snapshot</div>
<script>
window.snapshotCallback = function() {
var ts = document.querySelectorAll( '.test-status' )[ 0 ];
ts.innerText = 'Callback fired - I should never be in the snapshot';
ts.className = ts.className + ' has-run';
};
</script>
</body>
</html>
Alternative example
Add the meta tag into the head of your html and ensure your scripts are added to the bottom of the html.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Callback when snapshot finished</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<meta name="callbackWhenSnapshotFinished" content="snapshotCallback" />
<style>
.test-status {
background: maroon;
color: white;
font-size: 24px;
padding: 20px;
}
.has-run {
background: green;
}
</style>
</head>
<body>
<h1>Callback when snapshot finished</h1>
<p>This page should run the specified JavaScript callback when the snapshot is removed.</p>
<div class="test-status">Callback has not fired - I should be in the snapshot</div>
<script src="main.js"></script>
</body>
</html>
In your main.js, add the following:
window.PUGPIG = {};
document.addEventListener('DOMContentLoaded', function() {
if (!inApp()) {
snapshotCallback();
}
});
function inApp() {
return window.location.protocol.search(/http(s)?/) === -1;
}
function snapshotCallback() {
// add your code here
var ts = document.querySelectorAll( '.test-status' )[ 0 ];
ts.innerText = 'Callback fired - I should never be in the snapshot';
ts.className = ts.className + ' has-run';
}
Delaying a snapshot
Sometimes you want to build your page by manipulating the DOM using Javascript. If you do this, you must tell Pugpig to wait until you're done before taking the snapshot:
<meta name="delaySnapshotUntilReady" content="yes"/>
When you've built your page, tell Pugpig that it can proceed with the snapshot. We use a helper:
var Messaging =(function(){
function Messaging(){}
Messaging.fn = Messaging.prototype;
Messaging.fn.postMessage = function( message ){ //avoid popup on safari and IE if(window.location.protocol.search(/https?/) === -1){
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src","pugpig://"+ message);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
};
return new Messaging();
}());
and then invoke it like this:
Messaging.postMessage('onPageReady');
Basic example below
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Delay snapshot until ready</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <meta name="delaySnapshotUntilReady" content="yes" /> <style> .test-status { background: maroon; color: white; font-size: 24px; padding: 20px; } .has-run { background: green; } </style> </head> <body> <h1>Delay snapshot until ready</h1> <p>This page should not snapshot until it is told to.</p> <div class="test-status"> Snapshot taken before I told it to be taken - I should not be in the snapshot </div> <script> var Messaging = (function() { function Messaging() {} Messaging.fn = Messaging.prototype; Messaging.fn.postMessage = function( message ) { var iframe = document.createElement("IFRAME"); iframe.setAttribute("src", "pugpig://" + message); document.documentElement.appendChild(iframe); iframe.parentNode.removeChild(iframe); iframe = null; }; return new Messaging(); }()); var ts = document.querySelectorAll( '.test-status' )[ 0 ]; ts.innerText = 'Snapshot taken after I told it to be taken - I should be in the snapshot'; ts.className = ts.className + ' has-run'; Messaging.postMessage( 'onPageReady' ); </script> </body> </html>
Pausing snapshots
Occasionally you will have a page that requires heavy user interaction. Usually Pugpig continues snapping other pages in the background, which can decrease responsiveness. You can tell Pugpig to temporarily stop snapshotting:
<meta name="stopSnapshotting" content="yes"/>
This technique should only be used sparingly because it stops all snapshotting for as long as the user is on the page with the meta tag.
Single-load pages
Occasionally you will have pages that must not be loaded more than once at the same time (for example, they access database storage in a non-concurrent way). You should mark such pages like this:
<meta name="concurrent" content="no"/>
This tag only has an effect in the web reader.
Different behaviour when rendering in the background
The client apps render the pages in the background to create snapshots for the pages when an edition is first opened, and often, e.g. when running code after the snapshot, this code only makes sense when the user is viewing the page.
For example, in-page analytics should only run when the user has performed the action themselves and also if replacing markup with iframes, these are only useful for the end user.
Luckily the javascript can recognise whether it is running in the background or the foreground like this:
if (typeof(ppCustomData) === "function") {
var ppData = ppCustomData();
if (ppData.ppIsBackground) {
return; // in background so skip following code
}
}
Comments
0 comments
Please sign in to leave a comment.