Drawing A Line Between Two Draggable DIVs

Drawing a line between 2 moving DIVs can be tricky sometimes. It involves a little bit of Mathematical knowledge and a few jQuery plugins.

Demo: http://kennykee.com/demo/draw-line/

Drawing A Line Between Two Draggable DIVs

screenshot

The code:

<!DOCTYPE HTML>
<html>
<head>
	<script src="jquery-1.9.1.min.js" type="text/javascript"></script>
	<script src="jquery-ui.js" type="text/javascript"></script>
	<script src="jQueryRotateCompressed.2.2.js" type="text/javascript"></script>
	<style>
		.box{
			width: 100px;
			height: 100px;
			border: solid thin black;
			position: absolute;
			cursor: pointer;
			-webkit-border-radius: 10px;
			-moz-border-radius: 10px;
			border-radius: 10px;
			-webkit-box-shadow:  3px 3px 2px 2px rgba(1, 1, 1, .3);
			box-shadow:  3px 3px 2px 2px rgba(1, 1, 1, .3);
			text-align: center;
			font-weight: bold;
			color: black;
			padding-top: 5px;
			font-family: Verdana;
		}
		.box1{
			background-color: green;
		}
		.box2{
			background-color: yellow;
		}
		#line{
			width: 100px;
			height: 10px;
			border: solid thin red;
			position: absolute;
			background-color: red;
			-webkit-border-radius: 10px;
			-moz-border-radius: 10px;
			border-radius: 10px;
		}
		.kennykee-styles{
			font-size: 20px; 
			font-family: Arial; 
			margin: 10px; 
			font-weight:bold;
		}
	</style>
	<script type="text/javascript">
		var boxCenterXOffset = 50;
		var boxCenterYOffset = 50;

		$(document).ready(function(){
			$(".box").draggable({ delay: 0, distance: 0 },{
				drag: function(event, ui){
					var x1 = $("#box1").offset().left + boxCenterXOffset;
					var x2 = $("#box2").offset().left + boxCenterXOffset;
					var y1 = $("#box1").offset().top + boxCenterYOffset;
					var y2 = $("#box2").offset().top + boxCenterYOffset;

					var hypotenuse = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
					var angle = Math.atan2((y1-y2), (x1-x2)) *  (180/Math.PI);
					if(angle >= 90 && angle < 180){
						y1 = y1 - (y1-y2);
					}
					if(angle > 0 && angle < 90){
						x1 = x1 - (x1-x2);
						y1 = y1 - (y1-y2);
					}
					if(angle <= 0 && angle > -90){
						x1 = x1 - (x1-x2);
					}

					$("#line").queue(function(){
						$(this).offset({top: y1, left: x1});
						$(this).dequeue();
					}).queue(function(){
						$(this).width(hypotenuse);
						$(this).dequeue();
					}).queue(function(){
						$(this).rotate(angle);
						$(this).dequeue();
					});

					$("#gx").html(x1);
					$("#gy").html(y1);
					$("#yx").html(x2);
					$("#yy").html(y2);
					$("#lx").html($("#line").offset().left);
					$("#ly").html($("#line").offset().top);
					$("#degree").html(angle);
				}
			});
		});

	</script>
</head>
<body>
	<div class="kennykee-styles"><a href="http://kennykee.com">KennyKee Styles</a></div>
	<div id="box1" class="box1 box">Drag Me</div>
	<div style="margin-bottom: 100px;"> </div>
	<div id="box2" class="box2 box">Drag Me</div>
	<div style="margin-bottom: 100px;"> </div>
	<div id="line"></div>
	<div style="margin-bottom: 100px;"> </div>

	Green Box: X=<span id="gx"></span> Y=<span id="gy"></span><br />
	Yellow Box: X=<span id="yx"></span> Y=<span id="yy"></span><br />
	Line Box: X=<span id="lx"></span> Y=<span id="ly"></span><br />
	Degree = <span id="degree"></span> <br />
</body>
</html>

Some explanation:
1) First, we have 3 divs. 2 divs will be the draggable objects. The 3rd div will be the “line” connecting these 2 divs.

2) During dragging process, the line div is positioned at the center of first draggable object. Note that “center” means offset of first draggable object plus (+) half the width of draggable object.

3) Next, we have to get the distance between the draggable divs by using hypotenuse formula between 2 points. Set the width of the line div as the distance between the 2 draggable divs.

4) Finally, we have to calculate the angle between the two draggable divs. We can get the angle by using arctangent formula. In JavaScript, we can use Math.atan2(). Set the rotation degree of the line div using this angle.

Note that arctangent has a value between 180° and -180º. Hence, we use the method below to shift the line div to correct position.

if(angle >= 90 && angle < 180){
						y1 = y1 - (y1-y2);
}
if(angle > 0 && angle < 90){
						x1 = x1 - (x1-x2);
						y1 = y1 - (y1-y2);
}
if(angle <= 0 && angle > -90){
						x1 = x1 - (x1-x2);
}

And now we have one line drawn between 2 draggable divs.

Demo: http://kennykee.com/demo/draw-line/

DIV 100% Width Without Horizontal Scroll Bar

When a DIV is set to have 100% width,  you may see horizontal scroll bar appearing. This is due padding, margin and type of position.

To make a DIV with 100% width without horizontal scroll bar appearing, try the following:

1) Set the DIV position type to fixed. Suitable for DIV to be used as a fixed position header.

.div_header{
	height: 30px;
	border-color: black;
	top: 0px;
	width: 100%;
	position: fixed;
}

2) Let the DIV position type to be default. Width = auto. This is the simplest method. Remove left and right margins.

.div{
 	height: 30px;
	border-color: black;
 	width: auto;
 	margin-left: 0px;
	margin-right: 0px;
}

3)  Set the DIV position type to relative. Width = 100%. Remove border, margin and padding for both left and right of the DIV. Any padding or margin will cause horizontal bar to appear.

.div{
	height: 30px;
	border-color: black;
	position: relative;
 	margin-left: 0px;
 	margin-right: 0px;
 	padding-left: 0px;
 	padding-right: 0px;
 	width: 100%;
	border: none;
}

Software Project Management Process Flow Simplified

Starting up a software development business or becoming a freelance software developer can be very confusing. One can face lots of issues such as legal contract, pricing agreement, scope creep and payment dodge. These small businesses usually has no legal binding contract and most of communication is done verbally or via simple email.

Here is the basic framework that I use for many of my clients:

Step 1 – Pricing Proposal Agreement
The first step is to understand and analyse requirements from client. Next, put all the deliverable functions into a pricing proposal (the common term for this is quotation). Ensure all functions and its itemized prices are written down in table format. Below this table, write down all the terms and conditions, and assumption if any. The final thing to do is to ensure the client sign-off the pricing proposal.

Step 2 – Upfront Payment
After the client sign-off the pricing proposal, make sure an upfront payment of 30% or 50% is received. Do not start any development until the client make the upfront payment. A client who has interest in doing business with you and appreciate your value proposition will pay promptly.

Step 3 – Functional Specification Document
If the scale of the project is large and might require more than 6 months time to deliver, then you should prepare functional specification document and workflow document (mock-up page) to describe functions to be delivered in detail. Get your client to sign-off this document.

Step 4 – Development
During development period, visit your client at least once a month to show your current progress and get feedback. In many cases, requirement changes during development phase is very common. So getting frequent feedback is important to reduce these changes in the future.

Step 5 – Installation of Application To Test Server
After completing development, user can begin testing out new application. Visit these users as frequent as once a week to get feedback. There will be some requirements or user interface changes to the application during this phase.

Step 6 – User Acceptance Test (UAT)
After few weeks time, perform UAT with your client. Ensure the client sign-off the UAT document.

Step 7 – Commissioning
After the UAT is completed, upload the new application to live server. Finally, prepare two copies of commissioning letter for the client to sign-off. One for you and the other for your client. This commissioning letter will indicate that the client has fully accepted the new application and the application is now considered fully delivered. For my case, I have added warranty period into the letter as well. So this letter can be used as warranty certificate.

Step 8 – Full Payment
Send invoice to your client requesting for remaining payable amount. Payment terms = 30 days. If payment made within first 7 days, discount 5% on remaining payable amount.

Project is now completed and closed.

Disclaimer: The flow mentioned above is for reference purpose only and may not be suitable for everyone. Please refer to Project Management Professional book for better understanding on project management skill.

 

Saving Image To Database Using PHP

Images are usually located in assets/images folder of your application. Web users can easily access your images using direct URL without logging in. If you are storing users’ uploaded images in your web server folder, someone might be able to steal your important images. For example, photo of employees.

Another issue is if you have multiple application servers running the same application to serve many HTTP request concurrently, images uploaded by users may be stored in either one of the server. Hence, when another user trying to view image uploaded, the image may appear missing. See image below.

Image Missing When Using Multiple Application Server

Image Missing When Using Multiple Application Server

There are many ways to solve this issue. Here is how I solve it. Saving the image into the database.

Summary of workflow:
Saving Image
1) Uploaded image will be saved in one of the server folder.
2) Convert the image binary string to base64 string using PHP base64_encode.
3) Store base64 string in database as longtext type.

Loading Image
4) Load base64 string containing image from database.
5) Convert base64 string to binary using PHP base64_decode.
6) Set return type header as ‘image/png‘.
7) Echo the binary data.

See sample code below.

File Upload Form:

<html>
<body>

<form action="backend.php" method="POST" enctype="multipart/form-data">
	<input type="file" name="file"/>
	<br />
	<input type="submit"/>
</form>

</body>
</html>

Backend:

<?php
if(!isset($_GET["getfile"])){
	if ($_FILES["file"]["error"] > 0){
		echo "Error: " . $_FILES["file"]["error"] . "<br>";
	}else{
		move_uploaded_file($_FILES["file"]["tmp_name"], $_FILES["file"]["name"]);
		$bin_string = file_get_contents($_FILES["file"]["name"]);
		$hex_string = base64_encode($bin_string);
		$mysqli = mysqli_init();
		if (!$mysqli->real_connect('localhost', 'root', '', 'test')) {
			die('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error());
		}
		$mysqli->query("INSERT INTO upload(image) VALUES ('" . $hex_string . "')");
	}
}else{
	$mysqli = mysqli_init();
	if ($mysqli->real_connect('localhost', 'root', '', 'test')) {
		if ($result = $mysqli->query("SELECT * FROM upload ORDER BY id DESC")){
			if($row = $result->fetch_assoc()){
				$output_hex_string = $row["image"];
				$output_bin_string = base64_decode($output_hex_string);
				header("Content-Type: image/png");
				header("Content-Length: " . strlen($output_bin_string));
				$result->free();	
				echo $output_bin_string;
			}
		}
	}
  }
?>  

<img src="backend.php?getfile=1" />

Note: The last line of code ‘<img src=”backend.php?getfile=1″ />’. Note the “src”  parameter. By using this method, we can just call a PHP function within the src tag and the browser will take the PHP output as image to display. This inline method is clean and easy to use. In addition, we can preprocess the image output or perform access control before displaying.

MySQL allows storage of binary data but I am storing it as hex string. The reason is I won’t need to handle not 8-bit clean characters or null characters that might break the code during saving process.

HTML5 WebCam With Images Overlapping

This post demonstrates the basic on how to stream webcam from your computer to Opera browser using JavaScript and overlap image on top of the stream.

If you are looking for overlapping some images on top of the real-time stream, then this post is suitable for you.

View demo here. (Please use latest Opera browser only)

Overlap-Image-With-Webcam

The Basic Method

1) Download latest Opera browser. (Unfortunately, I managed to get this demo working in Opera only)

2) Ensure your webcam has been enabled.

3) Create an HTML file with the following. This creates our video display page.

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<title>HTML5 WebCam With Images Overlapping</title>
	<meta name="author" content="KennyKee Technologies. Email: kennykee@kennykee.com">
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
	<script type="text/javascript" src="jquery.js"></script>
</head>
<body style="background-color:white; margin:0px;">
	<h1></h1>
	<div id="camera_area">
		<video height="768" autoplay style="z-index: 0"></video>
		<div id="label" style="position: absolute; z-index: 999"><img src="image.png"/></div>	
	</div>

	<script type="text/javascript">
	$(document).ready(function(){
		var video = document.getElementsByTagName('video')[0]; 
		var heading = document.getElementsByTagName('h1')[0];

		if(navigator.getUserMedia) {
			navigator.getUserMedia('video', successCallback, errorCallback);
			function successCallback( stream ) {
				video.src = stream;
			}
			function errorCallback( error ) {
				heading.textContent = "An error occurred: [CODE " + error.code + "]";
			}
		} else {
			heading.textContent = "Native web camera streaming is not supported in this browser! Please use Opera.";
		}

		//For animation purpose
		$('#label').css({left:'200', top:'200'});
		var next = false;
		var animateMe = function(targetElement, speed){
		var left = 800;
		if(next){ left = 200; next = false}else{next = true;}

		$(targetElement).animate(
				{
				'left': left
				},
				{
				duration: speed,
				complete: function(){
					animateMe(this, speed);
					}
				}
			);
		};
		animateMe($('#label'), 1000);

	});
	</script>
</body>
</html>

Download latest jQuery library and rename as jquery.js. Put this file in the same directory as the HTML file created earlier. Use this image sample. Save as image.png and put in the same directory as the HTML created earlier image.

4) Open the created HTML file with Opera. Make sure you enable webcam request access from Opera.

We are done. View demo here. (Please use latest Opera browser only)

KennyKee Styles New Website

KennyKee Styles is back on the business. Website revamp is now completed with a fresh look. This year KennyKee will be posting more types of interesting information and developing fun application.

Looking forward for support from everybody!

Thank you very much!