left-right

I created a new public repo on my GitHub page. Check it out.

Advertisements

UTC Offset regex validation

I was working on validating UTC Offset values in a javascript application and came up with this regex to do the job. What do you think?

//see http://en.wikipedia.org/wiki/List_of_UTC_time_offsets for list of valid positive and negative offsets
var positiveOffset = /^[+]?([0-9].?[0]?[0]?|1[0-4].?[0]?[0]?|[3,4,5,6,9,10,11].30|[5,8].45|12.45)$/g;
var negativeOffset = /^[-]([0-9].?[0]?[0]?|1[0-2].?[0]?[0]?|[3,4,9].30)$/g;
var GMT = /^0.?[0]?[0]?$/g;
if(!positiveOffset.test(value) && !negativeOffset.test(data.value) && !GMT.test(value)) {
    //show error
}

Closure function vs defined (named) function

I wrote a performance test on jsperf.com to measure the difference between calling a closure function from within a loop and calling a defined function within another loop for the same number of iterations. See the difference and run the test yourself.

PHP file download

So I have been working on a PHP website for a freelance job and had to write few lines of code to download a file from the database. Very simple right? Yeah that’s what I thought too. I mean it was < than 20 lines of code. Why wouldn’t it work? What could go wrong? That’s where I was wrong. This is what I had at first:

if(isset($_GET['id']))
{
  // if id is set then get the file with the id from database
  $id = $_GET['id'];
  $application = new Applications();
  $application->get($id);
  header("Content-length: $application->size");
  header("Content-type: $application->type");
  header("Content-Disposition: attachment; filename=$application->name");
  $content = $application->data;
  echo $content;
}
exit;

The problem I experienced was that a file would upload (different piece of code) fine. I knew that because the size attributes match when the file is written to the db. When I actually try to download the file back from the db using the script above, the file gets corrupted. I had no idea why! The weird (but made sense later) part was that plaintext files were fine no matter how large they were. It was binary files like images, DOCs, PDFs etc. So, I scoured the internet searching for answers and finally came across one thread somewhere where there was a similar discussion from over a year ago and someone said that the file stream would get random whitespace characters when downloading the file. Then it hit me, I remember seeing whitespace at the beginning of the stream when I had opened the corrupt file using notepad. The solution was to ob_clean() before you begin writing the headers and the content stream itself. You see one of the important points about writing header information to the client is that there shouldn’t be any whitespace before writing headers.

I modified the above code then to this:

if(isset($_GET['id']))
{
  // if id is set then get the file with the id from database
  $id = $_GET['id'];
  $application = new Applications();
  $application->get($id);
  ob_clean(); //clears output buffer in php..see php manual
  header("Content-length: $application->size");
  header("Content-type: $application->type");
  header("Content-Disposition: attachment; filename=$application->name");
  $content = $application->data;
  echo $content;
}
exit;

It would then download without any problems. At this time I should also caution you about dangling newline/whitespace in the php file itself which handles the download. The reason why plaintext files were ok is because plaintext files are not written in binary so whitespace or not it doesn’t matter for those file types and they will upload/download fine, at least in my case they did. Do you have a better way to handle this? If so, please leave a comment. Let me know about it.

canvas-charts

I just committed my first open source project on GitHub. You check it out here.

Here’s the example client with graphs:

Horizontal Bar Graph

 

Line graph

Simple validation of required fields in html5 mobile apps

I am working on an html5 mobile app and wanted a simple validation of required fields. Nothing fancy. Just a simple validation that would let the user know they left something blank. Since I was not interested in checking the format of the values entered in these fields, I felt that I should create something very generic that can be reused across platforms especially by using html5 features. A micro validation script, if I may.

So the setup is pretty easy. You need to mark your required input tags with the required attribute. Now, remember that this is an html5 attribute, so while older browsers won’t understand this it shouldn’t break anything. The next, optional, attribute to set is the data-tab-id, which when set tells validating function that it needs to mark that tab with an indication that it contains errors. This will be useful when you have data entry in multiple tabs.

<input id=”name” type=”text” placeholder=”name” maxlength=”25″ required=”required” data-tab-id=”#tab1″/>

Next is the CSS, simple, nothing extreme:

input.inputrequired{
border: 1px solid #ff0000;
}

a.haserrors{
color: #ff0000;
font-weight: bold;
}

The haserrors class is for the tab. You can change the selector for this class to match whatever tag you would have used with your tabs. Again, this is optional, you do not need to set the data-tab-id in the first place, if don’t need this and you will, in a moment, see why.

Finally, the script:

var _validateInput = function(e){
var currentTarget = e.currentTarget;
var tabId = currentTarget.dataset[“tabId”];
var tab = $(tabId);
var result = false;
if(currentTarget.required && currentTarget.value == “” && tab != null && typeof tab !== “undefined”){
$(“#” + currentTarget.id).css(“class”, “inputrequired”);
tab.addClass(“haserrors”);
}
else {
currentTarget.setAttribute(“class”, “”);
//before removing the haserrors from the tab class check if any other siblings are in error
if($(“#” + currentTarget.id).siblings(“.inputrequired”).length <= 0 && tab != null && typeof tab !== “undefined”){
tab.removeClass(“haserrors”);
}
//set result to true since this input is fine
result = true;
}
tab = null;
currentTarget = null;
return result;
};

The actual event trigger:

//validates onblur the inputs that have required attribute
$(“input”).on(“blur”, function(e){
validateInput(e);
}, false);

Although the required attribute is backward compatible, meaning no existing functionality would break, there is no need to worry about old browsers for mobile anyway. The data- attributes are an html5 addition as well. They won’t be recognized by older browsers and you cannot access the DOM string map dataset from an element in older browsers. And again, there is no need to worry about these things unless you are planning to use this for the desktop in which case you will need to replace the use of dataset with a JS framework’s data() method which provides cross-browser support.

One nice thing about the “required” attribute is that when you place fields with required attributes inside a <form> element, when the form is submitted, the browser automatically validates them and shows a nice tooltip that the a value is required for the element. I wrote this script because I wasn’t using a <form> element and don’t think the required attribute validation is supported in mobile webview at least it is not widely supported.

Optimizing HTML5 canvas drawing for high density screen

 //set the canvas size

canvasEl.style.width = this.containerWidth + “px”;

canvasEl.style.height = this.containerHeight + “px”;

// scale 2x

if(window.devicePixelRatio == 2) {

//set the actual drawing size

canvasEl.width = this.containerWidth * 2;

canvasEl.height = this.containerHeight * 2;

context.scale(2, 2);

}

On a side note, for PNGs you would do it with CSS3 media query: 

@media screen and (-webkit-min-device-pixel-ratio: 2), screen and (max–moz-device-pixel-ratio: 2) {

.your_class_name_here{

background: url(‘path_to_your_image_with_326ppi_here.png’);

width: 150px; //this is the size you actually want to scale it down to.

height: 150px; //this is the size you actually want to scale it down to.

}

}

More related articles:

http://menacingcloud.com/?c=highPixelDensityDisplays

http://blog.iwalt.com/2010/08/generating-highresolution-graphics-with-html5s-canvas-element.html

iOS Style Scroller For PhoneGap App

I have moved the files to GitHub at https://github.com/praneetloke/SpinningWheel-Wrapper

I am going to show you the extensions I made to the spinningwheel script created by the developer of the popular iScroll script. The spinningwheel script by Matteo works great just out-of-the-box. It’s much better than mobiscroll. Spinningwheel allows you to add slots of custom data which means if you are about to use spinningwheel for a date picker then you have to write your own logic for handling the days/months logic and then there’s the leap year calculation for February. But working with spinningwheel was easy and interesting. Matteo’s code is always organized as you can see from the source of his iScroll and SwipeView scripts. It was just a matter of writing down what extensions I wanted to make to his script. So, I first started out by realizing that I wanted a wrapper around the spinningwheel; that’s where the second file in the attachments comes to use. Most importantly his scripts are always written in regular javascript and always has a destroy method (which is very useful when you want to manage memory). Writing in regular javascript means no external dependencies. Following the same guidelines I too made the extensions in regular javascript and also the new events you can subscribe to in the spinningwheel are written in regular javascript. Another advantage of using spinningwheel over mobiscroll is spinningwheel uses translate3d for the transitions which means it will look and work awesome on iOS devices and even on higher end Android devices (phones and tablets). Oh and another one again is that since spinningwheel is written in regular javascript it easy for you to make extensions to it based on your needs unlike mobiscroll which relies of jQuery selectors heavily which means if you are not using jQuery, good luck!

The ScrollWheel class I wrote allows you to use the SpinningWheel instance as a singleton object. You can create an instance of ScrollWheel and pass in parameters like ‘date’, ‘time’ or ‘custom’ (if you want to use custom slots). Most of you would want to use the date and time presets that I created. The custom presets allow you to simply bind a click listener to text input and show the spinning wheel without having to do any extra work.

As you will see in the ScrollWheel.custom file, I have set the cancel action to call the post callback (which you would have passed when an instance of ScrollWheel was created) immediately and a null value for the results. In your post callback be sure to add a check for the results array so you don’t accidentally update the existing value in the text box (if any) to null. You can see what I have done with my post callback in ScrollWheel_Init.

The HTML element that you need to have to actually show the spinningwheel is pretty simple. Just use something like this (or exactly):

<input id=”timePicker” type=”text” readonly=”readonly” onfocus=”preventFocus(this)” onclick=”showTimePicker(event, this.id, this.value);”/>

or you can modify the showTimePicker function to take just the event object as a parameter and modify the click handler in the element to:

<input id=”timePicker” type=”text” readonly=”readonly” onfocus=”preventFocus(this)” onclick=”showTimePicker(event);”/>

Or you could alternatively ‘bind’ to the click event using jQuery or Zepto as well. I will not explain the logic of updateDates since it is pretty straight forward. In spinningwheel.js, you will find that I have added a new event handler that you can set via an instance of ScrollWheel (or directly via SpinningWheel) called scrollEndAction. This is what you need to set if you want to subscribe to the scrollEnd event and have a handler invoked every time the user stops scrolling a slot.

A snippet of the handleEvent function in spinninwheel where I added the invocation of the scrollEndAction

else if (e.type == ‘touchend’) {

if (e.currentTarget.id == ‘sw-cancel’ || e.currentTarget.id == ‘sw-done’) {

this.tapUp(e);

} else if (e.currentTarget.id == ‘sw-frame’) {

this.scrollEnd(e);

//console.log(“calling scroll end action”);

setTimeout($.proxy(this.scrollEndAction(this.activeSlot), this), 100);

var self = this;

setTimeout(function () {self.scrollEndAction.apply(this, [self.activeSlot]);}, 100);

}

}

There are two new public functions I have added to the spinningwheel.js, called showSlotValuesAfter and hideSlotValuesAfter. These functions will allow you to pass the slot index (0 based), the last key of the json object that the slot holds as values, and the number of values you want to show/hide after that last key. The reason for these is to help with hiding the dates that don’t apply for a particular month and then showing them again when they are applicable. Look at updateDates to understand how this is done. I have also made sure that when you call on these functions the corresponding slot’s max scroll boundary is updated so that it doesn’t allow you to scroll over the ‘hidden’ values. Find out why I call them ‘hidden’ values. 

The good thing about the wrapper I have written is that it checks if an instance of a ScrollWheel is already open and if so it won’t allow you to open another one. This was the only problem with spinningwheel out-of-the-box. SpinningWheel is a global instance and you have to manage it. If you open too many instances at the same time you are likely to chew up memory from the browser and can see significant impact to the performance of the page and even states and values will be corrupted. This is why I wrote the wrapper to make sure that I take care of this.

There is no technical reason for me to name the wrapper as ScrollWheel so you can change the name of the class to whatever you like. Just remember to retain the names and the original license at the top of the files. Although I claim no responsibility for the stability of these extensions and no support for them, I do know that they work because I use them and you can ask me for help as long as you don’t blame me for anything after all you downloaded them, I did not force you to.

A word of caution about spinningwheel’s goal. It is to be used with webkit based browsers. It was created to be used with iOS and Android phones as they implement the WebKit framework and also it is original intended to be used with touch enabled WebKit platforms which means it will not work with desktop browsers (Chrome, Safari, or Opera) out-of-the-box but there’s good news, download the touché framework I blogged about last week and it should work like a charm. I may look into porting this for the WP7 but not yet. I’ll tackle that when I get there but if you do be sure to let me know. It’ll save me some time 🙂

Be sure to ask me if you don’t understand the sources. Just don’t be a duck about it. That’s it for now. Enjoy your new spinningwheel!