How to display a custom cover embedding a youtube video and when stopped display the cover again

I need to display a custom image cover in front of an embedded Youtube video.

After the video has stopped, I need to display again the clickable cover.

For a better graphical result I’ve added an over image for the cover and a fadein to the cover when the video ends. To do this I’ve used the Youtube iframe API.

This code is for jQuery 1.4.4. If you have a newer version of jQuery and live() is not working change live() to on().

Here the html:

<a id="idcover" href="#" 
style="display: block; width: 100%;">
<img src="/path/to/cover/off.jpg" alt="Video"></a>

Here the js:

// include youtube API
$.getScript("http://www.youtube.com/player_api");
var myselector = "#idcover";
// preload image displayed on over to avoid glitches: 900 with, 500 height
overimg = new Image(900,500);
overimg.src = '/path/to/cover/on/hover.jpg';
var offimg_src = overimg.src;
$(myselector).live('mouseover', function (e) {
offimg_src = $(this).find('img:first').attr('src');
$(this).find('img:first').attr('src', overimg.src);
});
$(myselector).live('mouseout', function (e) {
$(this).find('img:first').attr('src', offimg_src);
});
$(myselector).live('click', function (e) {
e.preventDefault();
// add video player container
var playerid = 'yourplayercontainerid';
$(myselector).after('&lt;div style="display: none;" id="' + playerid + '"&gt;&lt;/div&gt;');
// I suppose the framework is loaded before the click, so this is not strictly necessary
// function onYouTubeIframeAPIReady() {
window.player = new YT.Player(playerid, {
width: '100%',
height: 720,
videoId: '7W2vjTgzucA', // your youtube code here
playerVars: { 'autoplay': 1, 'controls': 1, 'rel': 0 },
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange,
// 'onError': onPlayerError
}
});
// }
function onPlayerReady(event) {
// hide cover
$(myselector).hide();
// view the player
$('#'+playerid).show();
}

function onPlayerStateChange(e) {
// se stopped (raggiunto il fondo), rimette il tappo e distrugge il video player
if (e.data == 0) {
$(myselector).fadeIn(500);
// destroy iframe player
window.player.destroy();
// destroy player container
$('#'+playerid).remove();
// now the cover is ready to another click, and all 
// this process will restart on user click on cover
}
}

Clear Varnish cache via PHP: a Drupal 7 proof of concept

Using Varnish as reverse proxy or proxy is an useful approach to reduce the load of webservers like Apache.

In Drupal 7 I’ve to clear the varnish cache of a specific domain when Drupal caches are globally cleared. Drupal has the right hook invoked when cache are cleared:

function clearcachevarnish_flush_caches() {
  $filename = '/var/www/varnishdomains2cleardir/varnishdomains2clear';
  // each domain on a separate line: append to the end of the file
  $myfile = fopen($filename, &quot;a&quot;);
  $h = $_SERVER['HTTP_HOST'];
  $txt = $h . &quot;\n&quot;;
  fwrite($myfile, $txt);
  fclose($myfile);
  drupal_set_message('Varnish cache queued to be cleared. Please wait 1 minute before checking.');
  // no cache table should be cleared
  return array();
}

Now this piece of code simply adds the current domain to a ASCII text file on /var/www/varnishdomains2cleardir/varnishdomains2clear.

Preparing the file to the write

On CentOS you have to add /var/www/varnishdomains2cleardir to the httpd-writable directories list using:

mkdir /var/www/varnishdomains2cleardir;
chcon -v --type=httpd_sys_content_t /var/www/varnishdomains2cleardir;
chown myuser:mygroup /var/www/varnishdomains2cleardir;
chmod -R 777 /var/www/varnishdomains2cleardir;
touch /var/www/varnishdomains2cleardir/varnishdomains2clear;

Now the empty file is ready to be written by your hook_flush_caches() implementation. Now enable the clearvarnishcache module and clear the cache to write the current domain name to the file.

The clear varnish cache script

To clear the varnish cache you usually have to be logged as root using the command varnishadm. Here a script that will read the domains file written above, clear the varnish cache for that domain and then remove the domains lines.

#!/bin/bash
callinguser=`whoami`
if [ &quot;root&quot; != &quot;$callinguser&quot; ]
then
 echo &quot;Only root can run this command.&quot;
 exit 1
fi
cd /path/to/clear/cache/command/

date=`date +%Y-%m-%d_%H:%M:%S`

# check lock
# prevent the script from being run more than once
if [ -f /tmp/clearcachevarnish-lock ]; then
echo &quot;Script clearcachevarnish is already running. You can rm /tmp/clearcachevarnish-lock to break the lock manually.&quot;
exit 1
fi
touch /tmp/clearcachevarnish-lock
dominidapulire=`less /var/www/varnishdomains2cleardir/varnishdomains2clear`
while [[ ! -z $dominidapulire ]]
do
 dominio=$(echo &quot;$dominidapulire&quot; | sed -n '$p')
 echo $dominio
 dominidapulire=$(echo &quot;$dominidapulire&quot; | sed '$d')
 if [ &quot;&quot; != &quot;$dominio&quot; ]
 then
 varnishadm -T 127.0.0.1:6082 -S /etc/varnish/secret ban req.http.host == &quot;$dominio&quot;
 echo &quot;varnish cleared on $dominio&quot;
 fi
done
# remove all domains lines
truncate --size 0 /var/www/varnishdomains2cleardir/varnishdomains2clear

# remove lock
rm /tmp/clearcachevarnish-lock

Make this script as executable .sh file using chmod a+x on it. If you run the bash script, varnish cache for files on the domains list will be cleared. It’s not so useful when using the Drupal UI so we should schedule this task periodically, e.g. every minute.

Scheduling the varnish clear cache

Here the crontab entry for execute the script every minute:


* * * * * root /path/to/clear/cache/command/clearcachevarnish.sh

The steps

  1. User clear Drupal cache
  2. hook_flush_caches() is invoked: the domains list file is written
  3. clear varnish cache script is launched by root every minute
  4. for each domain in the list, varnish cache is cleared

This is the end of this proof of concept. The code wasn’t tested against attacks so please comment if you have any suggestion to improve it. I’m not very fond of the idea of a php script writing something read by a bash script but this is the less problematic solution I found for this case.

How to fix the Bash bug on CentOS 6

Recently a critical bash bug was discovered.

To fix your CentOS 6 you have to check if you have a vulnerable bash installed. From a non root user, type:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

If you read “vulnerable” as output then you have to update bash. Type su- and then the password to log in as superuser, then type:

yum update bash

Type Y when asked. When the update process is completed, retype the test script:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

And you shouldn’t read the “vulnerable” message anymore.

Read more:

Web fonts and dynamic height calculation issues on jQuery

Recently we’ve nice fonts on web pages like Google Fonts and other web fonts. Take this case, you have to set two divs to the same height. One (div.funny) has some text with Google Fonts, the other is empty.

On Chrome console you type something like:

jQuery(".very", ".myview").height(function () {
  jQuery(this).height(jQuery(this).parent(".myview").find('.funny').height());
});

Div.very and div.funny are now at the same height.

Now if you try to do the same on jquery document ready you got elements with different height. Why?

Because the calculation happens on document ready but before fonts are loaded. The solution is to wrap the code on $(window).load().

$(window).load(function () {
  $(".very", ".myview").height(function () {
    $(this).height($(this).parent(".myview").find('.funny').height());
  });
});

Now .very and .funny are at the same height.

See also:
Calculate Container’s Height After The Font File Loads

Web fonts and dynamic height calculation issues on jQuery

Recently we’ve nice fonts on web pages like Google Fonts and other web fonts. Take this case, you have to set two divs to the same height. One (div.funny) has some text with Google Fonts, the other is empty.

On Chrome console you type something like:

jQuery(".very", ".myview").height(function () {
  jQuery(this).height(jQuery(this).parent(".myview").find('.funny').height());
});

Div.very and div.funny are now at the same height.

Now if you try to do the same on jquery document ready you got elements with different height. Why?

Because the calculation happens on document ready but before fonts are loaded. The solution is to wrap the code on $(window).load().

$(window).load(function () {
  $(".very", ".myview").height(function () {
    $(this).height($(this).parent(".myview").find('.funny').height());
  });
});

Now .very and .funny are at the same height.

See also:
Calculate Container’s Height After The Font File Loads

Untitled document instead of Google Docs list: how to get your document list again

Until yesterday, the shortcut docs.google.com listed the files I’ve on Drive.

Today when I try to access the domain I can only get a blank, Untitled document.

In that case you have to move the cursor on the title and then click on the arrow.

back2gd

You’ll be back on drive.google.com.

How to enable gzip on proxy servers on Apache

I’m starting to use the gunicorn django app using supervisord. Here my configuration:

  • Varnish: port 80
  • Apache: port 8080
  • gunicorn: port 4180 (/path/to/my/manage.py run_gunicorn localhost:4180)

Only the port 80 is exposed to other clients than localhost. The Varnish default backend is Apache (localhost:8080). I have a Drupal installation and a django installation on the same machine: since I want to expose django on the same domain at a defined location, I add to Apache this location:

<IfModule mod_proxy.c>
ProxyRequests Off
ProxyPreserveHost On

<Proxy *>
Order deny,allow
Allow from all
</Proxy>

# on port 4180 gunicorn is running
# @see /etc/supervisor.conf
ProxyPass /foo http://localhost:4180/
ProxyPassReverse /foo http://localhost:4180/

<Location /mypath>
Order allow,deny
Allow from all
AddOutputFilterByType DEFLATE text/html
</Location>
</IfModule>

You can omit AddOutputFilterByType DEFLATE text/html: here I just take the response from gunicorn, compress and then serve to the client in this way:

(client) -> varnish -> apache -> gunicorn

(client) <- varnish <- apache (compress) <- gunicorn
                (X-Varnish-Cache: MISS) 

Here an example of what I get:
Image

It’s a big page, but using gzip from 2.2 MB of the uncompressed page I get 417 KB gzipped text/html, less than 1/4 of the original!

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: