Monday, October 29, 2007

ALPopup, A DHTML Popup

One of my web projects required the implementation of a dynamic HTML popup. Taking all the possible requirements in mind I have implemented a very cool (in my opinion) DHTML popup encapsulated in a javascript object model named ALPopup (AL stands for Ahmad Lafi).

You can create ALPopups with both fixed and percent width and height. The popup can also be resized and repositioned when linked to the browser resize and scroll events. It is also tested on IE7 and Firefox 2.

Find following a live demo for ALPopup.

You may also download the sample here.

Sunday, April 22, 2007

DHTML Color and Opacity Picker

I have once faced a situation where I had to implement a DHTML color picker with ability to select both color and opacity. I searched the Internet for samples, articles, and tutorials to help me start with this task, I found too many color pickers, some of them were free, others were commercial, and many of them came with good tutorials, but unfortunately, I didn't find any picker with opacity selection feature. So I decided to go on with the implementation myself and build it from scratch.

I will not describe every detail here; I would rather show all the features and explain how to use the picker in your HTML page.

The color and opacity picker will be shown on your page as a floating IFRAME with absolute positioning adjacent to the triggering element, which is the element that should be clicked in order to open the picker. See the picture below:


Adding the Color and Opacity Picker to Your HTML Page

To add the color and opacity picker to your page, you need the following files to reside within the same directory level:
• uc_ColorPicker.htm
• sok.gif
• scancel.gif
• opcty_haft.gif
• opcty_bg.gif
• niceearth2.gif

You may download these files from the following link:
http://www.kanimani.com/3/Color_And_Opacity_Picker_Sample.zip

We will start by adding the color and opacity picker IFRAME to your page, see the line below:

<iframe id="frmColPick" src="uc_colorpicker.htm" style="display: none"></iframe>

Place it anywhere in your page within the body tags. Note that the IFRAME has "display:none" CSS attribute so it will not be visible by default.

As you can see from the picture above, I have placed two examples for different usages of the color picker. The first example will write two values in the available text boxes, one for the chosen HTML color, and the other for the chosen opacity. The opacity is denoted by a number from 0 to 100 where 0 is completely transparent, and 100 is completely opaque. See the code below:

<input id="txtColor" name="txtColor" type="text" readonly="readonly" /> <input
id="txtOpacity" name="txtOpacity" type="text" readonly="readonly" /> <input
id="btnShow" type="button" onclick="document.getElementById('frmColPick').contentWindow.AttachPicker('txtColor','txtOpacity','btnShow')"
value="Show Opacity And Color Picker" />


The code above shows two read-only INPUT elements and a button. When clicking the button, the color and opacity picker will be attached to that button and shown adjacent to it. The "AttachPicker" method of the color picker IFRAME accepts three arguments, the first one is the id for the INPUT element that will receive the color value, the second one is the INPUT element id that will receive the opacity value, and the third argument is the id of the element that will have the picker shown adjacent to it.

Note that you may set initial values for the picker by assigning initial values to the INPUT elements.

The second example shows how the targeted text box CSS attributes can be modified according to the selected opacity and color. See the code below:

<div style="cursor:pointer" onclick="document.getElementById('frmColPick').contentWindow.AttachPicker('hidColor','hidOpacity','txtColor2')"><input type="hidden" id="hidColor" name="hidColor" onchange="document.getElementById('txtColor2').style.backgroundColor=this.value" value="#E0C0C0" /> <input type="hidden" id="hidOpacity" name="hidOpacity" onchange="document.getElementById('txtColor2').value='Opacity: '+this.value" value="34" /> <input id="txtColor2" name="txtColor" type="text" readonly="readonly" style="background-color:#E0C0C0" /> <img src="color_picker.gif" /> </div>


I have placed all the elements within a DIV and attached the picker to it. The container DIV will call the "AttachPicker" method on the click event. As you can see I have replaced the two INPUT text elements with INPUT hidden elements. I have also implemented the "onchange" event of the hidden fields to carry out any action upon color and opacity selection.

Here in this example upon color and opacity selection I modify the text box background color and set its value to the selected opacity. Remember always to implement the "onchange" event when you want to customize the action taken after color and opacity selection. Doing so will allow you to design the picker user interface on your page the way you like.

This picker should work smoothly on IE7 and Firefox 2. Enjoy it!

Saturday, March 31, 2007

Frameset Synchronization

You can see that most of the Web developers are escaping from using framesets in their designs to apply the approach of one page per view. This is due to many cons, but one issue is more important than the others is the problem of multi-frame synchronization. This can be explained by a certain frame setting or getting attributes from another frame.


For example the Yahoo mail in the late 90's was using framesets for their user interface. After that in the early 2000 till 2006 they changed to the one page per view approach. Now till the days of this article we can see that they are AJAXifying their mail portal and they are back again to the multi-frame approach.


What I want to tell here that multi-frame design is so good to be let behind and there are many ways to overcome the difficulties. And here we are going to put a simple framework for safe communication in a multi-frame environment.


To demonstrate the idea, I will give an example of a frameset that has three frames: top, left, and right. See the picture below:


Following is the HTML source for the frameset page:

<frameset rows="100,*" >
<frame name="top" src="top.htm" />
<frameset cols="300,*" >
<frame name="left" src="left.htm" />
<frame name="right" src="right.htm" />
</frameset>
</frameset>


The top frame will have three buttons named: Red, Yellow, and Green. Clicking any of these buttons should change the background color of the right frame to the same color mentioned on that button.

The right frame has a text box and a button. Clicking that button will set the text in the blue area within the left frame to the same text entered in the text box.

As you can see what we have is a frameset with three simple child frames. Following the HTML source for each frame:

"Top.htm":

<h3>Top Frame</h3>
<input type="button" value="Red" />
<input type="button" value="Yellow" />
<input type="button" value="Green" />

"Left.htm":

<h3>Left Frame</h3>
<div>Text from the right frame will go here:</div><br />
<textarea id="txtArea" style="background-color:#E0E0FF" readonly></textarea>


"Right.htm":

<h3>Right Frame</h3>
<input id="txtInputBox" type="text" size="60" /><br /><br />
<input type="button" value="Set The Text On The Left Frame" />


I will start now by adding the JavaScript required to implement the normal behavior for the actions described above.

In top frame just before the closing tag of the "body" element, I have added a script section with the following JavaScript function:

<script language="javascript">
function setRFBGClr(clr)//Set right frame background color
{
window.parent.frames["right"].document.body.style.backgroundColor=clr
}
</script>


As you can see, this function will access the "right" frame directly from the parent page (the frameset) and set the body background color. Now on each button within the top page I have implemented the "onclick" event by adding the following script respectively:

...value="Red" onclick="setRFBGClr('#FF0000')" />
...value="Yellow" onclick="setRFBGClr('#FFFF00')" />
...value="Green" onclick="setRFBGClr('#00FF00')" />


Now within the right frame I will add the required JavaScript to implement the second feature for setting the text on the left frame. By adding the following script section just before the closing tag of the body element on the right frame:

<script language="javascript">
function setLFText(txt) //Set left frame text
{
window.parent.frames["left"].document.all.txtArea.value=txt;
}
</script>


This function accesses the left frame directly and applies a new value to the text area element. I have also implemented the "onclick" event on the button within the right frame passing the value of the text box to the JavaScript function:

<input type="button" value="Set The Text On The Left Frame" onclick="setLFText(txtInputBox.value)" />

The Problem:

Until now, running the sample will get everything to work fine or at least as it appears so. Where is the problem then? Suppose that you have a slow Internet connection and that the left frame is heavy loaded with HTML contents, which will take some time till the page is loaded completely. During this time, as we assumed, the left frame will not be ready to accept direct communication from other frames, and that will yield some scripting errors every time you try to set the left frame text from the right frame.

If you think this is not a real problem and most probably you won't encounter it during the normal navigation on your Website; imagine that you are implementing a mailing system, something heavy like Gmail or the new Yahoo mail AJAXfied interface. A lot of operations are involved and many processes run in the background while you are navigating, typing, or just reading your mail. This huge and complicated infrastructure requires a decent synchronization between different frames and different pieces of scripts. In similar situations the direct access to frames within the same frameset is no more a robust way.

What we are going to do about that is to implement a safe frameset communication framework, sounds complicated but it is really simple, let's see how:

The parent page (the frameset page) will be the maestro page; it will receive and dispatch jobs from and to all child frames. This comes from the fact that it is the first page loaded before all the child pages and it always will be ready to be accessed.
First I will start by adding the following script to the parent page "frameset.htm" (note that for this script to work fine, it should be placed within the "head" tag):

<script language="javascript">
//Message Id's
var MSG_SET_BG_COLOR = 1
var MSG_SET_TA_TEXT = 2
//Message Queue object
var MessageQueue = new CMessageQueue();
function CMessageQueue()
{
var Q = new Array();
this.nextMessage=function(){
if(Q.length<=0)
return null;
return Q.shift();
}
this.postMessage=function(Message){
Q.push(Message);
}
}
</script>

We have here a JavaScript class called "CMessageQueue" and an object of that class called "MessageQueue". This class is actually a wrapper over an array object with two methods exposed: "nextMessage()" will remove and return the first object in the array, while "postMessage()" will append a new object to the array.

We will use "MessageQueue" to post commands from the child frames to the parent frame which on its turn will work as a source of commands to other child frames. Notice also the message id's which will be used to identify messages on the child pages.

The following script will be added to all the child frames ("left.htm", "right.htm", and "top.htm"):

window.setInterval(function(){HandleMessageQueue()},600);
function HandleMessageQueue()
{
var msg;
var arrRet=new Array();
while(msg = window.parent.MessageQueue.nextMessage())
{
switch(msg.Command)
{
default:
arrRet.push(msg);
break;
}
}
for(var i=0;i<arrRet.length;i++)
window.parent.MessageQueue.postMessage(arrRet[i]);
}

"HandleMessageQueue()" function iterates on all the messages within the message queue and handles only those targeted to this frame. As you can see under the "default" keyword within the "switch" statement, all the messages that are not targeted to this frame will be pushed back to the message queue to be handled somewhere else.
You may see also that "HandleMessageQueue()" function is set to be called periodically within intervals of 600 milliseconds. You may change this interval to best fit your case.

In the following last steps I will do some modifications on each page so it can accept the new commands and behave exactly the same way as was with the direct frame communication.

For the left frame we will add the following script to the switch statement:

case window.parent.MSG_SET_TA_TEXT:
document.all.txtArea.value=msg.value;
break;

For the right frame we will add the following script to the switch statement:

case window.parent.MSG_SET_BG_COLOR:
document.body.style.backgroundColor=msg.value;
break;

For the right frame also we will modify the function "setLFText(txt)" as following:

function setLFText(txt)//Set left frame text
{
window.parent.MessageQueue.postMessage(new function()
{
this.command=window.parent.MSG_SET_TA_TEXT;
this.value=txt
});
}

For the top frame we will modify the function "setRFBGClr(clr)" as following:

function setRFBGClr(clr)//Set right frame background color
{
window.parent.MessageQueue.postMessage(new function()
{
this.command=window.parent.MSG_SET_BG_COLOR;
this.value=clr
});
}

Now if you run the frameset page in the browser you will notice that everything is working exactly as with the old direct method but with a slight neglectable delay after any request to a certain command (you may control this delay by reducing the interval milliseconds for calling the "HandleMessageQueue()" function).

Downlod the complete source code:
http://www.kanimani.com/2/Frameset_Safe_Communication.zip

Conclusion:

Using message queue for synchronizing communication between different frames will always be safer and you don't have to worry which frame is loaded first. And if a certain frame is not ready for receiving requests, the message will keep cycling until this frame is ready.

Thursday, March 15, 2007

DHTML Auto Resizing List

I really had very tough time selecting a name for this post... Why? Because I am writing here about a very special type of dynamic lists.

This list increases/decreases the number of its rows to best fit the browser height. If the list has a small number of rows, they will all be visible within the browser view. But if you resized the browser until the list cannot fit anymore within the view, some rows from the list tail will disappear and a link of 3 dots (. . .) will appear in place of the last row to tell us that not all of the rows are shown.

Clicking on a row will fire a message box showing the content of that row, you may replace the javascript that shows the message box with any scripting you want. Also clicking the 3 dots indicator will fire another message box that you can replace with some script to show a new window with all the rows visible, or just disabling the resizing functionality.


The sample should work fine with IE7 and FireFox 2.0, let me know if you had any problems running it on your browser.

View it online
Download it:
http://www.kanimani.com/1/auto-resize.zip

My First Post

Hello everybody!

Finally I decided to start my own blog. It really doesn't matter if it was a blog or something else, all what I wanted is some space on the Internet to share my ideas and post some samples of my work. Hopefully this will contribute back to the Internet which I always consider my inspiring source and well of knowledge.

This blog will be mostly more professional than social. I will concentrate on posting technical issues regarding to my field of work - Software Development of course.

Pray for me to always have enough time and enthusiasm to keep posting on this blog.