<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SmartScripts articles</title>
	<atom:link href="http://www.smartscripts.nl/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.smartscripts.nl/blog</link>
	<description>Adds to your knowledge about PHP, javascript and more</description>
	<lastBuildDate>Mon, 07 May 2012 21:29:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>A Smart Form Script</title>
		<link>http://www.smartscripts.nl/blog/php/smart-form-script/</link>
		<comments>http://www.smartscripts.nl/blog/php/smart-form-script/#comments</comments>
		<pubDate>Sun, 06 May 2012 21:28:19 +0000</pubDate>
		<dc:creator>SmartScripter</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.smartscripts.nl/blog/?p=478</guid>
		<description><![CDATA[From this page you can download a smart form script, that almost needs no configuring, but still handles posted forms very securely. This form is an ideal solution if you don&#8217;t have an extended programming knowledge and yet want to &#8230; <a href="http://www.smartscripts.nl/blog/php/smart-form-script/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>From this page you can download a smart form script, that almost needs no configuring, but still handles posted forms very securely. This form is an ideal solution if you don&#8217;t have an extended programming knowledge and yet want to have a highly configurable form. The form configuration is done by special attributes in the html of the form. The visitor of you site will not get to see these attributes.</p>
<p>The comments in the script will help you to understand and configure the script. All files visible below are available in an archive: <tagarchieflink>smart-php-form</tagarchieflink>.</p>
<p>For your convenience the three files in this archive are listed below, with added syntax coloring. A working example of this form can be seen <a href="http://www.smartscripts.nl/smart-php-form">here</a>. This example will not send any mails however, to prevent the sending of spam mails.</p>
<div class="accordeon">
<div class="accontainer"<br />
<h2 class="achandle">An example page</p>
<div class="acitem">
<p>This is an example of an contact page that contains the dynamically generated form.</p>
<p><taghtmldemobestand>smart-php-form/contact.php</taghtmldemobestand></p>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">Smart Form class</h2>
<div class="acitem">
<p>This is the class that does all the hard work of generating forms, processing posted data and securing them.</p>
<p><taghtmldemobestand>smart-php-form/formchecker.php</taghtmldemobestand></p>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">Stylesheet</h2>
<div class="acitem">
<p>This is the stylesheet that gives the form it&#8217;s lay-out. You can adapt it to your heart&#8217;s content.</p>
<p><taghtmldemobestand>smart-php-form/form.css</taghtmldemobestand></p>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.smartscripts.nl/blog/php/smart-form-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Basic Script to Switch Between Mobile and Desktop Layout</title>
		<link>http://www.smartscripts.nl/blog/browsers/a-basic-script-to-switch-between-mobile-and-desktop-layout/</link>
		<comments>http://www.smartscripts.nl/blog/browsers/a-basic-script-to-switch-between-mobile-and-desktop-layout/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 22:00:06 +0000</pubDate>
		<dc:creator>SmartScripter</dc:creator>
				<category><![CDATA[Browser Detection]]></category>
		<category><![CDATA[Browsers]]></category>
		<category><![CDATA[Mobile Devices]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.smartscripts.nl/blog/?p=323</guid>
		<description><![CDATA[On this page a basic PHP script will be presented to switch between a mobile and desktop version of a webpage. The main target for creating this script was to present a working model that can be used for educational purposes. &#8230; <a href="http://www.smartscripts.nl/blog/browsers/a-basic-script-to-switch-between-mobile-and-desktop-layout/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>On this page a basic PHP script will be presented to switch between a mobile and desktop version of a webpage. The main target for creating this script was to present a working model that can be used for educational purposes. This way it may become clear how such an approach can be realized and students can experience the main functions that we like to emphasize as important, which are:</p>
<ul>
<li>it automatically detects what kind of browser a visitor uses;</li>
<li>it presents the appropriate version of the webpage for desktop and mobile;</li>
<li>the automated presented desktop and mobile versions of the webpage will use the same filename (One Web);</li>
<li>the script allows the visitor to overrule this automatically determined choice;</li>
<li>the visitor&#8217;s preference will be stored in a cookie so that at a next visit with the same browser he does not need to use the switch again;</li>
<li>since this last function cannot be done without redirection there is a canonical link to the main version of the webpage present (One Web).</li>
</ul>
<p>A working example of this script can be found <a href="http://www.smartscripts.nl/switch/page.extphp">here</a></p>
<div class="accordeon">
<div class="accontainer">
<h2 class="achandle">The code</h2>
<div class="acitem">
<p>Click on the filenames below to see the code of the corresponding file and the companion instructions.</p>
<div class="accordeon">
<div class="accontainer">
<h3 class="achandle">.htaccess</h3>
<div class="acitem">
<p>The .htaccess file needs the following code to set the cache-control for the stylesheets. Since cache-control for PHP needs to be set with PHP you will not find the cache-control settings for the webpages in the .htacces file below.</p>
<p>In case you don&#8217;t have access to put a .htacces file on your server, you will find special stylesheets below that contain the cache-control with PHP.</p>
<p><taghtmldemobestand>desktop-mobile-layout-switcher/htaccess</taghtmldemobestand>
</div>
</div>
<div class="accontainer">
<h3 class="achandle">page.php</h3>
<div class="acitem">
<p>This webpage is a template for all the pages in the site. There is no need to bother about the canonical link, the script will automatically take care of it, same as for any duplicate page. The cookie will be automatically placed by the script as well, for all versions of the web page, desktop and mobile and duplicates.</p>
<p>The PHP code is kept out of the HTML as much as possible without losing the aim to make clear what needs to be done and how this can be done. This means there is some PHP in the webpages that can&#8217;t be left out:</p>
<ul>
<li>See the comments inside the code of the webpage, don&#8217;t leave out to read them. The comments at line 9 are especially important and are about the PHP variable at line 10.</li>
<li>You can edit the value of the lifetime of the cookie in the PHP code at line 11. The companion comments explain how.</li>
<li>The switch for mobile/desktop looks like this:<br /> <br />
  <code>&lt;?php echoSwitch('Desktop Page', 'Mobile Page'); ?&gt;</code><br />
  The content for either desktop or mobile can be placed between the single quotation marks. Here the content on desktop  will be &#8216;Desktop Page&#8217; and on mobile it will be &#8216;Mobile Page&#8217;. You can place this PHP code where ever you like in the content of the webpage, just make sure you paste it from the first &#038;lt up to the close &gt;. Any content outside of this code will be shown on both desktop and mobile.</li>
<li>At line 12 you will find the <code>$maxage</code> variable so that you can set the cache-control for each page as you like</li>
<li>At line 34 another PHP code begins that switches desktop/mobile content. If you look closely you will see that the single quotation marks as you can see them in the sample just mentioned, are missing inside the PHP code at line 34 and are replaced with HEREDOC notation. Read the comments that start at line 54 to learn more about this.</li>
</ul>
<p><taghtmldemobestand>desktop-mobile-layout-switcher/page.php</taghtmldemobestand>
</div>
</div>
<div class="accontainer">
<h3 class="achandle">page2.php</h3>
<div class="acitem">
<p>This page is created by duplicating the page above. Just make sure that any new webpage that you create will be a duplicate of that page as well and you will be fine. Don&#8217;t forget to fill in the page title for desktop and mobile. There is no need to bother about the canonical link, the script will take care of it. Also the cookie will be placed by the script.</p>
<p><taghtmldemobestand>desktop-mobile-layout-switcher/page2.php</taghtmldemobestand>
</div>
</div>
<div class="accontainer">
<h3 class="achandle">screen_styles.css</h3>
<div class="acitem">
<p>Write your CSS for the desktop version of your webpages in this stylesheet. If you want to change the name of the file, you can change the link in the webpage in the PHP code at line 28. If your server does not allow you to put an .htaccess file, you need to use the stylesheet below, screen_styles.php, instead. Read more about this at <a href="#downloadfiles">&#8216;Download the files&#8217;</a>.</p>
<p><taghtmldemobestand>desktop-mobile-layout-switcher/screen_styles.css</taghtmldemobestand>
</div>
</div>
<div class="accontainer">
<h3 class="achandle">screen_styles.php</h3>
<div class="acitem">
<p>This stylesheet is meant for those who cannot put an .htaccess file on their server. Write your CSS for the desktop version of your webpages in this stylesheet below the PHP code. Leave this PHP code in top of the stylesheet untouched, it contains the Cache-Control header instead of writing it in .htaccess.  If you want to change the name of the file, you can change the link in the webpage in the PHP code at line 28. See below at <a href="#downloadfiles">&#8216;Download the files&#8217;</a> for additional instructions.</p>
<p><taghtmldemobestand>desktop-mobile-layout-switcher/screen_styles.php</taghtmldemobestand>
</div>
</div>
<div class="accontainer">
<h3 class="achandle">mobile_styles.css</h3>
<div class="acitem">
<p>Write your CSS for the mobile version of your webpages in this stylesheet. If you want to change the name of the file, you can change the link in the webpage in the PHP code at line 28. If your server does not allow you to put an .htaccess file, you need to use the stylesheet below, mobile_styles.php, instead. Read more about this at <a href="#downloadfiles">&#8216;Download the files&#8217;</a>.</p>
<p><taghtmldemobestand>desktop-mobile-layout-switcher/mobile_styles.css</taghtmldemobestand>
</div>
</div>
<div class="accontainer">
<h3 class="achandle">mobile_styles.php</h3>
<div class="acitem">
<p>This stylesheet is meant for those who cannot put an .htaccess file on their server. Write your CSS for the mobile version of your webpages in this stylesheet below the PHP code. Leave this PHP code in top of the stylesheet untouched, it contains the Cache-Control header instead of writing it in .htaccess. If you want to change the name of the file, you can change the link in the webpage in the PHP code at line 28. See below at <a href="#downloadfiles">&#8216;Download the files&#8217;</a> for additional instructions.</p>
<p><taghtmldemobestand>desktop-mobile-layout-switcher/mobile_styles.php</taghtmldemobestand>
</div>
</div>
<div class="accontainer">
<h3 class="achandle">inc/switcher.php</h3>
<div class="acitem">
<p>This script is developed in teamwork with and for the <a href="http://www.w3devcampus.com/mobile-web-and-application-best-practices-training/">Mobile Web and Apps Best Practices Training</a> of W3C Online Training.<br />
<taghtmldemobestand>desktop-mobile-layout-switcher/inc/switcher.php</taghtmldemobestand></p>
</div>
</div>
<div class="accontainer">
<h3 class="achandle">inc/mobile_detection_class.php</h3>
<div class="acitem">
<p>The lightweight class for detection of mobile browsers device detection script below can also be found at <a href="http://www.opensource.org/licenses/mit-license.php">http://www.opensource.org</a></p>
<p><taghtmldemobestand>desktop-mobile-layout-switcher/inc/mobile_detection_class.php</taghtmldemobestand>
</div>
</div>
</div>
</div>
</div>
<div class="accontainer">
<h2 class="achandle" id="downloadfiles">Download the files</h2>
<div class="acitem">
<p>All files mentioned above are available in an archive: <tagarchieflink>desktop-mobile-layout-switcher</tagarchieflink>.</p>
<h3>About the PHP</h3>
<p>According the PHP there are two things worth mentioning:</p>
<ul>
<li>For the use of the script your server needs to support <strong>PHP 5</strong>.</li>
<li>To keep the script out of the HTML as much as possible for this basic method, you will find the main part of the script in the folder named &#8216;inc&#8217;, where it is split up in two parts: one is the device detection and the other one is responsible for the switch between presentation of the mobile or desktop version of the webpage.</li>
</ul>
<h3>Version with .htaccess</h3>
<p>For those among you that have the rights to put a .htaccess on the server, you need to do the following:</p>
<ul>
<li>Write your CSS in the files named desktop_styles.css and mobile_styles.css. </li>
<li>You can delete the files named desktop_styles.<strong>php</strong> and mobile_styles.<strong>php</strong></li>
</ul>
<h3>Version without .htaccess</h3>
<p>For those among you that are not allowed to work with .htaccess on the server, you need to do the following:</p>
<ul>
<li>Change the link in the web page(s) to the stylesheets from .css to .php</li>
<li>Write your CSS in the files named desktop_styles.php and mobile_styles.php. Be careful to leave the PHP code in the beginning of the stylesheets untouched.</li>
<li>You can delete the files named desktop_styles.<strong>css</strong> and mobile_styles.<strong>css</strong></li>
<li>You can delete the .htaccess file</li>
</ul>
<p>To complete the download there is a readme file included.</p>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.smartscripts.nl/blog/browsers/a-basic-script-to-switch-between-mobile-and-desktop-layout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Force update of AppCache with PHP</title>
		<link>http://www.smartscripts.nl/blog/browsers/force-update-of-appcache-with-php/</link>
		<comments>http://www.smartscripts.nl/blog/browsers/force-update-of-appcache-with-php/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 15:00:16 +0000</pubDate>
		<dc:creator>SmartScripter</dc:creator>
				<category><![CDATA[AppCache]]></category>
		<category><![CDATA[Browsers]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.smartscripts.nl/blog/?p=201</guid>
		<description><![CDATA[AppCache can be hard to deal with. Browsers seem unpredictable in updating the AppCache. This example of a PHP-script (for PHP 5) makes sure the AppCache gets updated when pages have been changed. Important This script relies heavily on http-headers &#8230; <a href="http://www.smartscripts.nl/blog/browsers/force-update-of-appcache-with-php/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>AppCache can be hard to deal with. Browsers seem unpredictable in updating the AppCache. This example of a PHP-script (for PHP 5) makes sure the AppCache gets updated when pages have been changed.</p>
<div class="accordeon">
<div class="accontainer">
<h2 class="achandle">Important</h2>
<div class="acitem">
<p>This script relies heavily on http-headers sent <em>dynamically</em> by PHP. Headers that are defined in .htaccess can <em>never</em> be overruled by PHP, so don&#8217;t put these headers (especially Last-Modified and Expires) in .htaccess: the script won&#8217;t work then.</p>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">The Process: two modi</h2>
<div class="acitem">
<p>The script will be executed on the server in two modi: from the manifest and from a regular webpage on your site.</p>
<p>To clarify this let&#8217;s name the first mode &#8220;manifest-mode&#8221; and the second mode &#8220;page-mode&#8221;. Both modi use different parts of the PHP-script in <a href="#manifestloader">manifest-loader.php</a>.</p>
<ul>
<li>In <strong>manifest-mode</strong> the script will be activated directly by <a href="#htaccess">.htaccess</a>. In this mode the script will echo the contents of manifest.appcache to the browser, but not before it has searched for pages that are more recent than the manifest, in all the folders that are listed in a special file named <a href="#folders">folders.txt</a>. Since almost every page of your site may link to the manifest, every time one of these pages is visited, the script will start its search for modificated pages.</li>
<li>In <strong>page-mode</strong> if the script is included in the page, it will only check if the current webpage is more recent than the <a href="#manifest">manifest</a>. In page-mode the script sends cache-control-headers (Cache-Control: max-age, Last-Modified, Expires) for the current webpage to the browser.</li>
</ul>
<h3 id="manifestmode">More about the manifest-mode</h3>
<ol>
<li>The script will investigate if the script itself or one of your regular webpages is more recent than the manifest.</li>
<li>If so, the manifest on the server will be updated with an new version-number and modification-time. Then it will be sent to the browser, along with some headers that tell the browser that the manifest has expired and will have to be refreshed from the browser during the next request of a webpage.</li>
<li>The update of the online manifest forces the visitor&#8217;s browser to update its local AppCache.</li>
<li>In case there are no webpages more recent than the manifest, the script checks if maybe your stylesheet is more recent than the manifest. In that case the manifest also will be updated.</li>
<li>There may be a delay before you see updates of the manifest. This delay is determined by:
<ol>
<li>The number of files in the appcache that have to be checked for updates (and the time it takes to download modificated files).</li>
<li>On the max-age send sent by the script for each file while in page-mode.</li>
</ol>
</li>
</ol>
<h3 id="pagemode">More about the page mode</h3>
<ol>
<li>If the requested webpage on the server is more recent than the manifest, the script will update the manifest on the server with a new version-number and modification-time.</li>
<li>The script also checks if the requested page is in a folder that is not yet listed in <a href="#folders">folders.txt</a>. If so, this file will be updated with the new folder. This list of folders enables the script to check this new folder for modificated pages when it&#8217;s in manifest-mode.</li>
</ol>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">The Files</h2>
<div class="acitem">
<p>You need four files, each of which you can find below:</p>
<ol>
<li>The <a href="#manifest">manifest</a> that is called manifest.appcache.</li>
<li>The <a href="#htaccess">.htaccess</a> file</li>
<li>The script that is called <a href="#manifestloader">manifest-loader.php</a></li>
<li>A register for the folders on your site <a href="#folders">folders.txt</a></li>
</ol>
<p>Also you need to include some extra PHP-code in your regular webpages, as you can see in the <a href="#pages">samples</a> below.</p>
<p>All files mentioned above are available in an archive: <tagarchieflink>manage-appcache-with-php</tagarchieflink>.</p>
<p><strong>Don&#8217;t forget to make manifest.appcache and folders.txt writable!</strong> Without this permission the script will not be able to write/change/add anything in these files.</p>
</div>
</div>
<div class="accontainer">
<h2 id="manifest" class="achandle">The Manifest</h2>
<div class="acitem">
<p>This is an example of the manifest thats is needed to enable AppCache. Modify according to your requirements, but don&#8217;t change the first two occurrences of lines that start with &#8220;#&#8221;.</p>
<p><taghtmldemobestand>manage-appcache-with-php/appcache/manifest.appcache</taghtmldemobestand></p>
</div>
</div>
<div class="accontainer">
<h2 id="htaccess" class="achandle">.htaccess</h2>
<div class="acitem">
<p>Only the bare minimum of rules needed for this setup are demonstrated here. This file must reside in the root directory of your site.</p>
<p><taghtmldemobestand>manage-appcache-with-php/htaccess</taghtmldemobestand></p>
</div>
</div>
<div class="accontainer">
<h2 id="folders" class="achandle">folders.txt</h2>
<div class="acitem">
<p>In this file manifest-loader.php maintains a list of folders on your site. This list enables manifest-loader.php while in manifest-mode to crawl the folders of your site in search of files that are more recent than the manifest.</p>
<p><taghtmldemobestand>manage-appcache-with-php/appcache/folders.txt</taghtmldemobestand></p>
</div>
</div>
<div class="accontainer">
<h2 id="manifestloader" class="achandle">manifest-loader.php</h2>
<div class="acitem">
<p>This is the script that does all the hard work. It has to be included in the head of your pages (see the <a href="#pages">sample</a> below).</p>
<p><taghtmldemobestand>manage-appcache-with-php/appcache/manifest-loader.php</taghtmldemobestand></p>
</div>
</div>
<div class="accontainer">
<h2 id="pages" class="achandle">Sample files</h2>
<div class="acitem">
<p>Below you find examples of three regular pages (two in the root folder of your site and one in a subfolder &#8220;subdir&#8221;) and of the stylesheet for these pages.</p>
<p>Notice how the <a href="#manifestloader">manifest loader</a> is being loaded in the start section of your pages. You only have to add some extra PHP-code above the doctype and in the HTML element of your pages. Of course your webpages must have the extension .php for this to work.</p>
<h3>In the root folder: page.php (in the manifest)</h3>
<p><taghtmldemobestand>manage-appcache-with-php/page.php</taghtmldemobestand></p>
<h3>In the root folder: page2.php (not in the manifest)</h3>
<p><taghtmldemobestand>manage-appcache-with-php/page2.php</taghtmldemobestand></p>
<h3>In a subfolder: page3.php (not in the manifest)</h3>
<p><taghtmldemobestand>manage-appcache-with-php/subdir/page3.php</taghtmldemobestand></p>
<h3>The stylesheet: css/css.css (in the manifest)</h3>
<p>The contents of this file are not very relevant. I&#8217;ve only added it here because this sheets also will be checked for modifications by manifest-loader.php.</p>
<p><taghtmldemobestand>manage-appcache-with-php/css/css.css</taghtmldemobestand></p>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.smartscripts.nl/blog/browsers/force-update-of-appcache-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Know your AppCache</title>
		<link>http://www.smartscripts.nl/blog/browsers/know-your-appcache/</link>
		<comments>http://www.smartscripts.nl/blog/browsers/know-your-appcache/#comments</comments>
		<pubDate>Sun, 28 Aug 2011 21:41:22 +0000</pubDate>
		<dc:creator>SmartScripter</dc:creator>
				<category><![CDATA[AppCache]]></category>
		<category><![CDATA[Browsers]]></category>
		<category><![CDATA[HTML5]]></category>

		<guid isPermaLink="false">http://www.smartscripts.nl/blog/?p=203</guid>
		<description><![CDATA[AppCache can significantly speed up the loading of the pages of your site and lets visitors surf your site even when they are offline and haven’t downloaded all pages yet. In this post I&#8217;ll present a solution to get AppCache &#8230; <a href="http://www.smartscripts.nl/blog/browsers/know-your-appcache/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>AppCache can significantly speed up the loading of the pages of your site and lets visitors surf your site even when they are offline and haven’t downloaded all pages yet.</p>
<p>In this post I&#8217;ll present a solution to get AppCache functioning correctly (which can be quite problematic). I&#8217;ll conclude with some interesting facts about AppCache and how different browsers cope with it.</p>
<div class="accordeon">
<div class="accontainer">
<h2 class="achandle">How does AppCache work?</h2>
<div class="acitem">
<p>AppCache is a new feature of HTML5. In the html-tag of web pages must be a link present to the “manifest” of the AppCache (preferably with the extension .appcache):</p>
<pre id="line1">&lt;html manifest="/manifest.appcache"&gt;</pre>
<p>Now this manifest is used by the browser as central point of reference: in this manifest the webmaster of a site can sum up all the pages, images and documents that have to be downloaded and cached in the background. Instead of checking online for each and every page if a new version thereof exists, the browser consults the manifest to check if that has been changed. If it has not and the requested page/file is present in the AppCache, the local copy will be loaded instead of the online one. Since the manifest is only one small file, checking this for updates instead of the numerous online pages and files is much, much faster.</p>
<p>For more detailed information and instructions how to write a manifest see the links at the end of this page.</p>
<p>The main subject of this post are the problems you can encounter when trying to use AppCache and how to solve them. As easy as the use of AppCache may seem in theory, in practice it soon will surprise you with its seemingly unreliable behavior. It can prove quite hard to force your browser to update it’s AppCache with modified online content.</p>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">The problem: AppCache conflicts with normal cache-control headers</h2>
<div class="acitem">
<p>The AppCache of any browser will only be renewed when the contents of the manifest have been changed. A simple way to make this change of content is to add a comment in the manifest in which you simply write down a version number. Whenever this version number changes, meaning the content of the manifest has changed, the browser will update the AppCache.However, any cache-control with Cache-Control and Expires headers set in a .htaccess-file in the root of a site, can and most probably will conflict with the cache-management by the AppCache. I noticed that whenever I used this standard method of cache-control, AppCache wouldn’t function correctly anymore: it would never update its cache afterwards with newer versions of the same pages. This meant that the visitor would only and forever get to see the out-of-date version of any page once it has been stored in the AppCache. That is, until the visitor deletes the AppCache of his browser.</p>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">Problems with AppCache and HTML forms</h2>
<div class="acitem">
<p>AppCache can also be problematic on pages that contain a form. When a visitor posts the form, you have make adaptations to ensure that the post will indeed get through. I&#8217;ll write about this subject in another post.</p>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">The solution to the problem</h2>
<div class="acitem">
<p>I have found a solution to this problem. The central point of it is that the Cache-Control headers are never to be set in .htaccess, but always to be sent dynamically by a scripting language. An example how to accomplish this with PHP can be found <a href="/blog/browsers/force-update-of-appcache-with-php/" title="Force update of AppCache with PHP">elsewhere</a> in this blog. I have tested this solution thoroughly after including it in <a href="/site-optmizer">Site Optimizer</a>, a system I wrote to optimize sites.</p>
<p>In the example script I&#8217;ve set the refresh time for the AppCache to 2 minutes. I found that if changed pages were present, the AppCache would indeed be updated after this interval (or a little longer). So the visitor will see changed content after a relatively short delay. When visiting the same page some hours later, the visitor will surely see the changed content of the AppCache, since the max-age of two minutes has by then expired long since. And as long as, in between visits, the manifest hasn’t changed, the pages will be shown from the browser&#8217;s AppCache.</p>
<p>The result is very interesting:</p>
<ol>
<li>Despite the low max-age you still have avoided unnecessary downloading of pages that were already downloaded before and that haven&#8217;t been changed in the meantime.</li>
<li>What&#8217;s more: your visitor can see the contents of pages listed in the manifest even when he is offline and hadn&#8217;t visited this pages while online.</li>
<li>Only the files that actually have changed will be re-downloaded to the AppCache.</li>
</ol>
<p>You may get penalty points in <a href="http://code.google.com/intl/nl-NL/speed/page-speed/">PageSpeed</a> for the missing expires-headers. If so then PageSpeed obviously is not (yet) smart enough to detect that they are compensated with the advantages of AppCache. The most recent test in <a href="http://developer.yahoo.com/yslow/">YSlow</a> though does indeed compensate for this.</p>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">AppCache in various browsers</h2>
<div class="acitem">Note: I&#8217;ve only tested AppCache on a Windows computer with the browsers available to me on that platform
<dl>
<dt>Chrome</dt>
<dd>
<ul>
<li>Chrome has good support for AppCache.</li>
<li>Very handy feature: when the user deletes the conventional cache of his browser, the AppCache will be cleared also.</li>
<li>If you want, you can get a list of all the AppCaches managed by Chrome by visiting <em>chrome://appcache-internals/</em> in this browser. In this list you can delete AppCaches on a per site basis.</li>
<li>On the visitor&#8217;s harddisk the AppCache is being stored in the directory<em>C:\Users\[User Name]\AppData\Local\Google\Chrome\User Data\Default\Application Cache</em>, but in a non readable format.</li>
<li>Luckily you can download the extension <a href="https://chrome.google.com/webstore/detail/fjmhjjohhiehaoljianalpmfcceojaff?hl=nl">Service Pages for Google Chrome</a>. One of the utilities in this suite is &#8220;View HTTP Cache&#8221;. In this utility you can also see which pages Chrome has stored in it&#8217;s AppCache. If you click on a page, you see the contents thereof <em>and</em> the headers that were issued by the server when the page was downloaded. This led me to believe that the AppCache not only delivers the contents of pages to the browser, but also reconstructs and sends the original headers.</li>
</ul>
</dd>
<dt>Firefox</dt>
<dd>
<ul>
<li>Firefox has the laudable but also annoying tendency to pop up a dialog that alerts the visitor that &#8220;this site is trying to store content for offline use&#8221;. In my mind this leaves the visitor with the impression that a site is engaged in shady activities.</li>
<li><strong>Edit:</strong> in my current version of Firefox 6.0.2 I can disable this dialog by unticking a checkbox: Options > Options > &#8220;Tell me when a website asks to store data for offline use&#8221;. If I remember correctly this checkbox wasn&#8217;t available in previous versions of Firefox.</li>
<li>Firefox&#8217;s AppCache will not be deleted when you empty this browser&#8217;s conventional cache manually. Instead you have to follow another pathway in the menu: Options &gt; Options &gt; Advanced &gt; Network. In the lower part of this dialog you&#8217;ll notice the AppCaches that Firefox manages; these can be erased manually in this dialog. Rather a pity that Firefox didn&#8217;t follow the same approach as Chrome i.e.: deleting the AppCaches simultaneously with the conventional cache.</li>
<li><strong>Edit:</strong> in more recent versions of FireFox (6.0.2 and newer) the AppCache will also be deleted when the visitor empties the local cache of Firefox. Huzza!</li>
<li>Firefox stores it&#8217;s meta information about the AppCache in a SQLite database: <em>C:\Users\[Username]\AppData\Local\Mozilla\Firefox\Profiles\[ProfileOfCurrentUser]\OfflineCache\index.sqlite</em>. So this information can be accessed in a SQLite-viewer, for example in the Firefox-extension <a href="https://addons.mozilla.org/nl/firefox/addon/sqlite-manager/">SQLite Manager</a>. See here an example of the information FireFox stores:<br /><a href="/blog/wp-content/uploads/2011/07/firefox-appcache-metadata.png"><img title="firefox-appcache-metadata" src="/blog/wp-content/uploads/2011/07/firefox-appcache-metadata-150x150.png" alt="Example of metadata Firefox stores about the AppCache of a site" width="150" height="150" /></a></li>
<li>When the browser is in the process of downloading the resources that are being listed in the manifest and the users goes off-line during this process, the browser crashes.</li>
</ul>
</dd>
<dt>Internet Explorer, all versions</dt>
<dd>
<ul>
<li>All versions of Internet Explorer up to version 9 don&#8217;t seem to support AppCache: none of the AppCache pages were shown to me when I went off-line. In Internet Explorer 9 only the pages I explicitly downloaded by actually visiting them where available to me when offline.</li>
</ul>
</dd>
<dt>Opera</dt>
<dd>
<ul>
<li>Although the latest version of Opera claims that it supports AppCache, in fact I noticed that it did not work. None of the pages in my manifest were shown to me when I went off-line and tried to surf the site.</li>
<li>Rather strange, because I did notice that Opera stores AppCache information. You can see what Opera has stored in it&#8217;s AppCache when you visit View &gt; Developer Tools &gt; Temporal Storage (maybe the exact wording differs, because it&#8217;s my translation of the menu-items in Dutch).</li>
<li>In C:\Users\[UserName]\AppData\Local\Opera\Opera\application_cache resides a file cache_groups.xml. In this file you can see which AppCaches the browser has stored.</li>
<li>The contents of the stored pages can be found in dcache4.url in the same folder as cache_groups.xml.</li>
</ul>
</dd>
<dt>Safari for Windows</dt>
<dd>In first instance AppCache didn&#8217;t seem to work in this browser, because the pages in the manifest weren&#8217;t show to me when I went off-line. However, after adding the header &#8220;Pragma: cache&#8221; Safari handled the AppCache exactly like it should.</dd>
</dl>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">Using AppCache for mobile browsers</h2>
<div class="acitem">
<p>Since HTML5 is needed to leverage the advantages of AppCache, you have to determine if the browser supports HTML5 at all. For a mobile browser this can be done by checking in the database of <a href="http://dbapi.scientiamobile.com/">TeraWurfl</a> if it has support for the HTML5 canvas element. To have your website work properly in both desktop and mobile browsers with AppCache, you will need to automate this and more:</p>
<ol>
<li>Have the correct http-headers send for using AppCache as mentioned above: the Cache-Control and Last-Modified headers</li>
<li>Adjustment of the version number inside the manifest</li>
<li>Detection of the desktop or mobile browser</li>
<li>Check if this browser support HTML5</li>
<li>Converting the pages to HTML5 (or back to XHTML, depending on your approach)</li>
</ol>
<p>You can test for yourself the advantages of AppCache in mobile browsers by visiting <a href="http://www.smartscripts.nl/">www.smartscripts.nl</a> in your mobile browser. The system I mentioned above, <a href="/site-optimizer">Site Optimizer</a>, has automated the functions mentioned above, and more, like dynamically changing the content and the layout of pages for the mobile version of site.</p>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">403/forbidden-oddities</h2>
<div class="acitem">
<p>Sometimes when a visitor has been denied access to a page (403 error), the offline page defined in the manifest gets displayed instead of the &#8220;access denied&#8221; message. So I&#8217;m inclined to conclude that if a offline page has been defined in the manifest and a visitor tries to load a non existing page, this offline page wil be displayed. This is good to know, so you can adapt the text of the offline page, alerting the visitor to the fact that he either is offline or that he tried to load a private page.</p>
</div>
</div>
<div class="accontainer">
<h2 class="achandle">Links</h2>
<div class="acitem">
<ul>
<li><a href="http://www.webdirections.org/blog/get-offline/">Get off(line)</a> Good introduction into AppCache.</li>
<li><a href="http://html5doctor.com/go-offline-with-application-cache/">Go offline with application cache</a> Just as good an introduction as the previous one into the use of AppCache.</li>
<li><a href="http://appcachefacts.info/">Appcache Facts</a> Very interesting and valuable AppCache information. With this information I finally tamed the AppCache and got it working just the way I expected it to.</li>
<li><a href="https://developer.mozilla.org/en/offline_resources_in_firefox">Using Application Cache</a> Good information about AppCache in Firefox.</li>
</ul>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.smartscripts.nl/blog/browsers/know-your-appcache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

