<?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>cotsweb.com Blog</title>
	<atom:link href="http://www.cotsweb.com/blog/feed" rel="self" type="application/rss+xml" />
	<link>https://www.cotsweb.com/blog</link>
	<description>Web design, Website development and life in the Cotswolds</description>
	<lastBuildDate>Sun, 17 Aug 2014 14:12:58 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.7.20</generator>
	<item>
		<title>Adding placeholders to IE8 &#038; IE9 using jQuery</title>
		<link>https://www.cotsweb.com/blog/adding-placeholders-to-ie8-ie9-using-jquery-376.html</link>
					<comments>https://www.cotsweb.com/blog/adding-placeholders-to-ie8-ie9-using-jquery-376.html#comments</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Sun, 17 Aug 2014 14:12:58 +0000</pubDate>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[javaScript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[placeholder]]></category>
		<category><![CDATA[watermark]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=376</guid>

					<description><![CDATA[The placeholder attribute on the input statement is a useful way of providing prompts to the user without cluttering up the screen, it is well supported by all modern browsers but sadly not by versions of Internet Explorer before IE10.  There is a good jQuery plugin called watermark which solves the problem but you need [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The placeholder attribute on the input statement is a useful way of providing prompts to the user without cluttering up the screen, it is well supported by all modern browsers but sadly not by versions of Internet Explorer before IE10.  There is<a title="jQuery Watermark plugin on google code" href="https://code.google.com/p/jquery-watermark/"> a good jQuery plugin called watermark </a>which solves the problem but you need to apply it to the  required fields, they suggest something like.</p>
<p><code class="preserve-code-formatting">$( &#039;#inputId&#039; ).watermark( &#039;Required information&#039; );</code></p>
<p>That is fine but I don&#8217;t really want to separately to each field, particularly if I have already populated the placeholder for each field.  So being lazy I have written a little bit of jQuery which takes the existing placeholder for each field and adds it as a watermark.</p>
<p><pre><code class="preserve-code-formatting">
&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;js/jquery.watermark.min.js&quot;&gt;&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
&nbsp;&nbsp; $(document).ready(function () {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Set watermarks on input fields; IE8 &amp; IE9 don&#039;t support placeholders
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* This routine extracts the placeholder text from the HTML input statements and 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;passes it to the jQuery watermark plugin
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* so we don&#039;t have to separately maintain the watermark text
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(&#039;[placeholder]&#039;).each(function () {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var placeholderText = $(this).attr(&#039;placeholder&#039;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(this).watermark(placeholderText);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });
&nbsp;&nbsp; });
&lt;/script&gt;
</code></pre></p>
<p>Obviously this requires that you have included jQuery and the jQuery watermark plugin earlier in your code as I have in the example but now every input field that I add a placeholder to<br />
<code class="preserve-code-formatting">&lt;input type=&quot;text&quot; placeholder=&quot;Put some text in here&quot; name=&quot;textField&quot; /&gt;</code><br />
will display that placeholder text whether the user is running the latest version of Chrome or an antique version of Internet Explorer.</p>
<p>I hope you find this useful.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/adding-placeholders-to-ie8-ie9-using-jquery-376.html/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Android Tablet won&#8217;t connect to Google</title>
		<link>https://www.cotsweb.com/blog/android-tablet-wont-connect-to-google-367.html</link>
					<comments>https://www.cotsweb.com/blog/android-tablet-wont-connect-to-google-367.html#respond</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Fri, 10 Jan 2014 20:13:59 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Hudl]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=367</guid>

					<description><![CDATA[Unable to connect to Google Play My son got a Hudl tablet for Christmas and has been very pleased with it but in the last couple of days he hasn&#8217;t been able to connect to Google Play to update or download Apps. I had a look and was a bit confounded, he was right; it [&#8230;]]]></description>
										<content:encoded><![CDATA[<h2>Unable to connect to Google Play</h2>
<p>My son got a Hudl tablet for Christmas and has been very pleased with it but in the last couple of days he hasn&#8217;t been able to connect to Google Play to update or download Apps.</p>
<p>I had a look and was a bit confounded, he was right; it wouldn&#8217;t connect to the Play Store or to any Google service but it was connected to the internet via Wifi and I was able to use the web browser (Google Chrome) to surf the internet.   Fortunately with a short search I found <a title="Android device can't access Google Play Market " href="http://forums.androidcentral.com/t-inspire-4g/246409-cant-access-google-play-market.html#post2747553">this article on Android Central</a></p>
<p>The answer is simple (at least in this case); Check the date and time on the device!  The security settings on the Google services don&#8217;t like incorrect dates.  I&#8217;m not sure why my son&#8217;s Hudl had the wrong date and time on it, it may be a hangover from a recent trip, but setting it to pick up the network time corrected the date and time instantly.   I was immediately able to access the Play store, I didn&#8217;t even have to reboot.</p>
<h2>The Hudl Tablet</h2>
<p>A very brief review of the Hudl.  We have been very pleased with them,  they are very good value for money and seem able to cope with anything our boys have wanted to do.  The only things I would comment on are;</p>
<ul>
<li>The camera is ok but it doesn&#8217;t have a flash which limits its usefulness a bit.</li>
<li>It doesn&#8217;t work properly with older WEP wifi accees points.  Annoyingly it doesn&#8217;t tell you this, it just sits there trying to connect and failing.  Connecting to WPA or WPA2 is fine, but we have a second access point which is quite old and only supports WEP; the Hudl won&#8217;t connect to this.<br />
We have had this problem with a Windows 8 laptop too so I think it is time for us to upgrade our (rather old) access point but I do hate being forced into an upgrade.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/android-tablet-wont-connect-to-google-367.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Function to Sort an Associative Array in PHP</title>
		<link>https://www.cotsweb.com/blog/function-to-sort-an-associative-array-in-php-346.html</link>
					<comments>https://www.cotsweb.com/blog/function-to-sort-an-associative-array-in-php-346.html#respond</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Wed, 17 Apr 2013 11:30:25 +0000</pubDate>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Arrays]]></category>
		<category><![CDATA[Sort]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=346</guid>

					<description><![CDATA[I needed to sort an associative array into the correct order for display, PHP has various functions for sorting arrays but I couldn&#8217;t find a simple generic one that did what I wanted. Specifically I needed to sort on several keys and wanted a reasonably tidy solution (so much easier to figure out what is [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I needed to sort an associative array into the correct order for display, PHP has various functions for sorting arrays but I couldn&#8217;t find a simple generic one that did what I wanted. Specifically I needed to sort on several keys and wanted a reasonably tidy solution (so much easier to figure out what is going on when you come back it months/years later).</p>
<h3>The Sort</h3>
<p>Because I was using CodeIgniter for this site I put the following function in helpers/MY_array_helper.php so I can use it from other parts of the site. But it would work just as well if defined locally.<br />
<pre><code class="preserve-code-formatting">
function assoc_array_sort($a, $b, $key, $sequence = &#039;ASC&#039;)
{
/*
* Simple function for sorting between 2 values
* Designed to be called within the function called by usort or uasort
*
* $key is the key for the associative array so if we want to compare values of $array[&#039;my_key&#039;]
* $key would be set to &#039;my_key&#039;
*
* Default sequence is ASC but can reverse sort by passing DESC instead
*/
if (strtoupper($sequence) == &#039;DESC&#039;) {
&nbsp;&nbsp;$lower = 1;
&nbsp;&nbsp;$higher = -1;
} else {
&nbsp;&nbsp;$lower = -1;
&nbsp;&nbsp;$higher = 1;
}

if ($a[$key] == $b[$key]) {
&nbsp;&nbsp;return 0;
&nbsp;&nbsp;} else if ($a[$key] &amp;lt; $b[$key]) {
&nbsp;&nbsp;&nbsp;&nbsp;return $lower;
&nbsp;&nbsp;&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $higher;
&nbsp;&nbsp;&nbsp;&nbsp;}
}
</code></pre></p>
<h3>Calling the Sort</h3>
<p>The array I needed to sort is called $memberships so the call is;<br />
<pre><code class="preserve-code-formatting">
uasort($memberships, &#039;membership_sort&#039;);
</code></pre><br />
membership_sort is an intermediate function sitting between uasort (or usort) and assoc_array_sort.  If like me you are using CodeIgniter you will need to load the array_helper before calling this function.<br />
<pre><code class="preserve-code-formatting">
$this-&gt;load-&gt;helper(&#039;array&#039;);&nbsp;&nbsp; // load array_helper so we can use the sort in MY_array_helper
</code></pre><br />
<pre><code class="preserve-code-formatting">
function membership_sort($x, $y)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Use assoc_array_sort to determine sequence
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp; but where values match call again for the next variable to be checked.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * This should give us an array in order
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * - committee_sequence
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * - committee_name
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * - role_sequence
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * - role-name
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ret_var = assoc_array_sort($x, $y, &#039;committee_sequence&#039;,&#039;ASC&#039;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($ret_var == 0) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ret_var = assoc_array_sort($x, $y, &#039;committee_name&#039;,&#039;ASC&#039;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($ret_var == 0) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ret_var = assoc_array_sort($x, $y, &#039;role_sequence&#039;,&#039;ASC&#039;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($ret_var == 0) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ret_var = assoc_array_sort($x, $y, &#039;committee_name&#039;,&#039;ASC&#039;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $ret_var;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
</code></pre><br />
You can see that the first time assoc_array_sort is called it is sorting on $memberships[&#8216;committee_sequence&#8217;], if the values don&#8217;t match it returns -1 or 1 depending on whether the first or second value is higher.  But it the values are equal it drops through to the next sort key $memberships[&#8216;committee_name&#8217;] and repeats the process.</p>
<p>I am sure there are cleverer ways to do this, I would welcome feedback telling me of better ways, but hopefully this will be useful to somebody.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/function-to-sort-an-associative-array-in-php-346.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Setting up a Black Hole Email address</title>
		<link>https://www.cotsweb.com/blog/setting-up-a-black-hole-email-address-327.html</link>
					<comments>https://www.cotsweb.com/blog/setting-up-a-black-hole-email-address-327.html#respond</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Fri, 09 Nov 2012 12:42:30 +0000</pubDate>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Email]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=327</guid>

					<description><![CDATA[I have a client who has several email addresses all of which have to be redirected when she goes on holiday. To save work I have set up permanent redirect for all the addresses to all@example.com this one email address can then be redirected to whoever is covering the absence. The problem is that if [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I have a client who has several email addresses all of which have to be redirected when she goes on holiday.  To save work I have set up permanent redirect for all the addresses to all@example.com this one email address can then be redirected to whoever is covering the absence.</p>
<p>The problem is that if all@example.com isn&#8217;t currently redirected to a real email address anyone who sends a message to the client will get bounce message.<br />
<pre><code class="preserve-code-formatting">A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:

&nbsp;&nbsp;all@example.com
&nbsp;&nbsp;&nbsp;&nbsp;(ultimately generated from info@example.com)
&nbsp;&nbsp;&nbsp;&nbsp;No Such User Here&quot;
</code></pre><br />
So I need to redirect to a real address but I don&#8217;t actually want to store the messages as the original recipient is already getting a copy.  What I need is a &#8220;black hole email address&#8221;.</p>
<blockquote><p>A black hole e-mail address is an e-mail address which is valid (messages sent to it will not generate errors), but to which all messages sent are automatically deleted, and never stored or seen by humans. These addresses are often used as return addresses for automated e-mails.<br />
(Wikipedia)
</p></blockquote>
<p>I have found a couple of examples of such things on the internet but they didn&#8217;t suit my hosting setup, a reseller account with <a href="http://www.hostgator.com/" title="Hostgator web hosting">Hostgator</a>.  </p>
<p>There are black hole email services where you send messages you don&#8217;t want but I wasn&#8217;t happy forwarding a client&#8217;s messages to another party.  Great for junk mail but I wouldn&#8217;t want to send real mail to an unknown recipient.</p>
<h3>The cron job solution</h3>
<p>With some help from Jason C at Hostgator this is my first solution.  If you don&#8217;t have CPanel it is a pretty good solution.</p>
<ol>
<li>Set up a new email account for (in my case) blackhole@example.com</li>
<li>Use an FTP program (in my case <a href="http://filezilla-project.org/" title="FileZilla - Free FTP solution">Filezilla</a>) to find the path to where the incoming emails are being stored.  I found them at;<code class="preserve-code-formatting">mail/example.com/blackhole/new/</code></li>
<li>Set up a cron job to execute the following command;<code class="preserve-code-formatting">rm mail/example.com/blackhole/new/*</code>I set it to run every 15 minutes (*/15) which is probably excessive but it depends on how quickly the messages build up.</li>
</ol>
<p>Pretty simple in the end, just required a bit of thought.</p>
<h3>The CPanel Solution</h3>
<p>The solution above had been running ok for a few weeks when my client got an automated email;<br />
<code class="preserve-code-formatting">The following users are near or have exceeded their individual mail quota:</code><br />
It seems that CPanel doesn&#8217;t realise that the emails have been deleted so it doesn&#8217;t update the quota, there are nightly quota update jobs which should correct the issue but they don&#8217;t seem to work.</p>
<p>But Michael H at Hostgator pointed me in the direction of an another solution (Hostgator support is pretty good but as with most organisations it does depend on who you talk to).</p>
<p>CPanel does offer an alternative to the cron job solution, the <a href="http://docs.cpanel.net/twiki/bin/view/AllDocumentation/CpanelDocs/UserFiltering" title="User level email filters in CPanel">User Level Filter</a>, this was something I hadn&#8217;t come across before.  So now I have set up user level filter to simply delete all messages coming into the blackhole mailbox.  I have yet to see if this fixes the quota issue, as both are run by CPanel you would hope that it would but you never know.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/setting-up-a-black-hole-email-address-327.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using IfDefine in .htaccess file to support different environments in Apache</title>
		<link>https://www.cotsweb.com/blog/using-ifdefine-in-htaccess-file-to-allow-different-environments-in-apache-295.html</link>
					<comments>https://www.cotsweb.com/blog/using-ifdefine-in-htaccess-file-to-allow-different-environments-in-apache-295.html#respond</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Sat, 15 Sep 2012 14:05:38 +0000</pubDate>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[environments]]></category>
		<category><![CDATA[testing]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=295</guid>

					<description><![CDATA[I have three environments for most of the websites I build or support. My development machine where I do all the coding and initial testing.  Windows XP running Apache as part of  a  XAMPP setup.  All my local domain names are called something like &#8220;local.example.com&#8221; My testing machine which is designed to be as similar [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I have three environments for most of the websites I build or support.</p>
<ol>
<li>My development machine where I do all the coding and initial testing.  Windows XP running Apache as part of  a  XAMPP setup.  All my local domain names are called something like &#8220;local.example.com&#8221;</li>
<li>My testing machine which is designed to be as similar as possible to the live setup, I can access the server from other machines on the LAN to enable testing in different browsers.  Ubuntu server running Apache.  All the domain names are called something like &#8220;staging.example.com&#8221;</li>
<li>The live webserver which is run by Hostgator in Texas.  Apache again and of course the domain names are something like &#8220;example.com&#8221;.</li>
</ol>
<p>I use Git to manage the code and to push changes from one environment to another.</p>
<p>Different environments often require slightly different configurations but I prefer to put conditional statements in my configuration files so that the same file works in all environments. That way I don&#8217;t have to modify the configuration before promoting it to production. It is just too easy to accidentally push a development module to production and overwrite the correct configuration on the live site.</p>
<h2>Configuration in PHP</h2>
<p>It isn&#8217;t difficult to do this with a PHP module, I just use a switch statement on the value of $_SERVER[&#8216;SERVER_NAME&#8217;] and use this to define the various configuration variables. The default value is always the production settings so if I get something wrong I don&#8217;t damage the live site.  Something like this;<br />
<pre><code class="preserve-code-formatting">switch ($_SERVER[&#039;SERVER_NAME&#039;]) {
case &#039;local.example.com:
$environment = &#039;local&#039;;
break;
case &#039;staging.example.com:
$environment = &#039;staging&#039;;
break;
default:
$environment = &#039;live&#039;;
break;
}
</code></pre></p>
<h2>Configuration in .htaccess</h2>
<p>Apache&#8217;s .htaccess files are a bit more complicated.  For instance Hostgator requires you to specify if you want to use PHP 5.3 rather than their default of 5.2, also I sometimes want to password protect a new site until it is ready for its proper debut.  To do this I added the following code to the .htaccess file;<br />
<pre><code class="preserve-code-formatting">
#
# Use PHP 5.3 rather than default of 5.2
#
AddType application/x-httpd-php53 .php
#
# Until we are ready to go live this site is password protected
#
AuthType Basic
AuthName &quot;New website&quot;
AuthUserFile &quot;/home/username/.htpasswds/public_html/passwd&quot;
require valid-user

</code></pre><br />
The block is only executed if Apache hasn&#8217;t been started with the DEV variable set. So in my case it will only be executed in the production evironment.</p>
<h2>Defining an Apache Environment Variable in Windows</h2>
<p>The tricky bit is getting the environment variable set up in my development and testing environments. Fortunately I found <a title="Using IfDefine Conditions in an Apache .htaccess file" href="http://stackoverflow.com/questions/11073752/apache-ifdefine-conditionals-in-htaccess">a useful post by Nerivon on StackOverFlow</a>, it saved me a lot of messing around. I had to tweak Nerivon&#8217;s technique slightly for XAMPP but it worked perfectly.</p>
<ol>
<li>First I stopped Apache</li>
<li>Then I went into SCM from the XAMPP control panel, this opens the Windows Services Management Console</li>
<li>I found the Apache2.2 service and checked out it&#8217;s properties. Specifically I wanted the &#8220;Path to executable&#8221; value.<code class="preserve-code-formatting">&quot;C:\xampp\apache\bin\httpd.exe&quot; -k runservice</code></li>
<li>Then I opened a command window with RUN / CMD so I got a DOS prompt.</li>
<li>In that window I entered this command; <code class="preserve-code-formatting">&quot;C:\xampp\apache\bin\httpd.exe&quot; -D &quot;DEV&quot; -k config</code>That is the &#8220;path to executable&#8221; from above but an extra parameter &#8220;-D DEV&#8221; which defines my new DEV variable and with the last parameter &#8220;runservice&#8221; replaced with &#8220;config&#8221;</li>
<li>Then I restarted Apache and tested the change, it worked!</li>
</ol>
<p>Oddly when I look at the properties in SCM they are exactly the same as they were, no sign of the extra parameter, and I can&#8217;t find it in the registry either. I don&#8217;t know how it works but it does seem to do the job.</p>
<h3>Caveat</h3>
<p>Well it worked ok for a few days then I made some changes to my Apache set-up and restarted it but normally, not as a service. It lost my environment variable! I was able to repeat the instructions above and restart the service again and all was well again but it looks like this isn&#8217;t a perfect solution.<br />
If anyone has a better solution I&#8217;d like to hear it, in the meantime this will do but I will keep this blog entry handy to remind me what to do when it goes wrong again.</p>
<h2>Defining an Apache Environment Variable in Linux</h2>
<p>Unsurprisingly setting my DEV variable up on the Linux server was a lot simpler. Again I found help on the web, <a title="Using IfDefine in Apache on linux" href="http://jennyandlih.com/using-apaches-ifdefine-dev-and-production-environments">Jenny and Lih had useful article about using IfDefine for different environments</a>.<br />
I edited /etc/apache2/envvars and added the following line to the end of the file;<br />
<code class="preserve-code-formatting">export APACHE_ARGUMENTS=&#039;-D DEV&#039;</code></p>
<p>Update Feb 2014: In later versions of Apache the export APACHE_ARGUMENTS line already exists but has an empty value and is commented out; in this case just modify the line to match the line above.</p>
<p>I stopped and restarted Apache and tested the site, it worked!  But be aware that a simple reload isn&#8217;t sufficient, you o need to stop and start it to load the new argument.</p>
<h2>All Done</h2>
<p>Both my local environments set the DEV variable so my block of code would be ignored there whereas the live environment doesn&#8217;t set it so executes the extra code. Perfect.<br />
I could have set up different variables for the different environments but I don&#8217;t need to at present so I have taken the simple option of just setting and checking one variable.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/using-ifdefine-in-htaccess-file-to-allow-different-environments-in-apache-295.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Keeping PHP and mySQL dates in sync</title>
		<link>https://www.cotsweb.com/blog/keeping-php-and-mysql-dates-in-sync-287.html</link>
					<comments>https://www.cotsweb.com/blog/keeping-php-and-mysql-dates-in-sync-287.html#respond</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Wed, 16 May 2012 15:55:21 +0000</pubDate>
				<category><![CDATA[mySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[dates]]></category>
		<category><![CDATA[timezones]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=287</guid>

					<description><![CDATA[My websites are hosted with Hostgator in Texas, USA but most of my customers are based in the UK. This creates a potential problem with dates and times because we usually want timestamps etc. to be recorded as if they were in the UK timezone rather than the timezone where the server is. Setting the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>My websites are hosted with <a href="http://www.hostgator.com/" title="Hostgator website hosting" target="_blank">Hostgator</a> in Texas, USA but most of my customers are based in the UK.  This creates a potential problem with dates and times because we usually want timestamps etc. to be recorded as if they were in the UK timezone rather than the timezone where the server is.</p>
<h3>Setting the timezone for Apache</h3>
<p>Fortunately it is easy to tell Apache to use a different timezone, just add the following line to your .htaccess file.</p>
<p><code class="preserve-code-formatting">SetEnv TZ Europe/London</code></p>
<p>This works nicely to set the timezone for the webserver and the programs that run within it, including PHP.  This means that the PHP date and time functions will return the date/time as UK time rather than the server time.</p>
<h3>Getting mySQL to use the right time</h3>
<p>The only problem is that Apache doesn&#8217;t control mySQL, in fact on a shared hosting arrangement it isn&#8217;t possible to set mySQL&#8217;s timezone.  I would be changing it for all the customers on my server which would suit me fine but may not make them happy.</p>
<p>This means that using a mySQL function like NOW() generates a Texas timestamp rather than a London timestamp which isn&#8217;t what I want.  There are a number of solutions to this problem, <a href="http://www.richardlord.net/blog/dates-in-php-and-mysql" title="Richard Lord's Blog post about dates in PHP and mySQL" target="_blank">Richard Lord has written a good, clear post about possible solutions on his blog</a>.</p>
<p>What I want is something that uses the timezone from Apache but stores the date in a mySQL format so I can use mySQL date comparisons when I retrieve the data later on.  Fortunately the answer is quite straightforward; Where I would use NOW() to generate a timestamp I use the PHP function:</p>
<p><code class="preserve-code-formatting">date(&#039;Y-m-d H:i:s&#039;)</code></p>
<p>This uses the current date from Apache (which is set to the London timezone) but converts it to the mySQL DATETIME format so that you can use mySQL&#8217;s date processing functions on the data.  Of course if you had calculated some other date in your PHP code you could use the same function but pass your calculated date to the function instead of letting it use the current date/time</p>
<p><code class="preserve-code-formatting">date(&#039;Y-m-d H:i:s&#039;,$my_date)</code></p>
<p>So the SQL query you construct in PHP might look a bit like this:</p>
<p><pre><code class="preserve-code-formatting">
$query = &#039;INSERT INTO filename (
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current_time_stamp,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my_time_stamp)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VALUES (&quot;&#039; . 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;date(&#039;Y-m-d H:i:s&#039;) . &#039;&quot;, &#039;&quot; .&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// replaces NOW()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;date(&#039;Y-m-d H:i:s&#039;,$my_date) . &#039;&quot;)&#039;;&nbsp;&nbsp;&nbsp;&nbsp;// replaces calculated date
</code></pre></p>
<p>That solved my particular date/time problem, I hope it helps you too.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/keeping-php-and-mysql-dates-in-sync-287.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Signing up for Technorati</title>
		<link>https://www.cotsweb.com/blog/signing-up-for-technorati-285.html</link>
					<comments>https://www.cotsweb.com/blog/signing-up-for-technorati-285.html#respond</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Wed, 02 May 2012 15:17:55 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=285</guid>

					<description><![CDATA[This is just a mini post with my Technorati verification code of 6PV8MSJKKJQU included. Sorry there is nothing worth reading here.]]></description>
										<content:encoded><![CDATA[<p>This is just a mini post with my Technorati verification code of 6PV8MSJKKJQU included.<br />
Sorry there is nothing worth reading here.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/signing-up-for-technorati-285.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CSS Dropdown Menus don&#8217;t work on iPhones &#038; iPads</title>
		<link>https://www.cotsweb.com/blog/css-dropdown-menus-dont-work-on-iphones-ipads-275.html</link>
					<comments>https://www.cotsweb.com/blog/css-dropdown-menus-dont-work-on-iphones-ipads-275.html#comments</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Thu, 26 Apr 2012 14:58:02 +0000</pubDate>
				<category><![CDATA[Browsers]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[rants]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Safari]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=275</guid>

					<description><![CDATA[I have used CSS dropdown menus on quite a few sites, based on the Suckerfish idea. These have worked fine for a long time and with the addition of the sfHover function they work in IE as well as all more modern browsers.  But recently a client called me to say that the dropdowns weren&#8217;t [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I have used CSS dropdown menus on quite a few sites, based on the Suckerfish idea. These have worked fine for a long time and with the addition of the <a title="Son of Suckerfish CSS Dropdown menus" href="http://www.htmldog.com/articles/suckerfish/dropdowns/">sfHover</a> function they work in IE as well as all more modern browsers.  But recently a client called me to say that the dropdowns weren&#8217;t working on her iPhone.</p>
<h2>Making dropdown menus work on the iPhone</h2>
<p>After a bit of trial and error and a lot of searching on the internet I discovered that the problem was that the iPhone (and I believe the iPad too) doesn&#8217;t honour the :hover  pseudoclass.  I was able to find a solution <a title="Tip for getting dropdown menus to work on the iPhone" href="http://justtwonerds.com/2010/02/24/free-css-dropdown-menu-with-iphone-quick-tip/">here</a> and modified my code accordingly.</p>
<p>All I had to do was add onmouseover=&#8221;&#8221;  to the li elements which contained ul elements for the dropdown menus. So;<br />
<pre><code class="preserve-code-formatting">
&lt;li onmouseover=&quot;&quot;&gt;Top Level item
&lt;ul&gt;
&lt;li&gt;Dropdown item 1&lt;/li&gt;
&lt;li&gt;Dropdown item 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;</code></pre></p>
<p>&nbsp;</p>
<p>This solved the problem and made the iPhone display the drop down menu when the top level element was touched.  A simple solution to a subtle problem.</p>
<h2>But why doesn&#8217;t the iPhone work like everything else?</h2>
<p>It seems that the reason Apple have done this is because you can&#8217;t actually hover on a touchscreen, which sort of makes sense until you think of the consequences.  And if you can&#8217;t hover why do they honour the mouseover event which is surely the same thing?</p>
<p>One of the great things about smartphones is that they have good screens and good browsers so you can use the internet  reasonably well from a mobile device.  Unlike earlier attempts at mobile browsing,  like WAP, any well designed website will work properly on a smartphone.  You can design websites to take advantage of the smartphone&#8217;s extra capabilities but the vast majority of existing websites are navigable without changes.  If only sites designed from scratch for mobile use could actually be navigated by a smartphone they wouldn&#8217;t have access to very much at all and would lose one of their main attractions.  Apple have broken this; There must be quite large sections of some sites which are invisible to iPhone users.</p>
<h2>And I mean EVERYTHING else!</h2>
<p>All our websites are tested very thoroughly in lots of  browsers.  It isn&#8217;t possible to test every possible combination but we test in; Internet Explorer versions 6 through 9, Chrome, Firefox, Opera and Apple&#8217;s Safari.  This issue doesn&#8217;t appear in any of them, though of course we are not using a touch screen device with any these.  Even on <a href="http://www.electricplum.com/products.html" title="iPhone simulator">Electric Plum&#8217;s iPhone simulator</a> the dropdown menus work fine. </p>
<p>We don&#8217;t have a Mac so we can&#8217;t use Apple&#8217;s IOS simulator, I would be very interested to know if this problem is replicated there.  Significantly the problem does not seem to occur on Android phones, only Apple have taken this route.  I think they have made the wrong choice.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/css-dropdown-menus-dont-work-on-iphones-ipads-275.html/feed</wfw:commentRss>
			<slash:comments>31</slash:comments>
		
		
			</item>
		<item>
		<title>Integrating class.upload.php into CKeditor</title>
		<link>https://www.cotsweb.com/blog/integrating-class-upload-php-into-ckeditor-266.html</link>
					<comments>https://www.cotsweb.com/blog/integrating-class-upload-php-into-ckeditor-266.html#comments</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Thu, 22 Mar 2012 16:30:26 +0000</pubDate>
				<category><![CDATA[Content Management]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[javaScript]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=266</guid>

					<description><![CDATA[I have been working on a Content Management System for Kate&#8217;s Home Nursing, a Stow based charity who provide top quality palliative care around the North Cotswolds.  As part of the CMS I am using CKeditor, which is a very good WYSIWYG editor, allowing the users to create their own content in something like a [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I have been working on a Content Management System for <a title="Kate's Home Nursing, palliative care charity based in Stow on the Wold" href="http://www.kateshomenursing.org" target="_blank">Kate&#8217;s Home Nursing</a>, a Stow based charity who provide top quality palliative care around the North Cotswolds.  As part of the CMS I am using <a title="CKeditor Open Source WYSIWYG editor for websites" href="http://ckeditor.com/" target="_blank">CKeditor</a>, which is a very good WYSIWYG editor, allowing the users to create their own content in something like a word processing environment.</p>
<p>But I need the facility to upload images to be integrated into the page being edited, <a title="CKfinder Ajax File Manager" href="http://ckfinder.com/" target="_blank">CKfinder</a> is a possibility, it integrates well with CKeditor, but it isn&#8217;t Open Source.  <a title="KCfinder Open Source image upload and file browsing" href="http://kcfinder.sunhater.com/" target="_blank">KCfinder</a> is another possibility;  it  is Open Source but I found it difficult to do exactly what I wanted with it.  What I really wanted was to use <a title="class.upload.php file upload script" href="http://www.verot.net/php_class_upload.htm" target="_blank">class.upload.php</a> which is Open Source and I know from experience does exactly what I want it to do.</p>
<p>The problem was that while I found some useful hints I couldn&#8217;t find clear instructions on the whole process of how to integrate class.upload.php with ckeditor.  So after some trial and error here is my solution. </p>
<p>Please note, class.upload.php is a file uploader, it doesn&#8217;t offer the file browser facilties that CKfinder and KCfinder provide.  I have concentrated on the integration process rather than on the various parameters, both CKeditor and class.upload.php are quite well documented and once you have the upload process working it is just a matter of fine tuning until you get the result you want.</p>
<h2>Getting CKeditor to call your custom upload script</h2>
<p>I am calling CKeditor with javaScript from within a webpage so my calling code looks like this;<br />
<pre><code class="preserve-code-formatting">&lt;!-- Set up CKeditor --&gt;
&lt;script src=&quot;ckeditor.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
&nbsp;&nbsp;&nbsp;&nbsp;function displayCkeditor(id)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(CKEDITOR.instances[id])
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CKEDITOR.remove(CKEDITOR.instances[id]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CKEDITOR.replace(id,&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filebrowserUploadUrl :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;uploader.php?type=files,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filebrowserImageUploadUrl : &quot;uploader.php?type=images&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filebrowserFlashUploadUrl : &quot;uploader.php?type=flash&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});

&nbsp;&nbsp;&nbsp;&nbsp;}

&lt;/script&gt;
&lt;!-- CKeditor end --&gt;
</code></pre><br />
This just tells CKeditor to use my custom &#8220;uploader.php&#8221; script when the user clicks on the image upload facility in the editor.  In this case it is expecting to find uploader.php in the current directory (the Ckeditor directory).</p>
<h2>Creating the Custom Upload Script</h2>
<p>And this is the script called by Ckeditor;<br />
<pre><code class="preserve-code-formatting">
&lt;?php
/**
 * uploader.php
 * Use class.upload.php to upload images etc.
 */
include(&#039;/includes/class.upload.php&#039;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// where you have put class.upload.php

$msg = &#039;&#039;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Will be returned empty if no problems
$callback = ($_GET[&#039;CKEditorFuncNum&#039;]);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Tells CKeditor which function you are executing

$handle = new upload($_FILES[&#039;upload&#039;]);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create a new upload object 
if ($handle-&gt;uploaded) {
&nbsp;&nbsp;&nbsp;&nbsp;$handle-&gt;image_resize&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = true;
&nbsp;&nbsp;&nbsp;&nbsp;//
&nbsp;&nbsp;&nbsp;&nbsp;// Create a small image (thumbnail)
&nbsp;&nbsp;&nbsp;&nbsp;//
&nbsp;&nbsp;&nbsp;&nbsp;$handle-&gt;image_x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 150;
&nbsp;&nbsp;&nbsp;&nbsp;$handle-&gt;image_ratio_y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= true;

&nbsp;&nbsp;&nbsp;&nbsp;$handle-&gt;process($_SERVER[&#039;DOCUMENT_ROOT&#039;] . &#039;/userfiles/&#039;);&nbsp;&nbsp;// directory for the uploaded image
&nbsp;&nbsp;&nbsp;&nbsp;$image_url = &#039;/userfiles/&#039; . $handle-&gt;file_dst_name;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// URL for the uploaded image
 
&nbsp;&nbsp;&nbsp;&nbsp;if ($handle-&gt;processed) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $handle-&gt;clean();
&nbsp;&nbsp;&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$msg =&nbsp;&nbsp;&#039;error : &#039; . $handle-&gt;error;
&nbsp;&nbsp;&nbsp;&nbsp;}
}

$output = &#039;&lt;script type=&quot;text/javascript&quot;&gt;window.parent.CKEDITOR.tools.callFunction(&#039;.$callback.&#039;, &quot;&#039;.$image_url .&#039;&quot;,&quot;&#039;.$msg.&#039;&quot;);&lt;/script&gt;&#039;;
echo $output;
?&gt;
</code></pre><br />
In this simple example I just upload an image and resize it to a 150px wide thumbnail for inclusion in the edited text.</p>
<p>The important part is the $output echoed back to CKeditor which tells it which function to link up with and the URL of the uploaded file (which will then be inserted into the text being edited).  If the upload is successful the $msg field should be empty, otherwise it should contain an error message and the URL should be empty.</p>
<p>The code above is a working outline, obviously a bit more needs to be built in to make it a safe and useful bit of code but I have left it quite simple so that it is clear and useful for others to build on.  I hope you find it useful.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/integrating-class-upload-php-into-ckeditor-266.html/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Using Google Analytics to track clickthrus updated</title>
		<link>https://www.cotsweb.com/blog/using-google-analytics-to-track-clickthrus-updated-259.html</link>
					<comments>https://www.cotsweb.com/blog/using-google-analytics-to-track-clickthrus-updated-259.html#comments</comments>
		
		<dc:creator><![CDATA[cotsweb]]></dc:creator>
		<pubDate>Mon, 19 Mar 2012 16:51:52 +0000</pubDate>
				<category><![CDATA[Analytics]]></category>
		<category><![CDATA[click tracking]]></category>
		<category><![CDATA[Search Engine Optimisation]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[clickthru]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Google Analytics]]></category>
		<category><![CDATA[seo]]></category>
		<guid isPermaLink="false">http://www.cotsweb.com/blog/?p=259</guid>

					<description><![CDATA[About 4 years ago I wrote a post on the subject of Using Google Analytics to track click throughs from your website which described how to use PageTracker to log clicks on links which wouldn&#8217;t normally be picked up by Google Analytics.  This worked fine and indeed still does, but it is no longer the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>About 4 years ago I wrote a post on the subject of <a title="Using Google Analytics to track click throughs from your website" href="http://www.cotsweb.com/blog/using-google-analytics-to-track-click-throughs-from-your-website-7.html">Using Google Analytics to track click throughs from your website</a> which described how to use PageTracker to log clicks on links which wouldn&#8217;t normally be picked up by Google Analytics.  This worked fine and indeed still does, but it is no longer the method I would suggest to solve this problem.</p>
<p>Now you can use Event Tracking to track all sorts of things like ClickThrus, Downloads,  PDF reads, Media Plays and pretty much anything else you can think of.    I won&#8217;t go into how to implement Event Tracking as Google have a pretty good explanation in their <a title="Setting up event tracking in Google Analytics" href="http://code.google.com/apis/analytics/docs/tracking/eventTrackerGuide.html" target="_blank">Google Analytics Event Tracking Guide</a>.  Event tracking works very well and lets you track an event in  several different ways by specifying category,  action, label and a value if you want to.</p>
<h2>Missing pages in Webmaster Tools</h2>
<p>Event tracking has been around for a little while now and I have used it on several newer sites but I never bothered to go back to older sites and replace the PageTracker technique with Event Tracking.  They still worked ok and still collected the information I wanted.  But one day I was checking out a site in Google Webmaster tools and I spotted that there were a lot of Crawl Errors, most of these errors were 404 errors relating to missing pages; dummy pages that I had specified in PageTracker!</p>
<p>Oops! It seems that Google being super clever had tried to follow my PageTracker code even though they didn&#8217;t point to real pages.  The links the PageTracker code was attached to still worked fine but Google was trying to find another page based solely on the PageTracker.</p>
<h2>SEO Implications?</h2>
<p>As far as I could tell this hadn&#8217;t hurt the SEO ranking of the site but I decided it was time to update it to use Event Tracking instead of PageTracker.  If Google thought there were a whole lot of 404s on the site that couldn&#8217;t be a good thing.  A few months on I haven&#8217;t notice any difference in SEO terms  or in traffic but at least I have tidied up all the Crawl Errors and avoided any potential future penalties, Google does like a tidy site.   And of course I can get more information from Event Tracking than I could from PageTracker.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cotsweb.com/blog/using-google-analytics-to-track-clickthrus-updated-259.html/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
