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

Friday, February 6, 2009

Clone node issue in IE

Hi all,

I am writing after a long time.
If you are wondering why so long?
didnt I had anything worthwhile to type?
Yes, I didnt had anything to write, coz whatever I learnt in last few months its well documented all over internet.
Not to forget an important fact that during my free time last year i Played a lot with my Canon SLR-Like Camera.
You can check my photography @ Sinless Photography

But this Time again our big time sucker IE(Internet Explorer) showed his ugly face and delayed our work and entangled us in DOM herarchies.

IE Sucks it AGAIN.

cloneNode doesnt work for all elements in IE.
yes
cloneNode doesnt work for all elements in IE.

My Problem.
I wanted to upload an image form without submitting the original form (in page1).
What I wanted to do:
1. Created a hidden form outside original form.
2. Copy / Clone input (type = file) element from original form to hidden Form.
3. Submit hidden form via JavaScript and view output in a frame (in page1).

What I did:
1. var clonedFileObject = document.forms['originalForm'].fileElement.cloneNode(true);
( where fileElement is input type = file element)
2. document.hiddenForm.appendChild(clonedFileObject);
3. hiddenForm.submit();

And What Happened.
var clonedFileObject = document.forms['originalForm'].fileElement.cloneNode(true);
Above statement worked perfectly fine in Firefox but in IE nothing happened.
No cloning was done and on form submission / image upload button All I could see was empty $_FILES array with error code = 4.

What all I tried:
1. hiddenForm.fileElement.value = originalForm.fileElement.value // didnt in FF either
2. Created a outer div and copied innerHTML of first div to hiddenforms div // didnt worked for input type file (didnt wasted much time either...should have worked)
3. Finally I did a shabby Patch work in my code which i really hated but in the given time limit and set conditions this was only I could think of.
var OriginalFileObj = document.getElementById('fileElement');
//this will remove fileElement from Original Form

var clonedFileObj = OriginalFileObj;
document.hiddenForm.appendChild(OriginalFileObj);
document.hiddenForm.submit();
divObj.appendChild(OriginalFileObj); //restoring of original file object in original form
//if you dont do this there wont be any file object in original form


I am sure there would be other better ways to do the same.
If you are aware of it please add in comments so as others can benefit from you including me.

Friday, March 21, 2008

Problems with JS for...in Loop

Sometimes on pleasant mornings when you have got all the reasons to smile your code breaks down suddenly and your Page contains errors n errors.
Similar thing happen to me recently.
My webpage was full of JS errors on one fine morning.
I just could understand why..... but again google came to my rescue.
I found this article.... about dangers of using for...in loop

The Problem

Try the following code on an empty page, one without any JavaScript libraries added:

var associative_array = new Array();
associative_array["one"] = "Lorem";
associative_array["two"] = "Ipsum";
associative_array["three"] = "dolor";
for (i in associative_array) { alert(i) };

You’ll get three sequential alert boxes: “one”; “two”; “three.” This code has a predictable output and looks logically sound: you’re declaring a new array, giving it three string keys, then iterating over them.

Now do this: replace “Array” with “RegExp” and run the code again. As if by magic, this also works! It’s not the only one. Try Boolean, or Date, or String, and you’ll find they all work as well. It works because all you’re doing is setting properties on an object (in JS, foo["bar"] is the same as foo.bar), and a for..in loop simply iterates over an object’s properties. All data types in JS are objects (or have object representations), so all of them can have arbitrary properties set.

In JavaScript, one really ought to use Object for a set of key/value pairs. But because Array works as demonstrated above, JavaScript arrays (which are meant to be numeric) are often used to hold key/value pairs. This is bad practice. Object should be used instead.

I’m not trying to ridicule or scold. This misconception is too common to attribute it to stupidity, and there are many legitimate reasons for the confusion. But this is something that needs to be cleared up if JavaScript is ever to be used on a grand scale.

If you need further evidence that Array is not meant to be used this way, consider:

  • There is no way to specify string keys in an array constructor.
  • There is no way to specify string keys in an array literal.
  • Array.length does not count them as items. In the above example, associative_array.length will return 0.
  • The page on Arrays in the Mozilla JavaScript reference makes no mention of this usage. (Nor does the ECMAScript specification, by the way, but you’ll have to do your own legwork to verify that, because I’m not linking to page 88 of a kajillion-page PDF.)

The History

This confusion has several other contributing factors:

  • In PHP, a language that many JavaScript users are also familiar with, numeric arrays and associative arrays are treated more or less identically. And since a set of key/value pairs goes by about eleven different names, depending on the language, this usage is quite often a result of unclear definitions of terms.
  • JavaScript is interpreted, not compiled, and many people have learned it by example. Thus a third-party script that uses Array improperly might rub off on its users.
  • JavaScript started with no specification, then received a poor specification, and I know few people who spend their free time reading specifications. Especially bad ones.
  • Because there is no formal construct for key/value pairs, JavaScript cannot distinguish between creating a hash and setting properties on an object. As we’ve demonstrated, any object can have arbitrary properties, and a for..in loop simply iterates over each of these properties, so the code above is not explicitly incorrect.
  • The harmful side effects of using Array for key/value pairs are not experienced unless Array.prototype is extended. Since this is an underutilized feature of JavaScript, it hasn’t been done on a large scale until rather recently.

Why Prototype “breaks” this usage

Concurrent with Prototype’s rise in popularity have been various blog posts complaining that the JavaScript framework “breaks” associative arrays — i.e. Arrays with string keys. It “breaks” them because it adds a handful of useful methods for working with arrays to Array.prototype, and these methods are also iterated over in a for..in loop. This means that when Prototype is included on a page the code above will loop 35 times instead of the original three.

Prototype also extends String with some methods for dealing with strings. If you try to use String as an associative array, your code will loop 20 times instead of three.

I am aware of the mitigating factors — hell, I just enumerated them — but complaining that Prototype “breaks” your ability to use Array as a hash is like complaining that Prototype “breaks” your ability to use String as a hash. It is not Prototype’s fault that JavaScript does not deter this improper use, and it certainly does not mean that Prototype does not “play well with others.” You are free to reject Prototype and keep using Array improperly, but then you give up your right to bitch and moan.

Actually, we’ve been here before: before version 1.4, Prototype added a couple methods onto Object.prototype, meaning that Object couldn’t even be used in the manner I describe, and a bunch of people rightly took Sam Stephenson to task for it. Object.prototype is verboten. Since version 1.4, however, this is no longer an issue, and therefore there is no longer an excuse.

So I will say it again: Array is not meant to be used for key/value pairs. Luckily, there is a dead-simple way to fix this. In the above example, you need only change Array to Object. (Or, if you’re using literal syntax, change [] to {}.) There. Your wrong code is no longer wrong, and it took only a little more work than a simple find-and-replace.

There are plenty of JavaScript frameworks to choose from, and many of them are excellent. I use Prototype because it works for me, and I do not take it personally when other people decide they don’t like it. But I believe Prototype deserves to be hated on its merits, dammit, not because it makes wrong code stop working — especially when the wrong code can be made right in ten seconds.

Saturday, June 2, 2007

IE DOM Issue

Recently I had an issue wherein I had to create new HTML element via DOM.And these HTML elements needed to have some properties as well HTML events like onClick(), onMouseOver(), etc.

While doing so my code worked perfectly fine in FireFox, but in IE the new elements created did not behaved in desired manner.
After a bit research I found that setAttribute() function doesnt work always in IE (actually it is suppose to not work at all ;)..).

Substitue for using setAttribute() is to use innerHTML
eg.TR1.innerHTML = "";

In my case innerHTML didnt worked as i had too many parameters to pass wherein I was out of combinations for using single and double quotes.

Below were the different ways I tried.
Not one of the following examples worked in IE:

TD1.setAttribute('onclick', 'doThis(' + param + ');');
TD1.onclick = 'doThis(' + param + ');';
TD1.onclick = new Function('doThis(' + param + ');');
TD1.onclick = function() { doThis(param); };
TD1['onclick'] = 'doThis(' + param + ');';
TD1['onclick'] = new Function('doThis(' + param + ');');
TD1['onclick'] = function() { doThis(param); };

The hack for making onClick work for you in IE via DOM

TD1.onclick = function() {
var temp = new Function("dostuff('"+myvar+"')");
temp();
}

The above code works well with both IE and Mozilla.
The same technique is to be used for calling any function for any HTML Events(onMouseOver).


NOTE: The above code can be simplified only when the function you are calling (dostuff) does not have any parameters to pass.

E.g.
TD1.onclick = function() { dostuff(); }

Some more interesting hacks for making your DOM work in IE are

blah.setAttribute('class','myCSS');


blah.className = 'myCSS'; <-- This line needs to be added

blah.setAttribute('valign', 'top'); This wont work as IE is case-sensitive
blah.setAttribute('vAlign', 'top');

Reference: Why IE Sucks

Wednesday, May 30, 2007

JavaScript Conditional Compilation.


Below are few inbuilt JS variable using which we can know some details of Client machine.

Predefined conditional compilation variables
for JavaScript
Variable Description
@_win32 Returns true if running on a Win32 system, otherwise NaN.
@_win16 Returns true if running on a Win16 system, otherwise NaN.
@_mac Returns true if running on an Apple Macintosh system, otherwise NaN.
@_alpha Returns true if running on a DEC Alpha processor, otherwise NaN.
@_x86 Returns true if running on an Intel Processor, otherwise NaN.
@_mc680x0 Returns true if running on a Motorola 680x0 processor, otherwise NaN.
@_PowerPC Returns true if running on a Motorola PowerPC processor, otherwise NaN.
@_jscript Always returns true.
@_jscript_build The build number of the JScript scripting engine.
@_jscript_version A number representing the JScript version number in major.minor format.

IE4 supports JScript 3.x
IE5.x supports JScript 5.5 or less
IE6 supports JScript 5.6

The version number reported for JScript .NET is 7.x.

@_debug Returns true if compiled in debug mode, otherwise false.
@_fast Returns true if compiled in fast mode, otherwise false.

In most cases, you probably will be limited to just using @_win and @jscript_build:

/*@cc_on
@if (@_win32)
document.write("OS is 32-bit. Browser is IE.");
@else
document.write("OS is NOT 32-bit. Browser is IE.");
@end
@*/

User defined Variables

You can also define your own variables to use within the conditional compilation block, with the syntax being:

@set @varname = term

Numeric and Boolean variables are supported for conditional compilation, though strings are not. For example:

@set @myvar1 = 35
@set @myvar3 = @_jscript_version

The standard set of operators are supported in conditional compilation logic:

  • ! ~
  • * / %
  • + -
  • << >> >>>
  • < <= > >=
  • == != === !==
  • & ^ |
  • &amp;amp;& |

You can test if a user defined variable has been defined by testing for NaN:

@if (@newVar != @newVar)
//this variable isn't defined.

This works since NaN is the only value not equal to itself.

References:

Friday, May 25, 2007

JavaScript No click links

No-click-links are link which you don't have to click.
While Googling for Eazy no click links, I found a Javascript code which enables us to navigate without clicking.
The example is given here

http://labs.mininova.org/noclick/

Other than no Clicks, there quite good number of other examples also like
  • mulitselect without control button use,
  • Visual Passwords,
  • Instant Form Validation,
  • etc. ;)
btw myself hoping to see a revolution in Web Navigation by use of more No click links and Visual passwords.

Wednesday, May 23, 2007

Navigation Without Mouse Clicks

Have you ever wondered how Surfing would be without mouse-clicks.
Still thinking what I mean.
Let me make it straight then.
lets Say there exist a "Link". Now inorder to view this page, people would normally click it.
Navigating without mouse clicks is that -all we need to do is just do mouseover on it and the link will be clicked and we will be taken to the desired page.

This is very much possible and many research projects are made online based on No-Click Idea.
If this idea is accepted by Internet Users then there would be no sound of mouse clicking while surfing internet,it would be a Quite expedition and number of people complaining of finger pains due to mouse clicks will also gradually decrease ;).

One such research project is here .
Its www.dontclick.it

I would strongly recommed you all to visit it so as to get that weird-nice experience while navigating this site.

I thoroughly enjoyed my experience and even played few games there.

Thursday, April 19, 2007

JS 3d arrays

To use multi-dimensional arrays in js, we have to define it as an array at each dimension. -
eg:

abc['test1'] = new Array();
abc['test1'][test2'] = new Array();
abc['test1'][test2']['test3'] = new Array();

foreach() substitute in JavaScript JS

JavaScript For...In Statement
The for...in statement is used to loop (iterate) through the elements of an array or through the properties of an object.
The code in the body of the for ... in loop is executed once for each element/property.
Syntax
for (variable in object)
{
code to be executed
}
The variable argument can be a named variable, an array element, or a property of an object.
Example
Using for...in to loop through an array:

var x
var mycars = new Array()
mycars[0] = "Saab"
mycars[1] = "Volvo"
mycars[2] = "BMW"
for (x in mycars)
{
document.write(mycars[x] + "
")
}

appendchild issue in IE

While Working in one of my applications I had to create new row dynamically on click of a button.

The below code worked fine with Mozilla, however nothing happened in IE also no errors were shown
var theTable = document.getElementById(tableId);
var rowIdAttribute = i+1;
var newRow = document.createElement('tr');

newRow.setAttribute("id", rowIdAttribute); theTable.appendChild(newRow );



I found that IE does not support appendChild to add new rows in the table
So I added a container element to place the new row and append that container element.
Correct code is as shown below which works fine both in IE and Mozilla


var theTable = document.getElementById(tableId);
var newtbody = document.createElement('TBODY');
var rowIdAttribute = i+1;
var newRow = document.createElement('tr');

newRow.setAttribute("id", rowIdAttribute);

newtbody.appendChild(newRow);
theTable.appendChild(newtbody);