Archive for April, 2009
Create image upload field using Drupal Form API
Posted by anil in Drupal, Open Source on April 28th, 2009

Product Form with Image Field
We can create a image/file upload field using Drupal Form API. Here I am considering an example of product form so we can easily understand its use and its implementation. Our product form have two fields product name and product image. I am considering only three fields productid, product name and product image in our product table. The productid is primary key and set to auto increment. Our module name is ‘product.module’.
STEP 1.
function new_product_form() { $form['product_name'] = array( '#title' => t('Product Name'), '#type' => 'textfield', '#required' => TRUE, '#description' => t('Please enter product name.'), ); // Product picture $form['picture'] = array('#type' => 'fieldset', '#title' => t('Product image')); $form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload product image'), '#size' => 48, '#description' => t('Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => '250x250', '%size' => '30'))); $form['#validate'][] = 'product_validate_picture'; $form['submit'] = array( '#type' => 'submit', '#value' => t('Submit'), ); $form['#redirect'] = 'product_list'; $form['#attributes']['enctype'] = 'multipart/form-data'; return $form; }
We have set the enctype of form as multipart/form-data because we are uploading the file. We also set a validation function product_validate_picture() for validating our uploaded image.
STEP 2.
Now we are creating product_validate_picture() function.
function product_validate_picture(&$form, &$form_state) { $validators = array( 'file_validate_is_image' => array(), 'file_validate_image_resolution' => array('250x250')), 'file_validate_size' => array(30 * 1024), ); if ($file = file_save_upload('picture_upload', $validators)) { // Remove the old picture. if (isset($form_state['values']['_product']->image_path) && file_exists($form_state['values']['_product']->image_path)){ file_delete($form_state['values']['_product']->image_path); } $productid = 0; if (!isset($form_state['values']['productid'])) { // Execute in case of new product $query = "SHOW TABLE STATUS LIKE 'product'"; $rs = db_query($query); $row = db_fetch_object($rs); $productid = isset($row->Auto_increment) ? $row->Auto_increment : 0; } else { $productid = $form_state['values']['productid']; } $info = image_get_info($file->filepath); $destination = variable_get('product_picture_path', 'product_pictures') .'/picture-'. $productid .'.'. $info['extension']; if (file_copy($file, $destination, FILE_EXISTS_REPLACE)) { $form_state['values']['picture'] = $file->filepath; } else { form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", array('%directory' => variable_get('product_picture_path', 'product_pictures')))); } } }
Drupal provide a function file_save_upload() for saving the uploaded file to a new location. Its also take associative array of callback functions used to validate the file as optional argument. Here we passing three callback functions file_validate_is_image, file_validate_image_resolution, and file_validate_size for validating file type as image, image resolution and file size respectively. This function return an object containing the file information or 0 in case of error.
We are using this product_validate_picture() function in both new product and edit product form. So, if ‘_product’ is not set in form values then its fetch the id of next auto_increment value set in product table. In case of edit product form it replace the old product image with new image if user uploaded a new image.
We assign the uploaded image path in our form values so we can store that path in out product table.
$form_state['values']['picture'] = $file->filepath;
STEP 3.
function new_product_form_submit($form_id, $form) { $form_values = $form['values']; $product_name = trim($form_values['product_name']); $image_path = $form_values['picture']; $query = "INSERT INTO product(product_name, image_path) VALUES('%s', '%s')"; db_query($query, $product_name, $image_path); drupal_set_message(t('Product has been added successfully.')); }
Then we will save the product imformation in out product table.
STEP 4.
In case of edit product form we are passing productid as arg(2). We fetch the product imformation using this productid and set the default values in form. We also save the product information and productid in form values.
function edit_product_form() { $productid = arg(2); $query = "SELECT * FROM {product} WHERE productid = '%d'"; $rs = db_query($query, $productid); $product_data = db_fetch_object($rs); $form['_product'] = array('#type' => 'value', '#value' => $product_data); $form['productid'] = array('#type' => 'value', '#value' => $product_data->productid); $form['product_name'] = array( '#title' => t('Product Name'), '#type' => 'textfield', '#default_value' => stripslashes($product_data->product_name), '#required' => TRUE, '#description' => t('Please enter product name.'), ); // Product picture $form['picture'] = array('#type' => 'fieldset', '#title' => t('Product image')); $picture = theme('product_picture', (object)$product_data); if ($product_data->image_path) { $form['picture']['current_picture'] = array('#value' => $picture); $form['picture']['picture_delete'] = array('#type' => 'checkbox', '#title' => t('Delete picture'), '#description' => t('Check this box to delete your current picture.')); } else { $form['picture']['picture_delete'] = array('#type' => 'hidden'); } $form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload product image'), '#size' => 48, '#description' => t('Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => '250x250', '%size' => '30'))); $form['#validate'][] = 'product_validate_picture'; $form['#redirect'] = 'product_list'; $form['#attributes']['enctype'] = 'multipart/form-data'; return $form; }
STEP 5.
Then we will update the product detail. If user want to delete product image then we will delete the current image of product.
function edit_product_form_submit($form_id, $form) { $form_values = $form['values']; $product_name = trim($form_values['product_name']); $image_path = $form_values['_product']->image_path; // Delete picture if requested, and if no replacement picture was given. if (!empty($form_values['picture_delete']) && $form_values['picture'] == '') { if ($form_values['_product']->image_path && file_exists($form_values['_product']->image_path)) { file_delete($form_values['_product']->image_path); } $image_path = ''; } if (isset($form_values['picture']) && $form_values['picture'] != '') { $image_path = $form_values['picture']; } $query = "UPDATE {product} SET product_name = '%s', image_path = '%s' WHERE productid = '%d'"; db_query($query, $product_name, $image_path, $productid); drupal_set_message(t('Product has been updated successfully.')); }
STEP 6.
We are also theming our product image. For this, we are using a product-picture.tpl.php file. First we register our theme in theme registry using hook_theme() callback function.
function product_theme() { return array( 'product_picture' => array( 'arguments' => array('product' => NULL), 'template' => 'product-picture', ), ); } function template_preprocess_product_picture(&$variables) { $variables['picture'] = ''; $product = $variables['product']; if (!empty($product->image_path) && file_exists($product->image_path)) { $picture = file_create_url($product->image_path); } else if (variable_get('product_picture_default', '')) { $picture = variable_get('product_picture_default', ''); } if (isset($picture)) { $alt = t("@product's picture", array('@product' => $product->product_name )); $variables['picture'] = theme('image', $picture, $alt, $alt, '', FALSE); } }
<?php //product-picture.tpl.php file ?> <div class="picture"> <?php print $picture; ?> </div>
How know recipient read the email or newsletter?
Sometimes we send the newsletters or emails to lot of peoples and we want to know how many of them read it. Normally the websites like Gmail, Yahoo, Hotmail don’t provide any facility for this purpose. But we can know that by sending HTML emails.
HTML Emails – HTML emails are emails which can contain HTML tags in email body. Like <table>, <tr>, <td>, etc.
The main thing here is we need to send some information to our server when user open the email. So for this, we can place an image in email body and when user open this email the browser send request to our webserver for this image. We can also achieve this by adding javascript code or hidden iframe but normally email clients don’t support javascript code and iframes in email body and they strips out this unwanted code form email body. So, the best way to achieve this is by using images.
<?php /*send_newsletter.php*/ $newsletterid = 25; // array of recipients $recipients = array('test1@yahoo.com', 'test2@yahoo.com', 'test3@yahoo.com', 'test4@gmail.com', 'test5@gmail.com', 'test6@hotmail.com', 'test7@hotmail.com', 'test8@aol.com', 'test9@aol.com', 'test10@yahoo.com'); // subject $subject = 'Newsletter for April'; // message $message = " <html> <head> <title>Newsletter for April</title> </head> <body> <p>This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. This is a Demo Newsletter. </p> <img src='http://www.akchauhan.com/newsletter_read.php?newsletterid={$newsletterid}' height='1' width='1' /><br/><br/> Thanks,<br/> www.akchauhan.com </body> </html>"; // To send HTML mail, the Content-type header must be set $headers = 'MIME-Version: 1.0' . "rn"; $headers .= 'Content-type: text/html; charset=iso-8859-1' . "rn"; $headers .= 'From: AKChauhan Blog <anil@akchauhan.com>' . "rn"; foreach($recipients as $to) { // Mail it mail($to, $subject, $message, $headers); } ?>
I have used a variable $newsletterid to track newsletter. We can also send some extra information in query string as per our requirement.
Like
http://www.akchauhan.com/newsletter_read.php?newsletterid=$newsletterid&userid=$userid
Note: Here I have used mail() function only to make demonstration simple. mail() function is not suitable for sending large number of email in loop. Better we use PEAR::Mail or PEAR::Mail_Queue packages for sending large number of email.
<?php /*newsletter_read.php*/ $newsletterid = $_GET['newsletterid']; /*Write some code to update your read counter in your database. Or, do whatever you want to do when user open your newsletter.*/ mysql_query('UPDATE info SET newsletter_count = newsletter_count + 1 WHERE newsletterid = ' . $newsletterid); // We'll be outputting a JPEG header('Content-Type: image/jpeg'); $im = @imagecreatefromjpeg('images/one_pixel_small_white_image.jpg'); imagejpeg($img); imagedestroy($img); ?>
In above code, first we updated our newsletter read counter in database. We can do other things also like send an email to admin etc. as per requirement. Then we set the Content-Type to image/jpeg as we are going to send a jpeg image. So, we need to tell the browser about the content type of our response. Then, we created a 1 pixel white image usng GD library and outputted it to browser using imagejpeg() function.
Create CSS Stylesheet and JavaScript for Print
Posted by admin in CSS, HTML, JavaScript on April 13th, 2009

CSS Stylesheet for Print
When we want to print out HTML page we need a lighter version of our HTML page. Basically, we don’t want to print the background images, background colors, advertisements and other things which are not relevant in printing. For this purpose, we need to specify a CSS stylesheet which browser use when we print our HTML page. We can also change the width and layout of our HTML page. We can specify our CSS stylesheet for print like this.
<head> /*External style sheets*/ <link rel="stylesheet" href="css/print.css" type="text/css" media="print" /> </head>
<head> /*Embedded style sheets*/ <style type="text/css" media="print"> .noprint { display:none; } </style> </head>
The important thing to note here is the media descriptor media=”print” which we are giving through media attribute. The browser knows using this media descriptor that this CSS stylesheet is defined to use at the time of print. We can define CSS stylesheet for SCREEN like this.
<head> /*External style sheets*/ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" /> </head>
<head> /*Embedded style sheets*/ <style type="text/css" media="screen"> .header { width:800px; height:200px; } </style> </head>
In the following example, I don’t want to print the “Print this Coupon” link in coupon. So, I have just added the class “noprint” and set the display property none in this class. Now, I will apply this class to all the elements which I don’t want to print. You can easily create other classes for different purpose like to change the background color of element in print.
<!--coupon.html--> <html> <head> <title>CSS stylesheet for Print</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" /> <link rel="stylesheet" href="css/print.css" type="text/css" media="print" /> </head> <body> <div class="coupon-mini"> <table width="500" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="146" align="left" valign="top"><div class='default-coupon'><img src='/sites/default/files/coupon_116_116.'></div></td> <td width="354" align="left" valign="top"> <h3 style="font-family: 'palatino linotype',palatino; line-height:18px; padding:6px 0 0 0; color:#0e549c; "> Divan Restaurant and Hookah Lounge, Alabama </h3> <div class='coupons-text1'><span>McDonald 20% Off.</span><p>McDonald 20% Off.</p></div><br /> <div style="clear:both;"></div> <div class="detail-basic1"> 3125 Piedmont Rd NE, Atlanta, Alabama<br> <strong> Phone Number :</strong> (404) 365-0410<br/> <strong> Pincode:</strong> 30305 <div class="openhr1"><strong> Opening Hours:</strong> 6:30 PM to 01:00 AM</div> <div class="web1"> <div class="lft1"><a href="#" class="about-web-link">http://www.divanatlanta.com</a></div> <div class="rght1"><a href="#" class="about-mail-link">ajay0878@yahoo.com</a></div> </div> </div> </td> </tr> </table> </div> <div class="print noprint"><a href="javascript:window.print();" class="coupon-print-link">Print this Coupon</a></div> </body> </html>
We have also added the window.print() function on Print this Coupon link. This function print the current windows content. We can also print our page through File->Print… menu. But this function is useful when the toolbar and menubar are disabled.
How call JavaScript function from FLASH
Posted by admin in Flash, JavaScript on April 8th, 2009
We can call the JavaScript function from FLASH application. I am showing here how we do that.
getURL("javascript:helloWorld();");
Here “getURL()” is the Flash ActionScript function. We have give the name of our JavaScript function with “javascript:” as prefix. This will call the “helloWorld()” function which we have defined in JavaScript.
<script type="text/javascript"> function helloWorld() { alert('Hello World'); } </script>
Also, add the following parameter to the OBJECT and EMBED tag:
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0" width="150" height="120"> <param name="movie" value="swf/myflash.swf" /> <param name="allowscriptaccess" value="always" /> <param name="wmode" value="transparent" /> <param name="menu" value="false" /> <embed height="120" width="150" allowscriptaccess="always" wmode="transparent" menu="false" src="swf/myflash.swf" type="application/x-shockwave-flash"/> </object>
allowscriptaccess let the Flash application to communicate with the HTML page hosting it. This is required because getURL() function can cause JavaScript to use the permissions of the HTML page, which can be different from the permissions of your Flash application. This has important implications for cross-domain security.
The valid values for allowscriptaccess are:
always permits scripting operations at all times.
never forbids all scripting operations.
samedomain permits scripting operations only if the Flash application is from the same domain as the HTML page.
The default value used by all HTML publish templates is samedomain.
