Oct200816

Frontpage Slideshow for Drupal

I have begun coding a module to allow the Frontpage Slideshow to be displayed within a block or a panel.

Frontpage slideshow is a script by Joomlaworks.

The module requires that the script is purchased from Joomlaworks as it contains important files for it to work.

The module which is currently in development can be found at http://code.google.com/p/fpss-drupal/.

The code is still in an early stage but is working and usable, but I would recommend not using it on a production site.

There are a few issues with the module at the moment.

  • Module depends on jquery_update
  • Module uses the upload module to upload the image for the slide, but this allows any file to be uploaded, so requires some further work.

How does it work

The module adds in 2 new node types (slide, slideshow). Each slideshow node creates a new block which can be used anywhere in your site.

Slides are then assigned to a slideshow. The slideshow node contains most of the important settings such as dimensions and timings but as well as this there is an admin settings page which controls the default settings across the whole site such as the language of the text and the javascript engine.

I have developed the module purely with jQuery in mind. Mootools may work, but is likely to be unstable and buggy.

Where can I download this module?

Go to http://code.google.com/p/fpss-drupal/ and download it from the right hand side. If you find any issues with the module please do so by leaving an issue on the Google Code site.

Useful Drupal Module Development Book

Pro Drupal Development is a very good book published by Apress. The new second edition covers Drupal 6.

Oct200812

[PHP + MySQL] Making a basic product database – Part 1

Firstly you need a server which supports PHP and Mysql. If you haven’t got one, you can set up your computer as a local web server. If you are on Windows, you can follow this guide to help you Set up your PC as a test environment using Apache, PHP and MySQL.

Create the database and tables

Open up your database management tool (PHPMyAdmin or command prompt or MySQL Query Browser) and create a new database, I will call mine product_db.

Then we want to create 3 tables. Product, companies and ownership.

The products table will contain 3 fields:

pid – A unique ID that is automatically generated for us.
name – The name of the product.
weight – The weight of the product.

This is the SQL for the table I am creating:

CREATE TABLE products (
pid INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
name VARCHAR( 100 ) NOT NULL ,
weight FLOAT NOT NULL
)

Next up is the companies table which will contain 3 fields.

cid – A unique ID that is automatically generated for us.
name – The name of the company.
email – A contact email address for the company.

This is the SQL for the table I am creating:

CREATE TABLE companies (
cid INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
name VARCHAR( 100 ) NOT NULL ,
email VARCHAR(100) NOT NULL
)

The 3rd table is the ownership table which will link up products to companies.

This will contain 2 fields, pid and cid which relate to the automatic ID of the 2 other tables.

This is the SQL for the table I am creating:

CREATE TABLE ownership (
cid INT NOT NULL,
pid INT NOT NULL
)

Now that we have the tables set up we can write the PHP to interact with the tables.

Connecting to the database using PHP

In your web folder, create a file and call it db_config.php.

In this file we will make the connection to the database.

<?php
$db_host = 'localhost';
$db_user = 'root';
$db_pass = 'password';
$db_name = 'product_db';
mysql_connect($db_host,$db_user,$db_pass) or die(mysql_error());
mysql_select_db($db_name) or die(mysql_error());
?>

Change the $db_xxxx variables to your database settings.

Save the file and load it up in your browser. If you get a blank white screen, everything is OK.

Possible Errors

Some possible errors you may get are…

Unknown database 'product1_db'

This will be because $db_name is wrong.

Warning: mysql_connect() [function.mysql-connect]: Unknown MySQL server host 'loc1alhost' (11001) in D:\xampp\htdocs\product\db_config.php on line 3
Unknown MySQL server host 'loc1alhost' (11001)

This is because the $db_host is wrong.

Warning: mysql_connect() [function.mysql-connect]: Access denied for user 'ro1ot'@'localhost' (using password: YES) in D:\xampp\htdocs\product\db_config.php on line 3
Access denied for user 'ro1ot'@'localhost' (using password: YES)

This could be because $db_user is wrong or $db_pass is wrong.

Inserting new products in to the database

Create a new file and call it index.php and put it in the same location as the db_config.php file and paste the following code in it:

<?php require_once 'db_config.php'; ?>

Previewing the page should result in a blank white page. This means that everything is OK.

Now we will create a function which will used for all our modifying database interactions such as inserting data, updating data and deleting data.

function db_action($data = array()) {
	switch ($data['action']) {
		case 'insert':
			$keys = array(); $values = array();
			foreach ($data['data'] as $key => $value) {
				$keys[$key] = $key;
				$values[$key] = "'".$value."'";
			}
			$keys = implode(', ', $keys);
			$values = implode(', ', $values);
			mysql_query("INSERT INTO ".$data['table']." (".$keys.") VALUES (".$values.")");
			break;
		case 'update':
			mysql_query("UPDATE ".$data['table']." SET ".$values." WHERE ".$key." = ".$id);
			break;
		case 'delete':
			mysql_query("DELETE FROM ".$data['table']." WHERE ".$key." = ".$id);
			break;
	}
	return;
}

This is set up for inserting data only at the moment, both update and delete would fail at the moment, unless the data was passed on properly.

To insert data into the database we will pass all the information the db_function needs in an array like the one below.

$array = array(
  'action' => 'insert',
  'table' => 'products',
  'data' => array(
    'name' => 'Product Name',
    'weight' => '12.5',
  ),
);

By looking at the db_action function you can see that the action part of the array defines what we want to do in the database (insert, update or delete), then we have the table name (products, companies, ownership) and a data array which is in the format of the key (column name in the database) and the value we want to put in to the database.

We draw this data out the array in to a workable format using the following code:

$keys = array(); $values = array();
foreach ($data['data'] as $key => $value) {
  $keys[$key] = $key;
  $values[$key] = "'".$value."'";
}

This goes through the data array within our main array and spits out the $keys and $values that we will use for the database.

Once we have the $keys and $values arrays we need to organise these in a way that MySQL will know to insert correctly.

$keys = implode(', ', $keys);
$values = implode(', ', $values);

This sets the arrays in to strings with each field separated with a comma. Perfect for MySQL.

We then insert the data in to the database using the following code.

mysql_query("INSERT INTO ".$data['table']." (".$keys.") VALUES (".$values.")");

From the above array, the information sent to MySQL would be:

INSERT INTO products (name, weight) VALUES ('Product Name', '12.5')

Inserting new companies in to the database

By changing the array we can completely change the data that is going in to the database. Now lets modify the array to insert a new company.

$array = array(
  'action' => 'insert',
  'table' => 'companies',
  'data' => array(
    'name' => 'Something Enterprise',
    'email' => 'info@somethingenterprise.com',
  ),
);

So with the following code, by viewing the page we will insert data in to both tables.

<?php require_once 'db_config.php'; ?>
<?php
$action = $_POST['action'] ? $_POST['action'] : $_GET['action'];
$pid = $_POST['pid'] ? $_POST['pid'] : $_GET['pid'];
$cid = $_POST['cid'] ? $_POST['cid'] : $_GET['cid'];
 
function db_action($data = array()) {
	switch ($data['action']) {
		case 'insert':
			$keys = array(); $values = array();
			foreach ($data['data'] as $key => $value) {
				$keys[$key] = $key;
				$values[$key] = "'".$value."'";
			}
			$keys = implode(', ', $keys);
			$values = implode(', ', $values);
			mysql_query("INSERT INTO ".$data['table']." (".$keys.") VALUES (".$values.")");
			break;
		case 'update':
			mysql_query("UPDATE ".$data['table']." SET ".$values." WHERE ".$key." = ".$id);
			break;
		case 'delete':
			mysql_query("DELETE FROM ".$data['table']." WHERE ".$key." = ".$id);
			break;
	}
	return;
}
 
$product = array(
	'action' => 'insert',
	'table' => 'products',
	'data' => array(
		'name' => 'Product Name',
		'weight' => '12.5',
	),
);
 
$company = array(
	'action' => 'insert',
	'table' => 'companies',
	'data' => array(
		'name' => 'Something Enterprise',
		'email' => 'info@somethingenterprise.com',
	),
);
 
db_action($product);
db_action($company);
?>

Inserting new ownership in to the database

Now that we have both a company and a product we can try linking them together. Although we will automate this later, check your database, both the product and company should have an ID of 1.

$ownership = array(
	'action' => 'insert',
	'table' => 'ownership',
	'data' => array(
		'pid' => 1,
		'cid' => 1,
	),
);

Then by running

db_action($ownership);

We have the entry added to the ownership table.

Updating existing data

To update data we just need to modify our function a little to get the data in the right format and we can update with ease.

To do this we update the ‘update’ case in our switch statement to the following:

case 'update':
			$items = array();
			foreach ($data['data'] as $key => $value) {
				$items[] = $key .' = "'.$value.'"';
			}
			$values = implode(' , ', $items);
			$key = $data['key'];
			$id = $data['id'];
			mysql_query("UPDATE ".$data['table']." SET ".$values." WHERE ".$key." = ".$id);
			break;

We are using a similar foreach statement but have changed the 2 arrays into 1 array as the SQL format for UPDATE is different to INSERT.

For the update statement to work we need to pass on the values for the WHERE statement. After a minor change to our array we have the following:

$updateproduct = array(
	'action' => 'update',
	'table' => 'products',
	'data' => array(
		'name' => 'New Product Name',
	),
	'key' => 'pid',
	'id' => 1,
);

We have changed the action and added 2 new array keys, 1 called key which is the column name that we will use in our SQL statement and the id which is the cid or pid that needs to be updated.

Deleting data

The DELETE case in our function is even easier than our UPDATE as we don’t need to much around with any data.

case 'delete':
			$key = $data['key'];
			$id = $data['id'];
			mysql_query("DELETE FROM ".$data['table']." WHERE ".$key." = ".$id);
			break;

Our DELETE array is almost identical to our UPDATE array.

$deleteproduct = array(
	'action' => 'delete',
	'table' => 'products',
	'key' => 'pid',
	'id' => 1,
);

All we need is the key and id as no data is needed to delete a row.

In part 2 we will create the HTML to do our functions.

Oct200809

Google Chrome annoyances

It has been over a month now since Google released Chrome to the world and quite a few annoyances have appeared over that time.

Closing multiple tabs

The huge flaw that is extremely irritating is no warning of closing multiple tabs.

If you have 10 tabs open and accidentally close the main window at the top right rather than the tab close button. Goodbye tabs.

You can have the sessions enabled to get it back once you open Chrome again but that isn’t very helpful if you had active downloads going when you accidentally closed the browser.

Earlier today I was download Portal: Prelude, an expansion modification for the game Portal. After download 550MB of the 775MB file, I accidentally closed Chrome forgetting that I had the download going.

IE and FF would of both stopped this from happening as they both open downloads in separate windows rather than the main browser, so if you close the main browser the downloads continue. Chrome does not.

I wasted that time and bandwidth downloading 550MB to be lost in the ether and having to download it again, because something so trivial was missed out of Chrome.

It doesn’t take a lot of common sense to know this is could be a problem, Mozilla, Microsoft and Opera all have implementations in place to stop this happening. The fact that Google took the best parts of all the other browsers in to 1 then deciding that a rather important feature wasn’t in their users best interest is worrying. How many other problems are there going to be under the surface?

Downloads

I have found that on many user initiated downloads that they just fail to start full stop on my Chrome installation at work and some downloads on my Chrome installation at home.

By clicking a download button the file will appear at the bottom of the browser and have ‘starting…’ next to it but never progress past this stage. Right clicking the file and selecting Save as… works for all anchor links, but any downloads that are done through a form button are impossible to download which results in my opening up Firefox to download files.

Dictionary

You don’t seem to have the ability to add new words to the dictionary in Chrome which is rather strange. In Firefox you can and it is helpful when you type in something quite a lot and it isn’t in the dictionary, that little red line becomes annoying.

While writing this post, there are 2 words with red lines underneath them. The first is Firefox. Fair enough, it isn’t an actual word in the dictionary but still, Google do give a lot of money to the Mozilla foundation (which is in the dictionary). But the 2nd underlined word is an odd one indeed. It is Google. The company who have made the browser haven’t even put their name in the dictionary, instead suggesting that I meant to type goggle.

Oct200809

[HTML] Display HTML content over a Flash object

When dealing with drop down menus such as the suckerfish menu you will find that the menu disappears behind any Flash object that is on the page.

Unfortunately what works with other HTML elements with the z-index doesn’t work with Flash as Flash will end up on top regardless.

To change this we need to add some bits of code to a Flash object to allow HTML to appear on top.

<object width="425" height="344">
<param name="movie" value="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1"></param>
<param name="allowFullScreen" value="true"></param>
<param name="wmode" value="transparent" />
<embed src="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344" wmode="transparent"></embed>
</object>

What we have done is added the following 2 bits of code:

wmode="transparent"

To the tag and:

<param name="wmode" value="transparent" />

In between the tags.

For those that are using better code than the standard markup that websites like YouTube give you, such as using conditional formatting, you can do the same by just adding the param in.

<!--[if !IE]> <-->
<object type="application/x-shockwave-flash" width="350" height="284" data="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1">
<!--> <![endif]-->
<!--[if IE]>
<object type="application/x-shockwave-flash" width="350" height="284" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">
<![endif]-->
<param name="movie" value="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1" />
<param name="wmode" value="transparent" />
<p>Your browser is not able to display this multimedia content.</p>
</object>
Oct200809

[HTML] Make YouTube embed code XHTML valid without Javascript

When you embed a video on to your website from YouTube you will find that your site will no longer successfully validate on the W3C validator.

This is because the embed tag is not supported, although it works on most browsers.

The code you get from YouTube is something similar to this:

<object width="425" height="344">
<param name="movie" value="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1"></param>
<param name="allowFullScreen" value="true"></param>
<embed src="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed>
</object>

Note that line #4 is the embed code that isn’t supported.

To make the code valid and work in most browsers (tested in IE6+, FF3, Chrome + Safari, Opera).

<!--[if !IE]> <-->
<object type="application/x-shockwave-flash" width="350" height="284" data="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1">
<!--> <![endif]-->
<!--[if IE]>
<object type="application/x-shockwave-flash" width="350" height="284" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">
<![endif]-->
<param name="movie" value="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1" />
<p>Your browser is not able to display this multimedia content.</p>
</object>

With the use of condition formatting we are able to set out the code to work in most (if not all) browsers.

Oct200809

[HTML] Stop embeded YouTube videos autoplaying

When embedding YouTube videos on to your website, the video will play back automatically as soon as the page has loaded. To stop this, follow this quick edit.

When you embed a video from YouTube you get some code like this:

<object width="425" height="344">
<param name="movie" value="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1"></param>
<param name="allowFullScreen" value="true"></param>
<embed src="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed>
</object>

All you need to do is add &autoplay=0 to the end of both URLs, like so:

When you embed a video from YouTube you get some code like this:

<object width="425" height="344">
<param name="movie" value="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1&autoplay=0"></param>
<param name="allowFullScreen" value="true"></param>
<embed src="http://www.youtube.com/v/jJpx9MEi6_M&hl=en&fs=1&autoplay=0" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed>
</object>