Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Tuesday, August 18, 2009

for -> in loops with JavaScripts

I love for loops... don't think I could live without them! The problem with JavaScript is that you don't always have a numerically indexed array of elements that you need to loop through. These are often referred to as Associative Arrays. JavaScript simply treats them as Objects. They are VERY simple to use and usually easy to loop through... simply use the for -> loop syntax:

var fruitColorArr = {
'red':'apple',
'yellow':'banana',
'green':'lime'
};
for(var i in fruitColorArr){
alert(fruitColorArr[i]+"'s are "+i);
}

This will result in three alerts:
"apple's are red", "banana's are yellow", and "lime's are green".

Simple right? Wrong!!! There is a little problem called prototyping that can destroy this whole scenario! Let's imagine someone added the following JavaScript to their page to supplement the Object object:

Object.prototype.test = function(){alert('hi');}

It's a great feature of JavaScript and attests to it's amazing flexibility.... It gives us the power to call:

fruitColorArr.test();

And have it alert "hi".

The problem arises when you try to then run the for in loop on the fruitColorArr... We get the following alerts:

"apple's are red",
"banana's are yellow",
"lime's are green"
,
"function () {
alert("hi");
}'s are new"

Seems relatively harmless for this example, but it can be disastrous in a larger application, not to mention really hard to tack down!

So how do you work around it??? Test everything!!!

If you know the type of element you are expecting, test for it! If you are expecting a string, use the following:

for(var i in myArr){
if(typeof(myArr[i]) == 'string'){
/* loop code goes here */
}
}

If you are not sure what type of element to expect, at least test to make sure what you have is not a function.... At the very least, I use the following:

for(var i in myArr){
if(typeof(myArr[i]) != 'function'){
/* loop code goes here */
}
}

By doing this, you can be sure that no matter where your code is used, it will not cause strange behavior!

Friday, June 20, 2008

IE and another JS blunder...

So I report with great disdain, yet another problem with IE and cross browser compatibility. IE does not (by design) support the .innerHTML property correctly for elements like TABLE, THEAD, TFOOT, TR, and TBODY (even though it's not listed there). They decided for some unknown reason to be different on this topic than EVERY OTHER browser on the market.

Now, I will say, as a matter of practice, I resist the use of innerHTML as much as possible, using the DOM's document.createElement instead. I have, however, run into a case where this is not only impractical, it is not possible due to the very dynamic nature of the project I am working on.

So I built my project using FireFox (as usual) then crossed my fingers and launched it in IE to test compatibility. I was greeted with an ever-so-informative "Unknown runtime error". Even running they handy script debugger didn't give me any more information as to why .innerHTML would cause this sort of thing.

After much searching and much testing, I was forced to just destroy the table and use innerHTML on the parent DIV to recreate it.

What a pane... it's no wonder my boss made the early decision to only support FireFox for the administrative side of our software... too bad we can't do the same with the public side .

Wednesday, April 23, 2008

Get the querystring using JavaScript and Chaining

Okay, so this is going to be a very short pot... 'cause I don't have that much to say... except that everyday I use JavaScript, I like it more! Sure there are lots of drawbacks to it such as cross browser/os compatibility, and cross server insecurities... but you can do a lot to mitigate those issues, especially if you work with a good framework such as jQuery or YUI...

So what's the point of this whole post? Earlier today I created a js file that records metric information about website visitors... a pretty simple script... gather information such as screen resolution, user agent, color depth, ip address, session id, login id, etc and send it to a server side script to record the data.

So, one of the pieces I wanted to collect was the querystring. I wanted a clean one line solution to gathering that string.

I knew that window.location.href would give me the string version of the url currently in the browser so I thought I could split on the "?" resulting in "window.location.href.split('?')" Which in turn gave me an array containing 2 elements, the host string and the querystring... I am only interested in the query string... knowing that JS now treats the result as an array, I can grab the array element 1 (which is 2 in most programming languages...) like this: "window.location.href.split('?')[1]"... and there I have it!

Monday, February 4, 2008

YUI and Bookmarklets

I am a big fan of YUI (Yahoo User Interface) as it truly simplifies the cross browser implementation of JavaScript. In some ways it can be bulky, in some ways it's easier to implement my own light-weight controls... In other ways it has revolutionized the way I program JavaScript. Recently I came across one man's idea of implementing YUI everywhere you go. The idea is simple, add a simple script as a bookmarklet and you can utilize the power of YUI on anyones website!
The code is simple:

(function(){
var s = document.createElement('script');
s.src='http://yui.yahooapis.com/2.2.2/build/utilities/utilities.js';
document.getElementsByTagName('head')[0].appendChild(s);
})()


Once the script is run you can run additional scripts like:
var all = document.getElementsByTagName('*');for(var i = 0; i < all.length; i++) {new YAHOO.util.DD(all[i])}

Which will make all elements dragable, allowing you to mess with web pages in some pretty unique ways!

It is stuff like this that really makes being a web designer exciting!


Friday, January 25, 2008

setTimeout / setInterval and object scope

I have found over time, the need for setTimeout/setInterval is pretty rare... however, when the need does arrive, it is an invaluable tool!

The problem that I have consistently run into as of late (now that I am writing primarily object based JavaScript) is that when you use these functions, you loose the scope of your object. (i.e. if you call setTimeout(this.myFunc,900); this no longer refers to your object, but rather window, causing your script to fail). In search of a solution, I found an interesting article by Kelvo.

Klevo points out that in FireFox, setTimeout allows you to pass an additional parameter stating the implied scope. So by simply changing our command to: setTimeout(function(that) { that.methodToCall(); }, time, this); fixes the issues with scope... We basic create a proxy function that accepts an object as it's only paramater and gives us access to of that functions methods! This is a beautiful solution, if all you are developing for is FireFox.

From there, I found Alex's article who gives a simple yet elegant workaround for IE as well.

Check it out, it's absolutely worth a read for anyone who has run into trouble with setTimeout and JavaScript objects.

Friday, November 30, 2007

Generate Valid Visa CC Number

This is a valid visa CC # generator... I adapted it from the code presented on:

http://www.pdncommunity.com/pdn/board/message?board.id=samplecode&message.id=56

who adapted it from the code presented on:

http://www.darkcoding.net/projects/credit-card-generator/

It is pared down for just visa creation, and it create and returns a single valid visa number. This is perfect for generating numbers for use in sandbox cc processors.

All you need to do is call the function and you are set:

var myVisaNum = generateVisaCCNumber


function generateVisaCCNumber() {
var visaPrefixList = new Array("4539","4556","4916","4532","4929","40240071","4485","4716","4");
var ccnumber = visaPrefixList[ Math.floor(Math.random() * visaPrefixList.length) ];
// generate digits
while ( ccnumber.length < (15) ) { ccnumber += Math.floor(Math.random()*10); } // reverse number and convert to int and place in array var reversedCCnumber = new Array(); for ( var i=0; i < sum =" 0;" pos =" 0;" odd =" reversedCCnumber["> 9 ) {
odd -= 9;
}
sum += odd;
if ( pos != (14) ) {
sum += reversedCCnumber[ pos +1 ];
}
pos += 2;
}
// calculate check digit
var checkdigit = (( Math.floor(sum/10) + 1) * 10 - sum) % 10;
ccnumber += checkdigit;
return ccnumber;
}

Friday, November 16, 2007

Validate Credit Card Numbers Via Javascript

I frequently use this script to prevalidate creditcard numbers before they reach the server. It is built for javascript. I cannot take credit for the code... I found it on some website written for php and I ported it to javascript. Sorry, I cannot remember where I found the origional code. Here it is:

function validateCreditCard(s) {
if(s == "1212343456561234"){
return true;
}
// remove non-numerics
var v = "0123456789";
var w = "";
for (i=0; i < s.length; i++) {
x = s.charAt(i);
if (v.indexOf(x,0) != -1){
w += x;
}
}
if(s.length < 1){
return false;
}
// validate number
j = w.length / 2;
if (j < 6.5 || j > 8 || j == 7){
return false;
}
k = Math.floor(j);
m = Math.ceil(j) - k;
c = 0;
for (i=0; i a = w.charAt(i*2+m) * 2;
c += a > 9 ? Math.floor(a/10 + a%10) : a;
}
for (i=0; i c += w.charAt(i*2+1-m) * 1;
}
return (c%10 == 0);
}

Email Validation via JavaScript RegEx

I cannot take credit for the RegEx that makes this function work... I got it from the technical cheat sheet gurus at VisiBone (www.visibone.com/javascript). So without further adue:



function validateEmail(email) {
//alphanum,RFC822 chars,@-sign,alphanumbs dashes & dots,2-4 letter suffix,no more no less,case insensitive
return /^[a-z0-9][^\(\)\<\>\@\,\;\:\\\"\[\]]*\@[a-z0-9][a-z0-9\-\.]*\.[a-z]{2,4}$/i.test(email);
}