Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Wednesday, September 26, 2012

JavaScript date time localization e.g. central time to other time zone

Recently I had a requirement of doing JavaScript time localization. Problem statement goes like this-

"We have some data in central time (CST) in database. This data is basically a Gantt chart data. The database date time entry is there as CST because of the business lies in that region and there are many other business requirements. This data is presented as Gantt chart in web and people from many countries can see the chart and each one should see the data in their own localized time."

I have searched in web and could not get a direct content to the problem. So, thought to share the approach I have followed. We can solve this problem by following steps-
  1. Convert the source time to UTC time.
  2. And convert the UTC time to destination time.
Now for we need to be careful that whether the time zone has daylight-saving. As stated previously our source data in CST which is -06:00(offset) hours compared to UTC. In case of daylight saving its -05:00 hours. Let’s take a time 09/24/2012 14:00:00, this is a CST time. In this case the date falls under daylight-saving.

Now we need to get two things about the source system: - first- Date offset and second- is daylight-saving. As my IIS where the application is hosted is in CST time zone, we can get this information from application start event. Here I have decided to write the information to an xml file in the following format-
<TimeLocalization>
    <TimeOffset>-6.0</TimeOffset>
    <IsDayLight>True</IsDayLight>
</TimeLocalization>
So, in the Application_Start we can get this information.
XmlTextWriter myXmlWriterTime = new XmlTextWriter("file path", null);
myXmlWriterTime.Formatting = Formatting.Indented;
myXmlWriterTime.Indentation = 4;
myXmlWriterTime.WriteStartElement(Constants.TimeLocalization);
myXmlWriterTime.WriteElementString(Constants.TimeOffset, (DateTime.Now- DateTime.UtcNow).TotalHours.ToString());
myXmlWriterTime.WriteElementString(Constants.IsDayLight,DateTime.Now.IsDaylightSavingTime().ToString());
myXmlWriterTime.WriteEndElement();
myXmlWriterTime.Close();
In case of time offset it will always return -6.0 for CST now if the daylight-saving is true we need to add 1 resulting -5.0.

In the page load of the page where I am showing the Gantt chart, just doing a synchronous ajax call to read the value in JavaScript object like below-
$.ajax({
    type: "GET",
    url: "TimeOffset.xml",
    dataType: "xml",
    async: false,
    success: function (xml) {
        document.TimeOffset = parseFloat($(xml).find('TimeOffset').text());
        if ($(xml).find('IsDayLight').text() == "True")
            document.TimeOffset = document.TimeOffset + 1;
    },
    error: function () {
        alert("An error occurred while processing XML file.");
    }
});
Here it’s a specific case of CST. I have not tested where there is any time zone that needs a subtraction by 1.

I have created a function that will take a CST time and it will convert it to any time. In my case I am running the function from Indian time zone IST (+05:30). It goes like-
var cstArr;
function ConvertCSTTolocal(dateString) {
    //09/24/2012 14:00:00 CST
    debugger;
    cstArr = dateString.split(" ")[0].split("/");
    cstArr.push(dateString.split(" ")[1].split(":"))
    tmpDate = new Date(cstArr[2], parseInt(cstArr[0], 10) - 1, cstArr[1], cstArr[3][0], cstArr[3][1], cstArr[3][2]);
    tmpDate.setMinutes(tmpDate.getMinutes() - parseFloat(document.TimeOffset) * 60);

    tmpDate = tmpDate.toString().split(" ");
    tmpDate = tmpDate[0] + ", " + tmpDate[2] + " " + tmpDate[1] + " " + tmpDate[5] + " " + tmpDate[3] + " UTC";
    return new Date(tmpDate);
}
Now lets pass the input date to the function and see how the function goes. Our input is 09/24/2012 14:00:00 in CST. Lets investigate step by step-

Step1-
cstArr = dateString.split(" ")[0].split("/"); cstArr.push(dateString.split(" ")[1].split(":"))

With these lines we are simply splitting the date string in year, month, day, hours, minutes, and seconds. And it looks like-


Step2-
tmpDate = new Date(cstArr[2], parseInt(cstArr[0], 10) - 1, cstArr[1], cstArr[3][0], cstArr[3][1], cstArr[3][2]);

With these lines we are just passing the values to JavaScript Date function to create a date object. As I am in IST (+05:30) the resulting date is not the date as I have passed as input-



If you check the above date you can see it the same date and time as I have passed but UTC+05:30 is appended. Which means it’s the same time but in Indian time. If we convert this time to CST it will not be the same as passed input. But that’s not our intention. Our intention is to create a date and just add the offset to get the modified date and time.

Step3-
tmpDate.setMinutes(tmpDate.getMinutes() - parseFloat(document.TimeOffset) * 60);

With this line we are just negating the time zone offset of the central time (CST) to get the new time. Is it really giving the UTC time? Answer is no as explained earlier.

Step 4-


In the above image we can see the added time which is correct time with wrong offset. If we convert the input time 09/24/2012 14:00:00 to UTC, it will be 09/24/2012 19:00:00 in UTC time ( +5) considering daylight-saving. So, the problem is with the offset. If we see the UTC equivalent of the time using toUTCString method then we can see the UTC representation is coming like "day, date month year hour:min:sec UTC".

Step 5-
As the data are same except the time offset, we can prepare a UTC equivalent string from tmpDate like below-

tmpDate = tmpDate[0] + ", " + tmpDate[2] + " " + tmpDate[1] + " " + tmpDate[5] + " " + tmpDate[3] + " UTC";

this results the following-



This is the correct UTC value. Now if we pass this UTC string to a Date() function, it will result correct value for the current time zone. For example if we run this code in IST it will result the following-



Which is exactly the same value of we convert 09/24/2012 14:00:00 CST time to IST.

That’s it, problem solved.

Friday, September 14, 2012

Run a JavaScript function after asp.net client side validation is successful

There are some scenarios where we need to call some JavaScript code after the client side validation is successful and before the page is post back. We can do it easily. In asp.net while client validation it assigns a JavaScript variable Page_IsValid. If the validation is successful then it assign true else assign false. So we can trap the value of the variable to do your code execution. Hence let’s have the following code-
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>

    <script src="scripts/jquery.js" type="text/javascript"></script>
    <script type="text/javascript">
    function call(){
         if(Page_IsValid)
         {
            alert("alert page is value");
         }    
    }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="Required"
            ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="call();" />
    </div>
    </form>
</body>
</html>
But this code will not work. Reason is that the client click gets called before the page validation. We can solve this by two ways-

First-

In the above code we can explicitly call the client validation code. To do this we will just modify the call() JavaScript function like below-
    function call(){
        Page_ClientValidate();
         if(Page_IsValid)
         {
            alert("alert page is value");
         }    
    }
Here Page_ClientValidation() is explicitly calling the client validation. After this function is executed the value of Page_IsValid will get set to true /false. So, we are checking whether client validation is successful. If so call the alert method. We can replace this with our desired code.

Second-

After the client validation is done container form submit event is fired. We can trap the JavaScript submit event and do the same logic. For that let’s remove the OnClientClick from the button and then have the following JavaScript code-
    <script src="scripts/jquery.js" type="text/javascript"></script>
    <script type="text/javascript">
    $(document).ready(function(){
        $("#Button1").closest("form").submit(function(){
            if(Page_IsValid)
             {
                alert("alert page is value");
             }    
        });
    });
    </script>
And it’s done.

Sunday, September 2, 2012

Check whether a function is registered or not to an event in JavaScript

This is a small and simple post to check whether a JavaScript function is registered to an event of a DOM element. For this example we will take a button and click event. We will associate two functions and then will check whether one a function is attached or not.

We will do this using getAttribute method of a DOM element to get the value of onclick attribute. Code goes like below-
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <script type="text/javascript">
       function handlerFunction1() {
          alert("1");
      }
      function handlerFunction2() {
          alert("2");
      }
      function fn() {
           var functionArray = document.getElementById("test").getAttribute("onclick").split(",");
     for(var i=0; i<functionArray.length; i++)
     {
    if(functionArray[i].indexOf("handlerFunction1()")>=0)
     alert("function fn1() is registered with click me function");
     }
      }

  </script>
<title>
 </title></head>
<body>
    <form method="post" action="about show error message.aspx" id="form1">
    <input onclick="handlerFunction1(), handlerFunction2()" value="click me" type="button" id="test" />
    <a onclick="fn()" href="#">check fn1() is registered with click button</a>
    </form>
</body>
</html>
Now what if the event handlers are added dynamically with addEventListener/attachEvent, in that case the value of document.getElementById("test").getAttribute("onclick") will be null even if there are two functions registered to the event.

That reminds me some attribute or function like eventListenerList. But most of the browser does not support this now. It’s still a recommendation; you can check this here-

http://www.w3.org/TR/2001/WD-DOM-Level-3-Events-20010823/events.html#Events-EventListenerList

But we can implement something like below-
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <script type="text/javascript">
       function handlerFunction1() {
          alert("1");
      }
      function handlerFunction2() {
          alert("2");
      }
      function fn() {
           var functionArray = document.getElementById("test").getAttribute("onclick");
     if(functionArray!=null)
    functionArray=functionArray.split(",");
     else
     {
    if(document.getElementById("test").eventListenerList!=null)
    functionArray= document.getElementById("test").eventListenerList["click"];
     }
     
     for(var i=0; i<functionArray.length; i++)
     {
    if(functionArray[i].indexOf("handlerFunction1()")>=0)
     alert("function fn1() is registered with click me function");
     }
      }
   function addEventHandler(elem,eventType,handler) {
  if(elem.eventListenerList==null)
   elem.eventListenerList=new Object();
  if(elem.eventListenerList[eventType]==null)
   elem.eventListenerList[eventType]=new Array();
  elem.eventListenerList[eventType].push(handler);
   if (elem.addEventListener)
    elem.addEventListener (eventType,handler,false);
   else if (elem.attachEvent)
    elem.attachEvent ('on'+eventType,handler); 
   }
   window.onload=function(){
  var btn= document.getElementById("test");
  addEventHandler(btn,"click",handlerFunction1);
  addEventHandler(btn,"click",handlerFunction2);
   }
  </script>
<title>
 </title></head>
<body>
    <form method="post" action="about show error message.aspx" id="form1">
    <input value="click me" type="button" id="test" />
    <a onclick="fn()" href="#">check fn1() is registered with click button</a>
    </form>
</body>
</html>
Following is a running snap shot.

Wednesday, June 13, 2012

Replace smiley code with images in a chat application in JavaScript

Many application supports adding smiley. In the text area, used for typing, we enter some text code like :) and on enter we can we can see in the history of chat this gets converted to smiley image. We can implement this by-
<script type="text/javascript">
    var replacement = { ":)": "<img src='smiley1.png' />", ":(": "<img src='smiley2.png' />", ":-)": "<img src='smiley3.png' />" };
    var string = ":) is a smily where :( another. :-) is one more";
    string = escape(string);
    for (var val in replacement)
        string = string.replace(new RegExp(escape(val), "g"), replacement[val]);
    string = unescape(string);
</script>
Special characters are not properly recognized in this case. That why escape and unescape is used.

Monday, January 24, 2011

Restricting to floating point number onkeypress

Very simple JavaScript code to restrict text box to have floating point number. Code is here-

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <title>Untitled Page</title>
 <script type="text/javascript">
     function restrict(val, e) {
         var keyChar;
         if (window.event)
             keyChar = String.fromCharCode(window.event.keyCode);
         else if (e)
             keyChar = String.fromCharCode(e.which);
         else
             return true;
         var number = parseFloat(val + keyChar);
         if (number != val + keyChar)
             return false;
         else
             return true;
     }
</script>
</head>
<body>
 <input name="number" onkeypress="return restrict(this.value, event)">
</body>
</html>

Wednesday, December 1, 2010

JSON to HTML table

There was a need to converting JSON object to HTML Table. I found out different solutions over internet. But there was no generic solution where I can pass a JSON string and get the HTML table in return. So, I tried out a solution with JavaScript. The code is as follows-

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="form1">
<div id="test">
</div>
<script type="text/javascript">
var table = "[{'Country':'mycity','Name':'abc','Age':'29','Email':'test@mail.com'}," +
"{'Name':'abcd','Age':'39','Email':'test1@mail.com'}," +
"{'Name':'abcde','Age':'30','Email':'test2@mail.com'}," +
"{'Age':'30','Sex':'male','Name':'abcde'}]";
table = eval('' + table + '');
var tableObject = function (json) {
var headerCount = new Object();
var createTR = function (id) {
var tr = document.createElement("tr");
tr.ID = id;
return tr;
};
var createTH = function (html) {
var th = document.createElement("th");
th.innerHTML = html;
return th;
};
var createTD = function (html) {
var td = document.createElement("td");
td.innerHTML = html;
return td;
};
var getName = function (id) {
for (var name in headerCount) {
if (eval("headerCount." + name) == id) {
return name;
}
}
};
var pTable;
if (json.length > 0) {
var index = 0;
pTable = document.createElement("table");
var head = createTR();
for (var i = 0; i < json.length; i++)
for (var item in json[i]) {
if (!headerCount.hasOwnProperty(item)) {
head.appendChild(createTH(item));
eval('headerCount.' + item + "=" + index);
index++;
}
}
pTable.appendChild(head);
for (var i = 0; i < json.length; i++) {
var row = new createTR(i);
for (var j = 0; j < index; j++) {
var name = getName(j);
if (eval("json[" + i + "].hasOwnProperty('" + name + "')")) {
row.appendChild(createTD(eval('json[' + i + '].' + name)));
}
else
row.appendChild(createTD(''));
}
pTable.appendChild(row);
}
}
return pTable;

};
var c = new tableObject(table);
document.getElementById("test").appendChild(c);
</script>
</form>
</body>
</html>

Wednesday, November 3, 2010

HTML MULTI SELECT - maintain multiple selection state without Control Key.

Problem Description:
Recently I had a problem with MULTISELECT. The default behavior of MULTISELECT is that when we need to select multiple items at a time, either we need to press control key and then by mouse click select multiple item or by mouse drag. My problem was to maintain the previously selected item without the help control key.

Solution:
A simple jQuery code serves this purpose as follows



I have used ID selector. But we can use any kind of selector of our choice.