My (mostly technical) blog

Archive for the ‘Code’ Category

As I’m just trying out Microsoft SQL Server Azure Spatial, the following things need to be removed from any generated SQL script in order to make it run on SQL Server Azure as they are not supported:

ON [PRIMARY]
PAD_INDEX
ALLOW_ROW_LOCKS
ALLOW_PAGE_LOCKS
SORT_IN_TEMPDB
newsequentialid()

I will keep this post updated as I discover new booby traps!
For a full list, check: http://msdn.microsoft.com/en-us/library/ee336253.aspx 

I’ve run across this situation multiple times, where I have for example, an ID that I get in the code behind, and I want to append it to some href in the aspx, and each time I forget how to do it, so as a reminder for myself, here is how to do it and problems I ran into:

Assuming I have a property in the code behind that returns a GUID

protected Guid CustomerId {
 get { return new Guid(); }
}

And assuming I have a link in my aspx page that I want to append this property to, here is how to do it

<a href="upgrade.aspx?id=<%= CustomerId .ToString() %>">Upgrade</a>

Note that this will not work if you specify a runat=server to the href for any reason, for example. to show the link or hide it according to specific logic.

If you need to show and hide the link, you can enclose it in a place holder and access that placeholder from the code behind

<asp:PlaceHolder ID="UpdgradeLinkPlaceholder" runat="server">
<a href="upgrade.aspx?id=<%= CustomerId .ToString() %>">Upgrade</a>
</asp:PlaceHolder>
Tags:

I have never been more in need of a proper PHP debugger in my whole life. I have been stuck with a very mysterious behavior with CakePHP for the past 4 hours.

I was editing a model, then saving it. For some reason, my form action was changing from

/controller/edit/1
to
/controller/add

it was making me go crazy!

After seaching around (finally) I found this: https://trac.cakephp.org/ticket/5871
I came to realize that I have actually omitted the

<?= form->input('id'); ?>

from my edit view because I thought “why the hell do I need to edit the primary key?”

As it turns out, CakePHP needs a field (hidden or not) with the name ID or else it will revert to the ADD form.

Luckily though, it is smart enough to render it as a hidden field.

Google is your friend.

Tags: ,

I got asked this question during an interview last week. I think I gave a wrong answer in the interview but I decided I needed to find the correct answer! I searched and found this solution which involved bit manipulations, though I didn’t find it intuitive.

I came up with this simple solution

public class PowerOfTwo {
	public static void main(String args[]){
		for(int n=0,limit=16; n<Math.pow(2, limit);n++)
			if(isPowerOfTwo(n))
				System.out.println(n);
	}

	private static boolean isPowerOfTwo(int n) {
		double logNbase2 =  Math.log(n)/Math.log(2);	
		int logNbase2Integer = (int) (Math.floor(logNbase2));
		
		if(logNbase2-logNbase2Integer==0)
			return true;
		else
			return false;
	}
}
&#91;/sourcecode&#93;

maybe not quite as elegant as the bit hack, but I understand it!

<b>Update:</b>
Actually, I understood how the bit hack function below works:

	private static boolean isPowerOfTwoFast(int n) {
		return ((n!=0) && (n&(n-1))==0);
	}

Note that powers of two have only 1 bit set to one:

1:  000001
2:  000010
4:  000100
8:  001000
16: 010000
32: 100000

and so on, so we need to check if the number only has one bit that is set, and that the number is not 0 (because zero is not a power of two).

We can count the number of set bits (which is another interview question!), and if the number of set bits is one, then the number is a power of two. A smarter way to do it would be bitwise ANDing of the number and the number-1, and then check that the result == 0.

For example, to check that 32 is a power of 2, convert 32 to binary to be 100000, convert 31 to binary to be 011111. Bitwise ANDing of those 2 numbers would obviously result in 0.

UPDATE 2: Dear all, the code is now released under MIT license and is version controlled on github thanks to TuteC!

7/7/2009.

UPDATE: Please check this comment for a more updated example.

Component code updated on 30/4/2009, check the posted code or the download links.

I revisited the code I used to develop the old image resize component because I found a bug in the resize code. I used the resize function from the PImageComponent by Wendy and ended up with the current version I’m using at my websites:
Code download at the bottom of the post.

<?php
/*
 File: /app/controllers/components/image.php
*/
class ImageComponent extends Object
{
	/*
	*	Uploads an image and its thumbnail into $folderName/big and $folderName/small respectivley.
	* 	Also uploads a zoom cropped image into $folderName/home. You could easily modify it to suit your needs!
	
	* 	Directions:
	*	In view where you upload the image, make sure your form creation is similar to the following
	*	<?= $form->create('ControllerName',array('type' => 'file')); ?>
	

	*	In view where you upload the image, make sure that you have a file input similar to the following
	*	<?= $form->file('Image/image1'); ?>
	
	
	*	In the controller, add the component to your components array
	*	var $components = array("Image");
	

	*	In your controller action (the parameters are expained below)
	*	$image_path = $this->Image->upload_image_and_thumbnail($this->data,"name1", 573,380,80,80, "sets");
	*	this returns the file name of the result image.  You can  store this file name in the database
	*
	*	Note that your image will be stored in 3 locations:
	*	Image: /webroot/img/$folderName/big/$image_path 
	*	Thumbnail:  /webroot/img/$folderName/small/$image_path 
	*	Homepage:  /webroot/img/$folderName/home/$image_path  
	*
	*	You could easily add more locations or remove locations you don't need


	*	Finally in the view where you want to see the images
	*	<?= $html->image('sets/big/'.$furnitureSet['FurnitureSet']['image_path']);
	* 	where "sets" is the folder name we saved our pictures in, and $furnitureSet['FurnitureSet']['image_path'] is the file name we stored in the database
	

	*	Parameters:
	*	$data: the image data array from the form
	*	$maxw: the maximum width that you want your picture to be resized to
	*	$maxh: the maximum width that you want your picture to be resized to
	*	$thumbscalew: the maximum width hat you want your thumbnail to be resized to
	*	$thumbscaleh: the maximum height that you want your thumbnail to be resized to
	*	$folderName: the name of the parent folder of the images. The images will be stored to /webroot/img/$folderName/big/ and  /webroot/img/$folderName/small/
	*/	
	function upload_image_and_thumbnail($data, $maxw, $maxh, $thumbscalew, $thumbscaleh, $folderName) {
		if (strlen($data['name'])>4){ 
					$error = 0;
					$tempuploaddir = "img/temp"; // the /temp/ directory, should delete the image after we upload
					$homeuploaddir = "img/".$folderName."/home"; // the /home/ directory
					$biguploaddir = "img/".$folderName."/big"; // the /big/ directory
					$smalluploaddir = "img/".$folderName."/small"; // the /small/ directory for thumbnails
					
					// Make sure the required directories exist, and create them if necessary
					if(!is_dir($tempuploaddir)) mkdir($tempuploaddir,0755,true);
					if(!is_dir($homeuploaddir)) mkdir($homeuploaddir,0755,true);
					if(!is_dir($biguploaddir)) mkdir($biguploaddir,0755,true);
					if(!is_dir($smalluploaddir)) mkdir($smalluploaddir,0755,true);
					
					$filetype = $this->getFileExtension($data['name']);
					$filetype = strtolower($filetype);
 
					if (($filetype != "jpeg")  && ($filetype != "jpg") && ($filetype != "gif") && ($filetype != "png"))
					{
						// verify the extension
						return;
					}
					else
					{
						// Get the image size
						$imgsize = GetImageSize($data['tmp_name']);
					}

					// Generate a unique name for the image (from the timestamp)
					//$id_unic = str_replace(".", "", strtotime ("now"));
					$id_unic = $uuid = String::uuid();
					$filename = $id_unic;
					  
					settype($filename,"string");
					$filename.= ".";
					$filename.=$filetype;
					$tempfile = $tempuploaddir . "/$filename";
					$homefile = $homeuploaddir . "/$filename";
					$resizedfile = $biguploaddir . "/$filename";
					$croppedfile = $smalluploaddir . "/$filename";
					
					
					if (is_uploaded_file($data['tmp_name']))
                    {                    
						// Copy the image into the temporary directory
                        if (!copy($data['tmp_name'],"$tempfile"))
                        {
                            //print "Error Uploading File!.";
							unset($filename);
							unlink($tempfile);
                            exit(); 
                        }
						else {				
							/*
							 *	Generate the home page version of the image center cropped
							 */
							$this->resizeImage('resizeCrop', $tempuploaddir, $filename, $homeuploaddir, $filename, 886, 473, 85);
							/*
							 *	Generate the big version of the image with max of $imgscale in either directions
							 */
							$this->resizeImage('resize', $tempuploaddir, $filename, $biguploaddir, $filename, $maxw, $maxh, 85);							

							/*
							 *	Generate the small thumbnail version of the image with scale of $thumbscalew and $thumbscaleh
							 */
							$this->resizeImage('resizeCrop', $tempuploaddir, $filename, $smalluploaddir, $filename, $thumbscalew, $thumbscaleh, 75);
													
							// Delete the temporary image
							unlink($tempfile);
						}
                    }
 
                     // Image uploaded, return the file name
					 return $filename;   
		}
	}
	
	/*
	*	Deletes the image and its associated thumbnail
	*	Example in controller action:	$this->Image->delete_image("1210632285.jpg","sets");
	*
	*	Parameters:
	*	$filename: The file name of the image
	*	$folderName: the name of the parent folder of the images. The images will be stored to /webroot/img/$folderName/big/ and  /webroot/img/$folderName/small/
	*/
	function delete_image($filename,$folderName) {
		if(is_file("img/".$folderName."/home/".$filename))
			unlink("img/".$folderName."/home/".$filename);
		if(is_file("img/".$folderName."/big/".$filename))
			unlink("img/".$folderName."/big/".$filename);
		if(is_file("img/".$folderName."/small/".$filename))
			unlink("img/".$folderName."/small/".$filename);
	}
 
    function getFileExtension($str) {
 
        $i = strrpos($str,".");
        if (!$i) { return ""; }
        $l = strlen($str) - $i;
        $ext = substr($str,$i+1,$l);
        return $ext;
    }

	/*
	 * @param $cType - the conversion type: resize (default), resizeCrop (square), crop (from center) 
	 * @param $id - image filename
	 * @param $imgFolder  - the folder where the image is
	 * @param $newName - include extension (if desired)
	 * @param $newWidth - the  max width or crop width
	 * @param $newHeight - the max height or crop height
	 * @param $quality - the quality of the image
	 * @param $bgcolor - this was from a previous option that was removed, but required for backward compatibility
	 */
	function resizeImage($cType = 'resize', $srcfolder, $srcname, $dstfolder, $dstname = false, $newWidth=false, $newHeight=false, $quality = 75)
	{
		$srcimg = $srcfolder.DS.$srcname;
		list($oldWidth, $oldHeight, $type) = getimagesize($srcimg); 
		$ext = $this->image_type_to_extension($type);
		
		//check to make sure that the file is writeable, if so, create destination image (temp image)
		if (is_writeable($dstfolder))
		{
			$dstimg = $dstfolder.DS.$dstname;
		}
		else
		{
			//if not let developer know
			debug("You must allow proper permissions for image processing. And the folder has to be writable.");
			debug("Run \"chmod 777 on '$dstfolder' folder\"");
			exit();
		}
		
		//check to make sure that something is requested, otherwise there is nothing to resize.
		//although, could create option for quality only
		if ($newWidth OR $newHeight)
		{
			/*
			 * check to make sure temp file doesn't exist from a mistake or system hang up.
			 * If so delete.
			 */
			if(file_exists($dstimg))
			{
				unlink($dstimg);
			}
			else
			{
				switch ($cType){
					default:
					case 'resize':
						# Maintains the aspect ration of the image and makes sure that it fits
						# within the maxW(newWidth) and maxH(newHeight) (thus some side will be smaller)
						$widthScale = 2;
						$heightScale = 2;
						
						// Check to see that we are not over resizing, otherwise, set the new scale
						if($newWidth) {
							if($newWidth > $oldWidth) $newWidth = $oldWidth;
							$widthScale = 	$newWidth / $oldWidth;
						}
						if($newHeight) {
							if($newHeight > $oldHeight) $newHeight = $oldHeight;
							$heightScale = $newHeight / $oldHeight;
						}
						//debug("W: $widthScale  H: $heightScale<br>");
						if($widthScale < $heightScale) {
							$maxWidth = $newWidth;
							$maxHeight = false;							
						} elseif ($widthScale > $heightScale ) {
							$maxHeight = $newHeight;
							$maxWidth = false;
						} else {
							$maxHeight = $newHeight;
							$maxWidth = $newWidth;
						}
						
						if($maxWidth > $maxHeight){
							$applyWidth = $maxWidth;
							$applyHeight = ($oldHeight*$applyWidth)/$oldWidth;
						} elseif ($maxHeight > $maxWidth) {
							$applyHeight = $maxHeight;
							$applyWidth = ($applyHeight*$oldWidth)/$oldHeight;
						} else {
							$applyWidth = $maxWidth; 
								$applyHeight = $maxHeight;
						}
						$startX = 0;
						$startY = 0;
						break;
					case 'resizeCrop':
					
						// Check to see that we are not over resizing, otherwise, set the new scale						
						// -- resize to max, then crop to center
						if($newWidth > $oldWidth) $newWidth = $oldWidth;	
							$ratioX = $newWidth / $oldWidth;
						
						if($newHeight > $oldHeight) $newHeight = $oldHeight;
							$ratioY = $newHeight / $oldHeight;									
	
						if ($ratioX < $ratioY) { 
							$startX = round(($oldWidth - ($newWidth / $ratioY))/2);
							$startY = 0;
							$oldWidth = round($newWidth / $ratioY);
							$oldHeight = $oldHeight;
						} else { 
							$startX = 0;
							$startY = round(($oldHeight - ($newHeight / $ratioX))/2);
							$oldWidth = $oldWidth;
							$oldHeight = round($newHeight / $ratioX);
						}
						$applyWidth = $newWidth;
						$applyHeight = $newHeight;
						break;
					case 'crop':
						// -- a straight centered crop
						$startY = ($oldHeight - $newHeight)/2;
						$startX = ($oldWidth - $newWidth)/2;
						$oldHeight = $newHeight;
						$applyHeight = $newHeight;
						$oldWidth = $newWidth; 
						$applyWidth = $newWidth;
						break;
				}
				
				switch($ext)
				{
					case 'gif' :
						$oldImage = imagecreatefromgif($srcimg);
						break;
					case 'png' :
						$oldImage = imagecreatefrompng($srcimg);
						break;
					case 'jpg' :
					case 'jpeg' :
						$oldImage = imagecreatefromjpeg($srcimg);
						break;
					default :
						//image type is not a possible option
						return false;
						break;
				}
				
				//create new image
				$newImage = imagecreatetruecolor($applyWidth, $applyHeight);
								
				//put old image on top of new image
				imagecopyresampled($newImage, $oldImage, 0,0 , $startX, $startY, $applyWidth, $applyHeight, $oldWidth, $oldHeight);
				
					switch($ext)
					{
						case 'gif' :
							imagegif($newImage, $dstimg, $quality);
							break;
						case 'png' :
							imagepng($newImage, $dstimg, $quality);
							break;
						case 'jpg' :
						case 'jpeg' :
							imagejpeg($newImage, $dstimg, $quality);
							break;
						default :
							return false;
							break;
					}
				
				imagedestroy($newImage);
				imagedestroy($oldImage);
								
				return true;
			}

		} else {
			return false;
		}
		

	}

	function image_type_to_extension($imagetype)
	{
	if(empty($imagetype)) return false;
		switch($imagetype)
		{
			case IMAGETYPE_GIF    : return 'gif';
			case IMAGETYPE_JPEG    : return 'jpg';
			case IMAGETYPE_PNG    : return 'png';
			case IMAGETYPE_SWF    : return 'swf';
			case IMAGETYPE_PSD    : return 'psd';
			case IMAGETYPE_BMP    : return 'bmp';
			case IMAGETYPE_TIFF_II : return 'tiff';
			case IMAGETYPE_TIFF_MM : return 'tiff';
			case IMAGETYPE_JPC    : return 'jpc';
			case IMAGETYPE_JP2    : return 'jp2';
			case IMAGETYPE_JPX    : return 'jpf';
			case IMAGETYPE_JB2    : return 'jb2';
			case IMAGETYPE_SWC    : return 'swc';
			case IMAGETYPE_IFF    : return 'aiff';
			case IMAGETYPE_WBMP    : return 'wbmp';
			case IMAGETYPE_XBM    : return 'xbm';
			default                : return false;
		}
	}
	} 
?>

to use it in your controller,


<?php
class FurnitureSetsController extends AppController {

	var $name = 'FurnitureSets';
var $components = array("Image","RequestHandler");

function admin_add() {
 if (!empty($this->data)) { 
  $this->FurnitureSet->create();
   if ($this->FurnitureSet->save($this->data)) {
    // resize the image to 573x380 and create a square thumbnail 80x80
       $image_path = $this->Image->upload_image_and_thumbnail($this->data,"name1", 573,380,80,80, "sets");
    if(isset($image_path)) {
     $this->FurnitureSet->saveField('image_path',$image_path);
    }
    else {
     $this->Session->setFlash(__('The image for the set could not be saved. Please, try again.', true));
    }     

   }

 }
}

Note that you can modify the resize settings in the upload_image_and_thumbnail method.

The view..

<div class="furnitureSets form">
    <?php echo $form->create('FurnitureSet',array('type' => 'file'));?>
    <fieldset>
        <legend>
            <?php __('Add Furniture set');?>
        </legend>
        <?php
		echo $form->input('name');
		echo $form->input('country_id');
			?>
		<div class="input">
		<label for="Image/name1">Image</label>
		<?php
		echo $form->file('Image/name1', array('size' => '40'));
		?>
		</div>
		<?php
		echo $form->input('is_featured');
		echo $form->input('furniture_material_id');
		echo $form->input('furniture_category_id');
		echo $form->input('is_indoor');
		echo $form->input('is_outdoor');		
		echo $form->input('CustomerType');
	?>
    </fieldset>
    <?php echo $form->end('Submit');?>
</div>

Now as promised, the code!
30/4/2009: after modification from comments
17/7/2008: Old version

Again, thanks Wendy for your code!

I shamelessly ripped of the form designed at this excellent blog to use a somehow modified CSS structure.

The CSS button classes are customizable to allow positive/negative action buttons with different CSS images.

body{
font-family:"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif;
font-size:12px;
}

p, h1, form, button{border:0; margin:0; padding:0;}
.spacer{clear:both; height:1px;}

form.cleanform{
	margin:0 auto;
	width:400px;
	padding:14px;
	border:solid 2px #b7ddf2;
	background:#EAFFD5;
}

form.cleanform div.header {
	border-bottom:solid 1px #b7ddf2;
	font-size:11px;
	margin-bottom:20px;
}

form.cleanform div.header h1 {
	font-size:14px;
	font-weight:bold;
	margin-bottom:8px;
}

form.cleanform div.header .description {
	color: #666666;
}

form.cleanform p{
	font-size:11px;
	margin-bottom:20px;
}

form.cleanform label{
	display:block;
	font-weight:bold;
	text-align:right;
	width:140px;
	float:left;
}

form.cleanform .small{
	color:#666666;
	display:block;
	font-size:11px;
	font-weight:normal;
	text-align:right;
	width:140px;
}

form.cleanform input{
	float:left;
	font-size:12px;
	padding:4px 2px;
	border:solid 1px #aacfe4;
	width:200px;
	margin:2px 0 20px 10px;
}

/* Button main class */
form.cleanform input.button {
	float:none;
	width:125px;
	height:30px;
	text-align:left;
	line-height:20px;
	color:#FFFFFF;
	font-size:11px;
	font-weight:bold;
	
	background-color:#f5f5f5;
    border:1px solid #dedede;
    border-top:1px solid #eee;
    border-left:1px solid #eee;
	
	font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif;
    font-size:90%;
    text-decoration:none;
    font-weight:bold;
    color:#565656;
    cursor:pointer;
	
	background-position: 6px;
	background-repeat:no-repeat;
	text-indent:30px;
	
	margin: 0;
	padding: 0;
}


/* Positive button */
form.cleanform input.button.positive {
	color::#529214;	
}

form.cleanform input.button:hover.positive {
	background-color:#E6EFC2;
    border:1px solid #C6D880;
    color:#529214;
}

/* Negative button */
form.cleanform input.button.negative {
	color::#d12f19;	
}

form.cleanform input.button:hover.negative {
	background-color:#fbe3e4;
    border:1px solid #fbc2c4;
    color:#d12f19;
}

/* Button images */
form.cleanform input.button.add {
	background-image:url(add.png);
}

form.cleanform input.button.delete {
	background-image:url(delete.png);
}
<form class="cleanform" name="form" method="post" action="form.html">
		
			<div class="header">
				<h1>Sign-up form</h1>
				<p class="description">This is the basic look of my form without table</p>
			</div>
			
			<p>
				<label>Name
					<span class="small">Add your name</span>
				</label>
				<input type="text" name="name" id="name" />
			</p>
			
			<p>
				<label>Email
					<span class="small">Add a valid address</span>
				</label>
				<input type="text" name="email" id="email" />
			</p>
			
			<p>
				<label>Password
					<span class="small">Min. size 6 chars</span>
				</label>
				<input type="password" name="password" id="password" />
			</p>
			
			<div style="float:right">
				<input type="submit" name="submit" class="button positive add" value="Sign-up" />
				<input type="submit" name="submit" class="button negative delete" value="Cancel" />
			</div>
			
			<div class="spacer"></div>
			
		</form>

Download here

Tags: , ,

I made up this solution inspired by the post and comments on this excellent blog

<a href="#" class="button add">Add</a>
<a href="#" class="button delete">Delete</a>
a.button{
	display:block;	
	background-position: 6px;
	background-repeat:no-repeat;
	font-weight:bold;
	font-family: Trebuchet MS, Tahoma, sans-serif;
	font-size: 0.7em;	
	text-decoration:none;
	text-indent:30px;
	color:#555555;
	background-color:#EAEAD7;
	border:#CCCCCC solid 1px;
	height:30px;
	width:190px;
	line-height:30px;
}
	
a:hover{
	background-color:#F3F3E9;
	color:#737373;
}

.add {
	background-image:url(add.png);
}

.delete {
	background-image:url(delete.png);
}

any idea how can I put those buttons next to each other instead of below each other?
I tried removing the display:block from the but the button collapsed!

Update:
If you want to align the buttons next to each other, add

float:left;

to the CSS class of a.button, thanks to Stephan!

Download here

Tags: , ,

Ahmed Sabbour's Facebook profile
August 2017
S M T W T F S
« Jul    
 12345
6789101112
13141516171819
20212223242526
2728293031  

Tweets

RSS StackOverflow

Recently bookmarked