helped alot- everything on the page
| SitePoint Sponsor |
helped alot- everything on the page




My object-oriented version of parsing the query string:
PHP Code:/* usage example:
//assuming location.search = '?n1=v1&n2=v2&n3=v3'
var qs = new QueryString(location.search);
alert(qs); //outputs ?n1=v1&n2=v2&n3=v3
alert(qs.string); //outputs ?n1=v1&n2=v2&n3=v3 (quicker than toString() since it's direct property access)
alert(qs.length);
alert(qs.n1); //outputs v1
alert(qs.n2); //outputs v2
alert(qs.n3); //outputs v3
for (var i = 0; i < qs.length; i++) {
alert(qs[i]); //outputs <name>=<value>
alert(qs[i].name); //outputs <name>
alert(qs[i].value); //outputs <value>
}
*/
window.QueryString = function(str) {
this.string = str; //this.string is faster than this.toString()
this.length = 0;
var re = /[?&]([^\s=]+)=([^\s&]*)/g;
var match = re.exec(str);
while (match) {
var name = match[1];
var value = decodeURI(match[2]);
this[name] = value;
this[this.length] = new QueryString.Pair(name, value);
this.length++;
match = re.exec(str);
}
}
QueryString.prototype.toString = function() {
return this.string;
}
QueryString.Pair = function(name, value) {
this.name = name;
this.value = value;
}
QueryString.Pair.prototype.toString = function() {
return this.name + '=' + this.value;
}
Last edited by Maian; Apr 12, 2005 at 01:29.




Some random esoteric notes on Javascript and DOM perks, performance, bugs, and compatibility. Some info might be somewhat outdated, so use the info at your own risk.
EDIT: moved this to my own semi-temporary website: maian.50webs.com
Last edited by Maian; Nov 19, 2005 at 03:40.
Ha! My school teaching grounds
Instead of writing:
You can write it like this:Code:<script type="text/javascript"> var text = "The meeting this week will be at "; var nowDate = new Date(); var currDate = nowDate.getDate(); switch(currDate) { case 1: case 2: case 3: case 4: document.write(text + "Steve's house"); break; case 5: case 6: case 7: case 8: case 9: case 10: case 11: document.write(text + "Nancy's house"); break; case 12: case 13: case 14: case 15: case 16: case 17: case 18: document.write(text + "Mike's house"); break; default: document.write(text + "Sally's house"); break; } </script>
Code:<script type="text/javascript"> var text = "The meeting this week will be at "; var nowDate = new Date(); var currDate = nowDate.getDate(); switch(true) { case (currDate < 5) && (currDate > 0): document.write(text + "Steve's house"); break; case (currDate < 12) && (currDate > 4): document.write(text + "Nancy's house"); break; case (currDate < 19) && (currDate > 11): document.write(text + "Mike's house"); break; default: document.write(text + "Sally's house"); break; } </script>
Only when making object references that descend from the window object.Originally Posted by Ultimater
What you're really trying to point out is that bracket-notation is the better choice for member access.
Yeah that too, eval() is known to lock up system resources.
Instead of making a function like this, which I see people making all the time:
Avoid eval() by doing this:Code:function getEl(id){ if(document.getElementById) return document.getElementById(id) else if(document.all) return eval("document.all."+id) else if(document.layers) return eval("document."+id) else return null }
But If you were going to make such a function in the first place, do it right:Code:function getEl(id){ if(document.getElementById) return document.getElementById(id) else if(document.all) return document.all[id] else if(document.layers) return document[id] else return null }
Code:if(!document.getElementById){ if(document.all)document.getElementById=function(){ if(typeof document.all[arguments[0]]!="undefined")return document.all[arguments[0]];else return null } else if(document.layers)document.getElementById=function(){ if(typeof document[arguments[0]]!="undefined")return document[arguments[0]];else return null } } //This code was programmed by me, Ultimater
Why is arguments[0] better than the name of the first argument?
We miss you, Dan Schulz.
Learn CSS. | X/HTML Validator | CSS validator
Dynamic Site Solutions
Code for Firefox, Chrome, Safari, & Opera, then add fixes for IE, not vice versa.
It's a more generic way of referring to the first argument.Originally Posted by Kravvitz
A lot of times you later change the name of your argument as you enhance your function and forget to change crucial code inside the function that uses the old name.
Believe it or not I even needed to edit my last post because I first called the argument el then decided later to call it id because it is a string and not an element. Thus, I left one instance of the old name floating in my code and had to edit my post.
Just for the record,
arguments[0] can always be used to refer to the first argument whether or not you named the argument.
When you assign a name for an argument, I'd assume the function runs a minute(a bit) slower because there are now two variables able to access the same thing.
Which before there was only one -- arguments[0].
Thus, it's an extra statement assigns your name to the argument.
Both ways are correct, and the choice is up to you.
But that is not the main idea I'm trying to get across.
The reason why my last code is better (than my other two example functions) is because it only defines the document.getElementById function if it's undefined -- which occurs when the user is using an old browser.
If the user is indeed using an old browser, my last code still runs faster (than my other two example functions) because it performs all of it's document.all and document.layer if-checks only once -- to define the document.getElementById function rather than each time the function is run.
Also, notice how my function is able to return null if no such object is found -- just like the real document.getElementById function.
Some Uncommon Information about Math.random:
Math.random returns a random number greater than or equal to zero but smaller than and excluding one. Therefore it is possible for it to return an actual zero but not a one
(which is very unlikely, the odds are about one in ten quadrillion[10^16]).
Source: http://www.ecma-international.org/pu...T/Ecma-262.pdf
(15.8.2.14 PDF page 128)
Furthermore, when mixing Math.round and Math.random, be cautious. The following may seem like it produces random numbers but the odds of getting certain numbers are amazingly sliced in half!:
In the above statement, the chances of getting a zero or three are cut in half!Code:alert(Math.round(Math.random()*3))
(because it's range is from 0 through 3)
Math.random()*3
0.0 - 0.49 rounds to a 0
0.5 - 1.49 rounds to a 1
1.5 - 2.49 rounds to a 2
2.5 - 3.00 rounds to a 3
Here is a safe way to mix the two:
(Note: if Math.random returns a zero, the above will alert a zero)Code:alert(Math.round( (Math.random()*3)-0.5 ))
I'd strongly suggest using Math.floor in place of Math.round.
Math.floor is basicly a function that always brings the number to the floor or rounds down.
Math.ceil is basicly a function that always addes a ceiling to the number or rounds up.
Safe Math.floor alternitive:
Unsafe Math.ceil alternitive:Code:alert(Math.floor( Math.random()*4) )
Can't use the above because it can return a -1 if Math.random returns an exact 0.Code:alert(Math.ceil( Math.random()*4)-1 )
Here's my mighty new Math.random function:
Now let's put the two together:Code:function safeRand(){ var r=Math.random(); if(r==0){return safeRand()} return r; }
Safe Math.ceil alternitive:
Code:function safeRand(){ var r=Math.random(); if(r==0){return safeRand()} return r; } alert(Math.ceil( safeRand()*4)-1 )




Labelled statements, break, and continue
These are actually features of any C-style language. Any statement can be labelled, and continue and break statements can target them:
As that example shows, the |break outer;| ends execution of the whole loop. This example outputs: [0,0][0,1]Code:outer: for (var i = 0; i < 5; i++) for (var j = 0; j < 10; j++) { document.write('[' + i + ','+ j + ']'); if (j == 1) break outer; }
In this example, the |continue outer;| skips the rest of the current iteration and goes to the next iteration of the loop. This example outputs: [0,0][0,1][1,0][1,1][2,0][2,1][3,0][3,1][4,0][4,1]Code:outer: for (var i = 0; i < 5; i++) for (var j = 0; j < 10; j++) { document.write('[' + i + ','+ j + ']'); if (j == 1) continue outer; }
Break and continue statements can only target labels they are nested in. That means they can't be used as a generic goto statement. For example,
wouldn't work.Code:label: some_statement; //... break label;
Labelled statements and break, revisited
The above are pretty well-known features. Now comes the interesting part.
That would work exactly how'd you expect it to work. That's right - any statement can be a label, and breaks can target them in the same way. The only differences are:Code:label: if (cond) { for (var i = 0; i < 10; i++) if (obj == null) break label; alert('obj has no null elements'); }
- The continue statement can't be used here - continue statements can only be used on loops.
- The breaks must have label targets - it must be |break label;| instead of just |break;|. |break;| would only work in loops.
That's not all. There's another statement that can be used to abstract this break to label functionality to anything: the block statement, i.e. |{ ... }|.
That's the same as the above, except without the |if|. This means there's no need for weird hacks like this:Code:label: { for (var i = 0; i < 10; i++) if (obj == null) break label; alert('obj has no null elements'); }
or equivalently:Code:label: do { if (cond1) break label; statement1; statement2; statement3; statement4; if (cond2) break label; statement5; statement6; } while (0);
They can be replaced with:Code:if (cond2) { statement1; statement2; statement3; statement4; } else if (!cond1) { statement1; statement2; statement3; statement4; statement5; statement6; }
A note on block statementsCode:label: { if (cond1) break label; statement1; statement2; statement3; statement4; if (cond2) break label; statement5; statement6; }
Unlike C/C++, the block statement in JS does not introduce a new scope. For example, in C++:
would output: 12.Code:int a = 1; { int a = 2; cout << a; } cout << a;
The equivalent in JS (in the HTML environment):
would output: 22. That means, that the inner a and the outer a are actually the same thing. To illustrate the point further:Code:var a = 1; { var a = 2; document.write(a); } document.write(a);
would be a syntax error in C++, while the equivalent in JS:Code:{ int a = 1; cout << a; } cout << a;
would output: 11.Code:{ var a = 1; document.write(a); } document.write(a);
Last edited by Maian; Jul 16, 2005 at 01:16. Reason: the wysiwig editor here really sucks...
All about the OR and AND operators
A simple OR example that would alert "true" is:
Now what most people don't know is that the following actually alerts "first stuff" rather than "true":Code:<script type="text/javascript"> alert(true||false) //alerts "true" </script>
The reason for that is because anything that isn't 0, false, or null is treated as though it were "true" and the OR operator isn't limited to returning either true or false like most operators are (it can return "first stuff" in my example). Also the OR operator first "looks at" the first argument and checks if the first argument is true or false then only if the first argument is false does the OR operator ever look at the second argument. In otherwords meaning if the first argument is true then it doesn't matter if the second argument is true or false because either way the OR operator only needs one true in order to return true (really the first argument). Only if two falses are found does the OR operator return false (really the second argument)Code:<script type="text/javascript"> alert("first stuff"||"second stuff") //alerts "first stuff" </script>
Code:<script type="text/javascript"> function a1s(){alert("function a1s() has been called");return true} function a2s(){alert("function a2s() has been called");return true} if(a1s()||a2s())alert(true) //alerts "function a1s() has been called" //alerts "true" </script>The following will alert "second stuff":Code:<script type="text/javascript"> if("first stuff")alert("true") //alerts "true" </script>
Let's go a bit further:Code:<script type="text/javascript"> alert(false||"second stuff") //alerts "second stuff" </script>
Some fancy foot-work:Code:<script type="text/javascript"> var v1="first stuff" var v2="second stuff" if(v1){ var v3=v1 } else{ v3=v2 } alert(v3) //alerts "first stuff" </script>
And the grand finale:Code:<script type="text/javascript"> var v1="first stuff" var v2="second stuff" var v3=(v1)?v1:v2 alert(v3) //alerts "first stuff" </script>
Code:<script type="text/javascript"> var v1="first stuff" var v2="second stuff" var v3=v1||v2 alert(v3) //alerts "first stuff" </script>
Also don't confuse the OR operator(||) with the Bitwise OR-operator(|):
You are probably thinking, "How in the world does that alert 3582!?"Code:<script type="text/javascript"> alert(3516|1354) //alerts "3582" </script>
Here's an explaination:
3516 in Binary is 110110111100
1354 in Binary is 010101001010
110110111100
010101001010
______________
110111111110
110111111110 in Decimal is 3582
Might as well teach you the bitwise AND operator now lol. Don't confuse the AND operator(&&) with the Bitwise-AND operator(&).
Here's an explaination:Code:<script type="text/javascript"> alert(3516&1354) //alerts "1288" </script>
3516 in Binary is 110110111100
1354 in Binary is 010101001010
110110111100
010101001010
______________
010100001000
010100001000 in decimal is 1288
Finally, similar to the OR operator, the AND operator doesn't need to "look at" both arguments either:
In order for the AND operator to return true (really the second argument), it needs both arguments to be true otherwise it returns false (really the second argument).Code:<script type="text/javascript"> function a1s(){alert("function a1s() has been called");return false} function a2s(){alert("function a2s() has been called");return false} if(a1s()&&a2s())alert(true) else alert(false) //alerts "function a1s() has been called" //alerts "false" </script>
And the Grand Finale Finale lol:
Sorry for miss-calling my grand finales.Code:<script type="text/javascript"> alert("first stuff"&&"second stuff")//alerts "second stuff" alert("first stuff"||"second stuff")//alerts "first stuff" </script>
Here are some tips concerning the syntax of javascript code. It is not a "must do", but it will make your code easier to read for others.
First of all, always put a semicolon ( ; ) at the end of a line where it is needed, so on every line which does not contain an if-else-end, for, while or switch-case structure. Also, put every new command on a new line, so don't heap up a lot of code on the same line.
Now for the brackets. A lot of people use C-style brackets, meaning that the opening bracket is on the same line as the if() command. Although this might seem professional, it does not help to make your code easy to understand. Propose that you want to remove an if() command, you should then also remove the matching bracket. But when you put the opening bracket on the same line as the if(), it is not easy to spot which closing bracket to remove. You should also always use brackets after an if() command, also if only one command will follow after it:
Wrong example:
Good exampleCode:if (argument1 != argument2) { dosomething(); andsomethingelse() if (a1 == b2) { return blaat(); } else { if (sdf == fsd) return test(); } }
Please note that I also put the brackets in front of and after "else" on a new line. When you want to remove an if statement now, you can easily spot all other code which needs to be adjusted.Code:if (argument1 != argument2) { dosomething(); andsomethingelse(); if (a1 == b2) { return blaat(); } else { if (sdf == fsd) { return test(); } } }
Another thing which a lot of people do clumsy, is commenting their code. If you place comments, always place them above the line you actually want to tell something about. Do not put your comments at the end of a line, even if they are tiny ones. Also, when you have a big block of code (like a user defined function), you do not need to comment every line, just make sure the code itself works like it should, and only tell what the function returns and how you should use it.
As long as you make sure no bugs are in the functions, that's all the user needs to know...Code:// Function which does difficult things, returns a // string with details about the user (or something :P) // Needs no parameters function example_function() { //big block of code here //big block of code here //big block of code here //big block of code here //big block of code here //big block of code here //big block of code here return "You are running a browser!"; } // This example code will call a function and return it to the user var strVariable; strVariable = example_function(); window.alert(strVariable);
I hope someone can take advantages with these tips. For the comments, most of the times you will still remember why and how you did something, but if other people need to use the same code, it is nice if they can use it right away, without them having to read it four times...![]()




That bracket thing is a matter of style. I like my code as condense as possible - it allows me to see a "bigger picture" in a way. The point about finding closing brackets is a rather moot as well, since the if statement and the closing bracket will have the same number of indents.
I also will use whatever I deem looks concise and elegant enough. For example:
looks clean enough to me, so I'll use such a construct. Another example:Code:var x = cond1? a : cond2? b : cond3? c : d;
I always use semicolons except with function expressions, since I consider it inconsistent with function declarations. It also never produces any ambiguities. Ex:Code:function empty() {}
Concerning commenting, commenting isn't always good. One of the worst practices I've seen is useless commenting. For example:Code:var x = function() { alert('hi'); } //notice the lack of a semicolon after this statement
Well...hello Mr. Obvious.Code:// Set x to y. var x = y;
Last edited by Maian; Aug 3, 2005 at 01:40.
thanks 4 trip




That doesn't work in any browser except ones derived from Mozilla, and Firefox 1.5+ versions won't support this feature anymore.Originally Posted by jofa



I don't know if any of yo have already encountered difficulties in retrieving count of childNodes.
It appears that IE ans Moz do not return same count as Moz FFX finds empty text nodes where you normaly should not find them ...
here is the script a friend gave me that I use to clean undesired nodes and retrieve correct node count ...
PHP Code:function go(c){
if(c){
if(c.nodeType!=1 && !c.data.replace(/\s/g,'')){
c.parentNode.removeChild(c)
}
}
}
function cleanNodes(d){
var bal=d.getElementsByTagName('*');
for(i=0;i<bal.length;i++){
var a=bal[i].previousSibling;go(a);
var b=bal[i].nextSibling;go(b);
}
}
launch with
on the body onload to clean all empty nodes found by ffx...PHP Code:cleanNodes(document.body)
I've been getting a lot out of this thread, so thought it's time to contribute a couple of useful things:
For those who've been looking at the new Javascript 1.5 reference being touted by Mozilla, and feeling frustrated by the fact that we won't be able to use many of the lovely new features on the majority of browsers for a while...
Example: the Array object is getting a few nice new functions. Let's take two of them: indexOf and forEach. Don't they look handy? But we can't take them for granted for a long time to come...
Actually, we can quite happily use them now. This is another of those 'What many people don't know about Javascript' things.
We can extend existing global object types.
Try this:
Many of the others are equally simple to do.Code:<script type="text/javascript"> if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(val) { for (var item,index = 0; ( item = this[index] ); index++) { if (val == item) { return index; } } return -1; } } if (!Array.prototype.forEach) { Array.prototype.forEach = function(fn, o) { for (var item,index = 0; ( item = this[index] ); index++) { if (o) fn.call(o, item); else fn(item); } } } var testArray = [ 'One','Two','Three','Four']; // indexOf test alert('Index of "Two" is: ' + testArray.indexOf('Two')); // forEach test testArray.forEach(alert); </script>
Only dead fish go with the flow
Second Useful Thing
I was reading the onLoad debate above, and thought I'd contribute my own approach. This is based around the fact that with many complex JS-using sites, there's sometimes no predicting how and when you many need to add a new onLoad function. So I do something like the following:
(and yes, I'm using the Array extensions seen above)
I can just keep adding functions to my onLoad list to my heart's content, never worrying about name clashes and the like. It's certainly not the only way, and may or may not be the best, but it's simple and easy, both of which appeal to me.Code:<script type="text/javascript"> var gOnload = [ ]; function addOnload(fn) { gOnload.push(fn); } window.onload = function() { gOnload.forEach(function(fn) { fn(); }); } function test1() { alert('one'); } function test2() { alert('two'); } addOnload(test1); addOnload(test2); </script>
Only dead fish go with the flow
For some reason the forum system was removing the backslash from the regexp. There should be a backslash before the 's'. It doesn't seem to be a problem if you use [ code ] instead of [ php ].Originally Posted by SpaceFrog
I would like to point out that if you had something like the following, then that function would remove it even though it shouldn't.
In most cases you would put a space after 'go', so it wouldn't be a problem.Code:...<p>go<span>...
To avoid the potential problem, you could use this regexp
instead ofCode:/^\s+$/g
Code:/\s/g
We miss you, Dan Schulz.
Learn CSS. | X/HTML Validator | CSS validator
Dynamic Site Solutions
Code for Firefox, Chrome, Safari, & Opera, then add fixes for IE, not vice versa.
I'm not in such a position as to give out advices (being so new to serious Javascript [that is, beyond the simple rollover effect]), but i think this one hasn't been posted, so here it comes:
When creating classes, it's better to define the methods as prototypes methods instead of defining inner functions inside the constructor function:
Usual way:
Better way:PHP Code:function ClassName()
{
this.variable1 = 0;
this.variable2 = 0;
this.method1 = function(param1,param2)
{
alert("You passed the following parameters: " + param1 + " " + param2);
}
}
You might think: ¿What's the difference and why should it matters?PHP Code:function ClassName()
{
this.attribute1 = 0;
this.attribute2 = 0;
}
ClassName.prototype.method1 = function(param1,param2)
{
alert("You passed the following parameters: " + param1 + " " + param2);
}
The difference lies in that when you start instanciating ClassName objects, the methods of the class will be created each time (remember you're creating a function object
each time you call the constructor with the ¨usual way" of defining classes, whereas with the "better way" of defining classes, you're creating the method of the class only one time (when loading your script into the page, as a global statement), thus saving precious memory (most notably if you create hundreds of objects from the same class).PHP Code:function ClassName()
{
this.variable1 = 0;
this.variable2 = 0;
this.method1 = function(param1,param2)
{
alert("You passed the following parameters: " + param1 + " " + param2);
}
}





Don't put onload events in the <body> tag.
Doing that prevents you from using javascript to add another function to the onload event. If there's an onload event in the <body> tag, and you try to add a new function to the onload event, e.g.:
then when the body tag is subsequently "encountered by the browser", or parsed, its onload function will overwrite the window.onload function. Here is an example:Code:window.onload = newFunc; </script> </head>
In addition, putting an onload event in the body tag serves to intermingle javascript and html instead of keeping the two separate.Code:<html> <head><title></title> <script type="text/javascript" language="javascript"> <!-- Hide from browsers without javascript window.onload = newFunc; function newFunc() { alert("New function."); } function existingFunc() { alert("Existing function."); } // End hiding --> </script> </head> <body onload="existingFunc()"> <div id="d" class="">hello world</div> </body> </html>
Do this instead:
credit: Simon Willison, ppk, et al. See here:Code://Existing function--possibly in an external js file: ////////////////////////////////////// window.onload = existingFunc; function existingFunc() { alert("Existing function."); } /////////////////////////////////////// //Adding a new function to onload, which //is only possible because of the superior way the existing //function was added to onload(i.e. not in the <body> tag): function newFunc() { alert("New Function"); } var existingFuncs = window.onload; window.onload = function() { if(existingFuncs) existingFuncs(); newFunc(); };
http://simon.incutio.com/archive/200...6/addLoadEvent
Last edited by 7stud; Feb 7, 2006 at 18:05.
Is there a way to make a pointer to a variable?
With the advice of ultimater to use window[] over eval() I was able to make pointers to global variables or window properties.
but when trying to set child element properties, this way doesn't workCode:// custom pointer can be made by using window[] to set global variables or window properties window.status = "initializing"; var variable = "original"; var variablePointer = "variable"; var windowStatusPointer = "status"; alert("After declaring, 'variable' is '" + variable + "' and the statusbar reads '" + window.status + "'."); window[variablePointer] = "new"; window[windowStatusPointer] = "changed values"; alert("After changing values through custom made pointers, 'variable' is now '" + variable + "' and the statusbar sais '" + window.status + "'.");
Is this possible in any other way?Code:var windowDocumentBgColorPointer = "document.bgColor"; window[windowDocumentBgColorPointer] = "green";
I want this for setting a global variable of a system fromout a plugin. Only problem is that the plugin doesn't know the variable's name so I made it configurable in the config.js file. I though to let the user specify the name of the variable and as such be able to assign a new value to this variable...
Bookmarks