I got a CGI/Perl script that reads databases and displays the results on template pages. I need to be able to get the name of the database that is being read from the url location to be able to use it in a link in the template page. The URL would look something like this:
perl.cgi?i=database&w=template&re=date&rada=012
in which I would like to get the [i] field from the URL. I heard an idea about creating a dummy <span> tag with an id, then within the span tag use document.write to write the location url into the span tag, then using the getElementById it might be possible to use substr(value1,value2) to identify the database call in the url. I just don't know how to do this if it works. Any ideas about what I could do to solve this problem?
There are many ways to get the query string values (name-value pairs) out of the URL (location) of the current page. Many examples use the String::split() method to split the location on the "?", the "&", and the "=". This keeps breaking the URL up into smaller arrays that can eventually be used to grab the query string name-value pairs. This is a decent solution, and may in fact be faster than my solution, but I find my own solution a bit more simple.
I use the window.location.search value to return the query string itself from the url. This is one of those cases where if you don't know it exists, you can't use it. You will see a lot of examples out there that split the URL on the "?" in attempt to separate the query string from the rest of the URL. This is entirely unnecessary as Javascript already provides a reference directly to the query string via window.location.search.
Once I have the search value, I harness the power of the String::replace() method to match the name-value pairs as regular expressions. Javascripts String::replace() is such a bad-ass method and will, in fact, iterate over each matched pattern. We can then send that pattern to a headless function which will keep track of the name-value pairs.
Once we have all these name-value query string pairs, we can either write them to the document as the document is still loading or, we can write them to DOM-accessed nodes after the document has finished loading:
Launch code in new window » Download code as text file »
When we run the HTML above at the given URL:
page.cfm?i=database&w=template&re=date&rada=012
... this is the output of the resultant page:
i: database
w: template
re: date
rada: 012
Database: database
Notice that the first 4 values were written as the document was loading (using document.write()). Then, once the document finished loading (just about), we grabbed a DOM node reference based on the ID, "database," and wrote the URL value to its innerHTML. These are two valid was of handling this situation.
Just keep in mind that, unlike ColdFusion, Javascript is very much case sensitive. That means that the URL values that are parsed are kept in case; therefore, the objURL will have a value for "i" but will NOT have a value for "I". Also, I parsed the entire query string value in one go. This is not required. You could create a function that takes a name and returns the query string value for that name. This is fine to do, but if you are going to get more than one value, I would recommend just parsing the entire query string in one go to get the processing over and done with.
Download Code Snippet ZIP File
Comments (27) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
A split-based method (which seems more correct since you're not replacing anything) doesn't need to be much more complicated. E.g.:
// Parse the query (supports keys not followed by "=", and values which contain "=")
var q = (location.search.length > 1 ? location.search.substring(1).split("&") : []);
var qKeys = {};
for(var i = 0; i < q.length; i++){
qKeys[q[i].match(/^[^=]+/)] = q[i].replace(/^[^=]+=?/, "");
}
-----
You could also use an exec()-based approach, which would probably be even better/easier, come to think of it:
var qKeys = {};
var re = /[?&]([^=]+)(?:=([^&]*))?/g;
var matchInfo;
while(matchInfo = re.exec(location.search)){
qKeys[matchInfo[1]] = matchInfo[2];
}
Posted by Steve on May 10, 2007 at 10:25 AM
@Steve,
I am not familiar with the exec() method. From a very cursory Google search, it seems to globally update some regular expression property about the matches in the current string. I will have to look into this further. Thanks for the advices.
Posted by Ben Nadel on May 10, 2007 at 10:38 AM
The RegExp exec method returns all backreferences from a match in an array. If no matches are found it returns null. It also stores a couple properties on the returned array (the input and the index of the match), and on the regex object itself (the index where the match ended [lastIndex], as well as the source regex and Boolean values for each regex modifier, indicating if they were used).
The trick here is that if you use the exec method on a regex with the /g (global) modifier, it starts the match from the value of lastIndex. So, each time through the while loop, it's picking up where it left off on the last match, until there are no more matches and it returns null (ending the loop).
Posted by Steve on May 10, 2007 at 10:57 AM
@Steve,
That sounds cool. I like the fact that it picks up where it left off, sounds nice an efficient. This will be fun to play around with.
Posted by Ben Nadel on May 10, 2007 at 11:04 AM
@Steve,
This stuff is really cool. I did some playing around, and I think I am really gonna like this methodology. Thanks for bringing it to my attention.
http://www.bennadel.com/index.cfm?dax=blog:697.view
Posted by Ben Nadel on May 10, 2007 at 1:28 PM
For some reason, despite it being extremely useful, very few people seem to know about it or how to use it well. Even the Mozilla documentation for the method seems very neglected, with one example of "using exec" not even using exec (!), and another example doing a comparison against undefined to end a similar while loop, even though exec actually returns null (hence, their example code only works due to type conversion... i.e., (undefined == null) is true, but (undefined === null) is false).
Posted by Steve on May 10, 2007 at 2:08 PM
Here's the page I'm talking about:
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:RegExp:exec
Posted by Steve on May 10, 2007 at 2:10 PM
(Before anyone brings it up, of course my example uses type conversion as well [relying on null being falsie], but at least it avoids being misleading, hopefully.)
Posted by Steve on May 10, 2007 at 2:15 PM
Ha ha ha, yeah, that's where I looked up some of this stuff. I noticed that last example on the page... It has nothing to do with exec() :) I even did a page find to see if maybe I was just not seeing it. Sure enough, it just looped back up the top of the page.
Posted by Ben Nadel on May 10, 2007 at 2:59 PM
Gentlemen,
It seems to me the final example does call exec():
var firstName = /\w+/i(input.value);
While it bends my C++ mind, that looks like a pretty straight call to me as given by the first paragraph of the exec() Description.
firstName is an array where firstName[0] is the result for each iteration.
The comparison with undefined is, I agree, strange and clearly untested in the earlier example. I hope that's not how Firefox is tested.
Kevin
p.s. the combination of discovering window.location.search instead of document.location.search along with the query string parse and RegExp discussion makes this the most valuable information per word discovery I've made this year.
Posted by Kevin Andresen on May 14, 2007 at 3:32 PM
Kevin, you are certainly correct (regarding Mozilla's exec documentation, that is). Thanks for correcting my error.
Posted by Steve on May 15, 2007 at 3:40 AM
@Kevin,
Reading regular expressions with that funky /.../ notation confuses me so I tend to just gloss over it. Now, I'm just an unfrozen ColdFusion programmer thawed out by your scientists; my primitive mind does not understand crazy notation. But what I do know is that I like seeing new RegExp().
Posted by Ben Nadel on May 15, 2007 at 7:29 AM
Awesome script! I was able to use your code to pull in a URL that had a variable (mysite.htm?myVariable=value) & pass it to a function easily!
(Head script)
var urlObj = new Object();
window.location.search.replace(
new RegExp( "([^?=&]+)(=([^&]*))?", "g" ),
function( $0, $1, $2, $3 ){
urlObj[ $1 ] = $3;
}
);
(in the function that needed the variable)
for (var strKey in urlObj){
var myVariable = urlObj[ strKey ];}
Was tired of using convoluted substring queries and splits.... Worked like a charm... THANKS MAN!!!! :-)
-Tom
Posted by Tom on Jul 31, 2007 at 12:01 PM
@Tom,
Always glad to help :)
Posted by Ben Nadel on Jul 31, 2007 at 12:03 PM
Hi,
I modified the re to support parameters without values (flags) like
?par1=v1&flagX&par2=v2
/[?&]([^=&]*)=?([^&]*)/g
cheers
Posted by eduardo on Oct 14, 2007 at 6:20 AM
I love this script - but I'm having an issue. I want to strip a single variable from the URL and put it in the middle of a tag. For instance, I want to pull variable &abc=123 and parse "123" into an <iframe> tag.
Like:
<iframe src="http://www.url.com/123.html">
Is there a way to do this?
Posted by Don Day on Jun 27, 2008 at 1:34 PM
Once you get the variable value, give your IFRAME a name tag and a name, and then just put your parameter into a string like:
var url = "http://www.url.com/" & theVariableRepresentingTheUrlParameter & ".htm";
IFRAMEname.src = url;
Put that into its own function with the URL parser, then use an onlick or onload or whatever event you are looking for to change your IFRAME's src to that URL.
Hope that helps.
Tom
Posted by Tom on Jun 27, 2008 at 1:45 PM
Sorry - in my last comment those "&" should have been "+" since it's JavaScript. "&" are used in VB.
Posted by Tom on Jun 27, 2008 at 1:48 PM
@Tom,
Thanks for jumping in there.
Posted by Ben Nadel on Jun 27, 2008 at 2:07 PM
OK - I guess I don't get it. I have all the script included above - but I'm not seeing how to assemble this...
Posted by Don Day on Jun 27, 2008 at 2:12 PM
Probably 'cause I was wrong... use ID, not name, for your IFRAME tag, then reference it like this:
function returnUrlObjVal() {
if (s[0]) {
var iFrameForm = s[0];
var url = "http://www.url.com/" + iFrameForm + ".html"
myFrame.window.location.href = url;
}
}
Don't use src like I said before, either, use window.location.href. "s[0]" is an array variable from reading in the parsed URL.
Happy coding,
Tom
Posted by Tom on Jun 27, 2008 at 3:24 PM
OK - I think this is what we're trying to do here - but it still doesn't seem to work. What am I missing?
<html>
<head>
<title>Untitled Document</title>
</head>
<body>
<script type="text/javascript">
function returnUrlObjVal() {
if (s[0]) {
var iFrameForm = s[0];
var url = "http://www.url.com/" + catID + ".html"
ZZZ.window.location.href = url;
}
}
</script>
<iframe id="ZZZ">
</body>
</html>
Posted by Don Day on Jun 27, 2008 at 3:31 PM
You have it all except for how to get the parsed value. That part was the whole point of this website/page, so I figured you had to have figured that part out already, or at the very least I figured you could have figured out how to use Ben's code to do so (and the numerous posts below it). Don't expect everyone to do everything for you (even though if you look hard enough on this site, they have).
I should tell you, though, that the "s[0]" variable I put in my last post is the same thing as if I had used Ben's code to give me objURL[0], above. You need the URL parsing code from Ben's example to give you the value from the URL string - it'll be almost a direct copy-paste, anyway. That key info should help you finish your project.
-Tom
Posted by Tom on Jun 27, 2008 at 4:03 PM
Woahhhhhh there.
I really appreciate your help.
I had the other JS statements, but I'm not clear where to put the code you posted - the more I looked at it, the more I started to second guess myself and thought that I DIDN'T need the other code. I'm just unclear where to put your extra stuff.
I've been working on this for three days, but I'm definetley not an expert coder so this stuff confuses me a bit.
Posted by Don Day on Jun 27, 2008 at 4:07 PM
Best thing to do is to start off with Ben's complete code, then put in my function, not the other way around. If you replace my s[0] with objUrl[0], and put in your IFRAME tag into the HTML body, that's all there is to it. Test by putting file:\\\C:\folderMyFileIsIn\mypage.htm?url=test.html on your address bar.
Posted by Tom on Jun 27, 2008 at 5:03 PM
Sorry, I accidentally deleted this post when filtering SPAM:
Here....
[code]
<HTML><HEAD><TITLE>Parsing a URL</TITLE>
<SCRIPT language="JavaScript">
//<![CDATA[
var urlObj = new Object();
window.location.search.replace(
new RegExp( "([^?=&]+)(=([^&]*))?", "g" ),
function( $0, $1, $2, $3 ){
urlObj[ $1 ] = $3;
});
s = new Array();
var i = 0;
for (var strKey in urlObj) {
s[i] = urlObj[ strKey ];
i++;
}
function returnUrlObjVal() {
if (s[0]) {
var iFrameForm = s[0];
var url = "http://www.url.com/" + iFrameForm + ".html";
myFrame.window.location.href = url;
}
}
//]]>
</SCRIPT>
</HEAD><BODY onload="returnUrlObjVal()">
<FORM name="theForm">
<BR><BR>
<IFRAME ID="myFrame" height="500" width="800"></IFRAME>
<BR><BR></FORM>
</BODY></HTML>
[/code]
Posted by Ben Nadel on Jun 30, 2008 at 8:21 AM
Really very helpful. Thanks
Posted by Imran on Sep 11, 2008 at 3:53 AM