Hide Google Related Bar On Your Website With CSS

Update: The css method of removing / hiding the related bar no longer works. See the new (javascript only) fix at bottom of this post.

Google recently released a new browser extension for Internet Explorer and Google Chrome called Google Related. I’m sure it will be coming to Firefox soon.

The extension adds a bar to the bottom of some website which shows things like maps, video, images, reviews and related websites.

To get the bar to show at the bottom of your browser Google injects an iframe at the end of your body tag which is positioned with css to always sit at the bottom of your browser and has a high z-index to ensure it always sits above everything else on the page.

No longer working css fix

The beauty of Google Related using an iframe in your own pages html is that you can hide it using a single css declaration. For now it’s as simple as…

iframe.grelated-iframe {
	display: none;
}

…although in the future, if Google get wise to webmasters hiding their Google Related bar you may need to do something like

iframe.grelated-iframe {
	left:-99999px !important;
	display: none !important;
}

Update November 2011

Google no longer makes it easy to hide the tool using css. They’ve ensured every css property you could use to hide the iframe is forced as !important.

The only option left (if you still want to hide the bar) is to use javascript to hide or remove the element.

I’m suggesting a setInterval incase Google does an update which keeps trying to reshow / add the iframe.
I’m suggesting ‘none !important’ because it’s the highest selector value you can add and least likely to be replaced by other css on the page or that Google choose to inject.

setInterval(function()
{
 var ifr = document.body.getElementsByTagName('iframe'), l = ifr.length;
    for(var a = 0; a < l; a++)
    {
        if(ifr[a].src.match(/^http:\/\/www\.gstatic/))
        {
            ifr[a].style.display = 'none !important'
        }
    }
},1000);

That javascript will check all iframes in the page once every second to see if it’s the pesky Google related bar by checking the url (which may need updating in the future!) and hides it if it does.

If you’re unsure of what to do with the javascript code, copy the JavaScript above and paste it into a .js file which is included on every page of your site, or copy the whole next code chunk and paste it just before the closing body tag of your page.

<script type="text/javascript">
setInterval(function()
{
 var ifr = document.body.getElementsByTagName('iframe'), l = ifr.length;
    for(var a = 0; a < l; a++)
    {
        if(ifr[a].src.match(/^http:\/\/www\.gstatic/))
        {
            ifr[a].style.display = 'none !important'
        }
    }
},1000);
</script>

If you use jQuery on your site then the following will do something very similar:

setInterval(function()
{
    $('body > iframe[src^=http://www.gstatic]').css({display:'none !important'});
},1000);

css transform rotation and parent element dimensions

When you use css3 to rotate an element with it’s new transform property, you may find yourself fighting to keep it inside it’s parent.

To clarify, usually rotating an element will first put it into it’s usual position and then literally rotate it around it’s own centre, not caring if it now overlaps elements around it (well I suppose that’s the point sometimes?!?)

I’m using css transform to rotate, in combination with a little javascript to allow images to be rotated (and then saved) as part of PagePlay‘s super simple user interface.

So I initially start out with something like…

--div-------------------------
| ccw                     cw |
| --img--------------------- |
| |                        | |
| |                        | |
| |                        | |
| -------------------------- |
-----------------------------

When you click ccw (counter clockwise) or cw (clockwise) js switched classes on the img and it rotates. Initially, that would give me something like….

       ----------------
       |              |
--div-------------------------
| ccw  |              |   cw |
|      |              i      |
|      |              m      |
|      |              g      |
|      |              |      |
|      |              |      |
-----------------------------
       |              |
       ----------------

(loving the crude graphics? Thought so)

So what I wanted was for the parent div to sit around the image. The problem here is that the div parent doesn’t (and shouldn’t) care about the rotation of it’s child, so we need to make the div larger when it’s rotated. To do this I used a little bit of jQuery and maths to calculate the required additional space…

I don’t know whether the image is going to be taller or wider first, so we need to check that first and come up with a pixel margin to use later…

var img = $('rotator');
var img_w = img.width();
var img_h = img.height();
var the_margin = (img_w > img_h ? (img_w-img_h)/2 : 0);

The img width minus image height divided by 2 is the amount space above and below the standard space the image takes up that it will also need when rotated. If the image is taller than it is wide, we will already have enough space (you could do better by making the div smaller on rotation in this case).

So when we rotate we look at whether the image is rotated or not (rev tells me that here) and then based on that we add or remove the margin we calculated above to the top and bottom of the image to push it’s parent div away from it and make it large enough to accommodate the image.

img.css({marginTop:(rev ? 0 : marg),marginBottom:(rev ? 0 : marg)});

You could certainly do better with dealing with image which are portrait, but then maybe I’ll come back to that another time.

Yii – “Model.id” not defined for CArrayDataProvider and CSqlDataProvider etc

There is a Yii error I come across every now and again, and each time it stumps me.

If you ever get SomeModel.id not defined error when trying to put your dataprovider results into a cgridview or similar then it’s likely because

1) Your model doesn’t have an id column, it might use file_id or user_id etc instead and

2) You haven’t defined which other column should be used.

We do this using what’s known as keyField:


new CArrayDataProvider($users, array('keyField' => 'user_id'));
new CSqlDataProvider($users, array('keyField' => 'user_id'));

[carousel keywords=”yii” tag=”fetchit-21″]

Yii – Rewrite file or image urls for download or display

I recently had a need to track files and images which were uploaded and for their urls to be secret. This meant that they couldn’t sit in a folder waiting to be found and had to be saved below the site root.

To get access to them I wanted to the check the user permissions followed by forcing download of all files (including images). Here are the steps I took to accomplish this…

For the sake of this page, my (fake) file urls are something like:

example.com/user/123/file/456.pdf

Update the urlmanager to rewrite files to my filemanager/view:


	'user//file/.[a-z0-9]+' => 'filemanager/view',

Update the filemanager class’ actionView function:


	public function actionView($id)
	{
		$file = $this->loadModel($id);

		header("Pragma: public"); // required
		header("Expires: 0");
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
		header("Cache-Control: private",false); // required for certain browsers 
		//header("Content-Type: " . $file->mime_type);
		header("Content-Disposition: attachment; filename=\"" . str_replace(" ", "-", preg_replace("@[^a-z0-9 ]@", "", strtolower($file->file_name))) . '.' . $file->file_extension . "\";" );
		header("Content-Transfer-Encoding: binary");
		header("Content-Length: ".filesize(Yii::app()->basePath . '/../../uploads/user_files/' . $file->file_id . '.' . $file->file_extension));
		readfile(Yii::app()->basePath . '/../../uploads/user_files/' . $file->file_id . '.' . $file->file_extension);
		exit();

	}

I also of course required filemanager access to be strict:


	public function accessRules()
	{
		return array(
			array('allow', 
				'actions'=>array('view', 'create','delete'),
				'users'=>array(),
				'expression' => 'User::model()->hasRightsToFile()',
			),
			array('deny',  // deny all users
				'users'=>array('*'),
			),
		);
	}

And that’s about it. Controlled and forced file download with rewritten file urls.

[carousel keywords=”yii” tag=”fetchit-21″]

Yii – Only fill filter dropdown with used options

Sometimes you want to show a filter dropdown but by default it will show all value options even if not assigned to anything. You can use findAll with criteria to only bring back items which are in use…


$criteria = new CDbCriteria;
$criteria->join = 'INNER JOIN organisation ON organisation.category_id = t.category_id';

if($_GET['school_id'])
{
	$criteria->condition = 'organisation.school_id = ' . $_GET['school_id'];
}
else
{

}

$categories = OrganisationCategory::model()->findAll($criteria);
$categories_array = array();
foreach($categories as $category)
{
	$categories_array[$category->category_id] = $category->name;
}


$columns = array(
	'name',
	array(
		'name'=>'category_id',
		'value' => 'OrganisationCategory::model()->findByPk($data->category_id)->name',
		'filter' => $categories_array
[...]

[carousel keywords=”yii” tag=”fetchit-21″]