473,695 Members | 2,370 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

URL parameters by name or iteration..

I have written a few scripts to parse the
URL arguments and either list them or allow
access to the value of any parameter by name.
<http://www.physci.org/test/003url/index.html>
<http://www.physci.org/test/003url/index.html?url= http://mybiz.com/&that=this&when =now#21>
<http://www.physci.org/test/003url/index.html?url= http://mybiz.com/&when=now>

Before I go offering it in public (and writing it
into any number of the 'development kits' I deliver
through my site), I would like to get it reviewed
by the people who know Javascript.

Is this code as good as it can be?

Some further errata and comments are listed here..
<http://www.physci.org/test/003url/index.html#erra ta>
The 3 scripts are linked in the page.
[ ..to save you the trouble of pulling up
the source and making a direct fetch. ;-) ]

All comments welcome.

--
Andrew Thompson
http://www.PhySci.org/ Open-source software suite
http://www.PhySci.org/codes/ Web & IT Help
http://www.1point1C.org/ Science & Technology
Jul 23 '05 #1
11 3024
*Andrew Thompson* wrote:
I have written a few scripts to parse the
URL arguments and either list them or allow
access to the value of any parameter by name. .... All comments welcome.


Hi Andrew, I've got something similar
(www.andrewu.co.uk/tools/request/) - it's a little different as it's
trying to be a client-side version of ASP's Request.QuerySt ring
collection. As a result it's got a bit of bloat to it and it could do
with a re-write (I never seem to find the time, but it really needs it).
It supports Count, Key and Item methods so you can find out if keys
exist before using them, it also handles multiple keys and has
enumeration via the 'in' statement (caveat applies).

Trouble is, I kind of wish I hadn't written it because people use it to
create inaccessible/unusable web sites (e.g. site navigation that only
works by decoding the querystring client-side, etc.) The script is in a
compressed format at
http://www.andrewu.co.uk/tools/reque...csjsrequest.js (uncompressed
version upon emailing). There's an interactive demo where you can
compare it against the server-side original -
www.andrewu.co.uk/tools/request/demo/.

Best,
--
Andrew Urquhart
- FAQ: www.jibbering.com/faq/
- Archive: www.google.com/groups?q=comp.lang.javascript
- My reply address is invalid, use: www.andrewu.co.uk/contact/
Jul 23 '05 #2
On Sat, 8 May 2004 23:50:42 +0100, Andrew Urquhart wrote:
*Andrew Thompson* wrote:
I have written a few scripts to parse the
URL arguments and either list them or allow
access to the value of any parameter by name. ...
Hi Andrew, I've got something similar
(www.andrewu.co.uk/tools/request/) - it's a little different

<snip>

(chuckles) I suspected if I looked for an half
hour more I'd have found the (one of the..)
pre-existing solutions.

Yours sounds altogether more comprehensive
than my own little scripts. ;-)
Trouble is, I kind of wish I hadn't written it because people use it to
create inaccessible/unusable web sites


Ahhhh. Yes. You make something beautiful
and wonderful that provides that 'bit extra'
in particular arcane situations* and then it
encounters 'people' who base a navigation
system on it, ..and is never the same again. :-(

* My own interest springs from configuring
Java applets.. I have a site where I can
generate applet tags on the server-side, but
most of my applets can be enhanced using
parameters provided by URL, and many of the
people who use them on _their_ sites have no
PHP, JSP etcetera.

Of course, if my scirpts become in any way
well known, I do not doubt people will do
completely stupid things with it.. (shrugs)

Thanks for your input. :-)

--
Andrew Thompson
http://www.PhySci.org/ Open-source software suite
http://www.PhySci.org/codes/ Web & IT Help
http://www.1point1C.org/ Science & Technology
Jul 23 '05 #3
Andrew Thompson wrote:
I have written a few scripts to parse the
URL arguments and either list them or allow
access to the value of any parameter by name. <snip> Before I go offering it in public (and writing it
into any number of the 'development kits' I deliver
through my site), I would like to get it reviewed
by the people who know Javascript.

Is this code as good as it can be?

<snip>

No, it is pedestrian at best.

Starting with your - QueryParameter - object:-

| /** Provide the name of this URL parameter. */
| function getName() {
| return this.sName;
| }
|
| /** Provide the value of this URL parameter. */
| function getValue() {
| return this.sValue;
| }
|
| /** Check if this is the 'paramName' URL parameter. */
| function isParam( paramName ) {
| return ( this.sName==par amName );
| }
|
| /** Construct an URL parameter object, and attach the functions. */
| function QueryParameter( paramName, paramValue ) {
| this.sName = paramName;
| this.sValue = paramValue;
|
| this.getName = getName;
| this.getValue = getValue;
| this.isParam = isParam;
| }

- you are creating 4 global function to support one object. Generally,
code should have as little impact on the global namespace as possible.
For a globally available object constructor that impact does not need to
be more than just the constructor name. The more items added to the
global namespace the more there is a risk of naming collisions and
resulting unexpected interactions.

This is of most significance when creating generalised components (as
appears to be your intention) because the users of a generalised
component should not be expected to be intimate with its implementation
and so should not need to concern themselves with avoiding naming
collisions. You have chosen to create global functions called "getName",
"getValue" and "isParam", which are nice self-explanatory names to use,
but equally they are names that are likely to be well suited elsewhere.
When the those names are just the properties of a type of object then it
doesn't matter if another type of object has the same property names,
but habitually place them in the global namespace and you are asking for
trouble (and individuals who can only employ other people's components
are going to be the least capable of handling any manifest
consequences).

But javascript constructors to have a prototype which allows objets
created with the constructor to inherit common properties, and also
allows those properties to be define without any impact on the global
namespace. Using the prototype pattern to define your object would
result in:-

function QueryParameter( paramName, paramValue){
this.sName = paramName;
this.sValue = paramValue;
}
QueryParameter. prototype.getNa me = function(){
return this.sName;
};
QueryParameter. prototype.getVa lue = function(){
return this.sValue;
};
QueryParameter. prototype.isPar am = function(paramN ame){
return (this.sName==pa ramName);
};

With which all objects created with the constructor automatically
acquire all of the methods defined on the prototype without any need to
explicitly assign function object to object properties, and without the
creation of the methods needing to have any impact on the global
namespace.

But this namespace problem caries over in to the rest of the system,
which defines another 3 functions and 3 global variables, 2 of which are
only temporarily used and so would seem to be performing roles that
would be better suited to function local variables. The configuration
also uses two inline function calls, neither will work without the
other, and the functions being called are unlikely to be applicable in
other situations (especially as they employ global variables and have no
parameters).

I notice that, on the web page, you say; "I considered adding the
objects to a hash (associative array) as suggested by Grant , but
unfortunately could not then figure how to iterate the elements. For me
exploiting the hashtable-like aspects of javascript objects is the
obvious way to store name/value pairs. Doing so allows named property
references to be handled by native code instead of javascript, and
particularly javascript loops.

You use:-

| /** Provides the value for the parameter named by 'key'. */
| function getQueryString( key) {
| var value = null;
| for (var ii=0; ii<parameters.l ength; ii++) {
| if ( parameters[ii].isParam(key) ) {
| value = parameters[ii].getValue();
| break;
| }
| }
| return value;
| }

- which loops through (potentially) all of the created objects, and
makes two method calls to determine which value to return, and still
will only return the value corresponding with the first name/value pair
encountered on the query string (a general method should be able to
handle multiple occurrences of the same name in the query string.

Using javascript object to store name/value pairs allows much more
efficient retrieval of named properties. Being able to iterate through
the names used is just a matter of recording the names used in a
retrievable form.

The drawback with using a javascript objects to store name/value pairs
is that they have some properties of their own (constructor, toString)
which need some special consideration when the intention is to create
truly general code. But then creating truly general code is not
necessarily a good idea as all code will actually be used in a specific
context, and downloading code to handle possibilities that will never
arise in the specific situation is wasteful. For example a general query
string interface might go:-

/* This function call creates an interface to the name value pairs
from the query string associated with the URL of the current page
in the browsers. The interface is available as a global variable
called - queryStrings - and has two methods:-

queryStrings.ge tCountFor(name) ; - Returns the number of values found
in the query string under the - name - provided as a parameter,
or numeric zero if no elements exist under the name.

queryStrings.ge tValueFor(name, index); - Returns the value found on
the query string associated with the - name - provided as the
first parameter. The second parameter is optional and represents
an index into an array of the values found for the name. The
index defaults to zero if no value is provided. If no value is
found under the index, or no values exist under the name, then
undefined is returned. Otherwise a string value is returned for
each value provided on the query string associated with the
name, or, if a name was found on the query string with no
associated value this method returns boolean true;

queryStrings.ge tNames(); - Returns a reference to an Array of all
of the names found on the query string. Any modifications made
to the array will persist and be present in the Array that will
be returned by later calls, but will alter the name value pairs
returned by the other methods.

*/
var queryStrings = (function(out){
var list = {};
var keyList = [];
var global = this;
var unsc = (global.decodeU RIComponent)?'d ecodeURICompone nt':
'unescape';
var nameSafe = [' ','']; //first element is the space character
function addItem(name, value){
nameSafe[1] = name;
var sName = nameSafe.join(' ');
if(list[sName]){
list[sName][out[sName].length] = value;
}else{
list[sName] = [value];
keyList[keyList.length] = name;
}
}
if(typeof location != 'undefined'){
var nvp,ofSet, temp = location.search ||location.href ||'';
if((ofSet = temp.indexOf('? ')) > -1){
temp = temp.split("#")[0];
temp = temp.substring( (ofSet+1), temp.length);
var workAr = temp.split('&') ;
for(var c = workAr.length;c--;){
nvp = workAr[c].split('=');
if(nvp.length > 1){
addItem(global[unsc](nvp[0]),global[unsc](nvp[1]));
}else if(nvp.length == 1){
addItem(global[unsc](nvp[0]), true);
}
}
}
}
return ({
getCountFor:fun ction(name){
nameSafe[1] = name;
var sName = nameSafe.join(' ');
return ((list[sName] && list[sName].length)|0);
},
getValueFor:fun ction(name, index){
nameSafe[1] = name;
var sName = nameSafe.join(' ');
if(list[sName]){
return list[sName][(index|0)];
} //else return undefined (by default)
},
getNames:functi on(){
return keyList;
}
});
})(); //inline function expression call.

- and cover most possibilities in query string use. But in a real
situation it would be possible to avoid names in the query string that
would coincide with javascript object properties, know that name/value
pairs would be distinct, know that names would always have accompanying
values, know which values where expected to be used and avoid names and
values that would be modified in URL encoding.

Knowing these things allows much simpler code to be used, but to still
achieve the desired results. e.g.:-

var queryStrings = (function(out){
if(typeof location != 'undefined'){
var temp = location.search ||location.href ||'';
var nvp, ofSet;
if((ofSet = temp.indexOf('? ')) > -1){
temp = temp.split("#")[0];
temp = temp.substring( (ofSet+1), temp.length);
var workAr = temp.split('&') ;
for(var c = workAr.length;c--;){
nvp = workAr[c].split('=');
if(nvp.length > 1){
out[nvp[0]] = nvp[1];
}
}
}
}
return out;
}({})); //inline function expression call passed an object
// literal - {} - as its parameter (out).
I notice your page includes the line; "It is designed to degrade
'gracefully' by telling the user they require JS for this page.". That
is not a definition of "graceful degradation" that I would recognise (it
is never 'graceful' to be bothering the user with this sort of detail).
Though it is not really the role of such a low-level component to
gracefully degrade itself. That is a task for the code that wishes to
use it; to decide how it is going to respond to not being able to
extract the query sting information that it requires/expects. The
responsibility for the component designer is only to ensure that the
code does not actually error when it fails. and to have well defined
behaviour when that failure occurs, for which it is probably only
necessary, in this context, not to return values when they are requested
by name.

Richard.
Jul 23 '05 #4
On Sun, 9 May 2004 04:17:16 +0100, Richard Cornford wrote:
Is this code as good as it can be?

<snip>

No, it is pedestrian at best.


Thank you, thank you, thank you..

I will have a much closer look at what
you wrote over the next day ..or so. ;-)

From what I read of the first 80 or so
lines it seemed you were rattling the
foundations out of the rather fragile, hackish
code I wrote (I also noticed some important
points about URL's that I missed as well).

After I have made changes based on your
advice, I will report back.

Cheers,
--
Andrew Thompson
http://www.PhySci.org/ Open-source software suite
http://www.PhySci.org/codes/ Web & IT Help
http://www.1point1C.org/ Science & Technology
Jul 23 '05 #5
"Andrew Urquhart" <us************ **************@ spam.invalid> wrote in message news:<vt******* ******@newsfe2-gui.server.ntli .net>...
*Andrew Thompson* wrote:
I have written a few scripts to parse the
URL arguments and either list them or allow
access to the value of any parameter by name.

...


var entireURL = location.search ;
var url=location.se arch.split('url =')[1];

I don't speak JavaScript, rather Java. Those two lines look suspcious to me.
What if there is no url=something? Does that [1] not then become an out
of bounds subscript?
Jul 23 '05 #6
Richard Cornford wrote:
<snip>
There were some mistakes and typos in that post, so I may as well
correct them (at least the ones that I have noticed so far).
But javascript constructors to have a prototype which allows objets ^^
But javascript constructors have a prototype ...
<snip> I notice that, on the web page, you say; "I considered adding the
objects to a hash (associative array) as suggested by Grant , but
unfortunately could not then figure how to iterate the elements. <snip> ^
There should have been a closing quote mark at the end of that sentence.

<snip>. /* This function call creates an interface to the name value pairs
from the query string associated with the URL of the current page
in the browsers. The interface is available as a global variable
called - queryStrings - and has two methods:- ^^^
It actually has three methods.

<snip> var queryStrings = (function(out){ ^^^
That formal parameter is left over from an earlier version and is not
needed here

<snip> if(list[sName]){
list[sName][out[sName].length] = value; ^^^
I forgot to change that identifier to - list -:-

list[sName][list[sName].length] = value;

<snip> return out;
}({})); //inline function expression call passed an object

<snip> ^
That final closing parenthesis should follow the closing brace:-

})(); // ...

Richard.
Jul 23 '05 #7
On 8 May 2004 21:14:54 -0700, Roedy Green wrote:
*Andrew Thompson* wrote:
I have written a few scripts to parse the
URL arguments and either list them or allow
access to the value of any parameter by name.
.... var entireURL = location.search ;
var url=location.se arch.split('url =')[1];
(sshhh Roedy!) That was JS that predated
the 'much improved' version that Richard
just _decimated_.

I mean ..do you want to embarass me
or something? ;-)
I don't speak JavaScript, rather Java. Those two lines look suspcious to me.
What if there is no url=something? Does that [1] not then become an out
of bounds subscript?


That _original_ script handled
a) no query / with fragment
b) no query / no fragment
c) query / with fragment
d) query / no fragment..
(..I tested it)

Which, I might add, you could have verified
by testing it for _yourself_, either at your
site, or locally on your file system.

All you have to do is use the URL's and
see how it behaves [..much as I might
point out to a Java noob who asked such
a question, ..tut tut. ;-) ]

--
Andrew Thompson
http://www.PhySci.org/ Open-source software suite
http://www.PhySci.org/codes/ Web & IT Help
http://www.1point1C.org/ Science & Technology
Jul 23 '05 #8
On Sun, 9 May 2004 05:40:31 +0100, Richard Cornford wrote:
Richard Cornford wrote:
<snip>
There were some mistakes and typos in that post,...


Thanks for following it up, I will add those
as errrata after I've properly examined the
original huge post.

But, ..missed quote marks??

I had to reread that section of the post
before I actually noticed. You are
striving for precision! ;-)

--
Andrew Thompson
http://www.PhySci.org/ Open-source software suite
http://www.PhySci.org/codes/ Web & IT Help
http://www.1point1C.org/ Science & Technology
Jul 23 '05 #9
Roedy Green wrote:
<snip>
var entireURL = location.search ;
var url=location.se arch.split('url =')[1];

I don't speak JavaScript, rather Java. Those two lines look
suspcious to me.
From a Java perspective they would. But loose-typing, and its
accompanying automatic type-conversion, allow some possibilities that
are unthinkable in Java. Not that loose typing means you don't have to
think about type, you just have to think differently. (That is, the
programmer has to understand (or find out) what types he/she is dealing
with because the source code is not going to tell them.)

The first line is fine (subject to the absence of any feature detection
to verify that the - location - object exists in the environment (I
don't know of a browser where it doesn't, but no harm in making sure)).
If the - location - object implements a - search - property that
property will hold a string primitive value (no problem assigning a
string to a local variable in a loosely typed language). If the -
location - object does not implement a - search - property (and again I
don't know of any that don't) then the property accessor will result in
an - undefined - value (which is a distinct internal type in
javascript), and again assigning - undefined - to a local variable is
perfectly OK. (A variable or object property may be defined and still
hold the value - undefined -, and that is distinct from a variable that
has not been defined (or a property that does not exist on an object).)
What if there is no url=something? Does that [1] not then
become an out of bounds subscript?


That isn't an error in javascript. The feature of Array(s) that is
distinct from Object(s) is the internal handling of the - length -
property (via the Array's special internal - [[Put]] - method (see ECMA
262 3rd edition section 15.4.5.1)), apart from that, what would appear
to be an Array indexing syntax in Java is in fact a bracket notation
property accessor in javascript.

Bracket notation property accessors are identical in mechanism to dot
notation property accessors, so:-

var entireURL = location.search ;

- means the same as:-

var entireURL = location['search'];

- and, with:-

var x = 'search';

var entireURL = location[x];

- with the exception that a dot notation property accessor may only use
legal identifiers between/around the dots, while a bracket notation
accessor may use any character sequence in the string used within the
brackets. You cannot index an Array as - ar.1 - because "1" is not a
legal identifier in javascript (ECMAScript), so indexed access to array
elements must use bracket notation. But in practice the number 1 is
internally type-converted to the string "1" for use with the bracket
notation accessor.

With:-

var ar = new Array;

ar[1] = 20;

- and:-

ar['1'] = 20;

- are specified as being identical in terms of which property of the
array is being assigned to (though Netscape 4 (eroniously) thinks
differently).

So if the array returned from the - split - method of the - String -
object (the string primitive is internally type-converted to a String
object when it appears in an object context (the dot notation property
accessor)) only has one element, an attempt to read an element indexed
as 1 is identical to attempting to read a non-existent property of any
object; it will result in the - undefined - type, and assign that value
to the local variable without erroring.

Whether that second line of code is wise/safe depends on what is done
with the - url - variable afterwards (it should be tested to ensure that
it contains a viable value (which would not normally include -
undefined -) prior to any attempt to use it).

Richard.
Jul 23 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

35
3733
by: Raymond Hettinger | last post by:
Here is a discussion draft of a potential PEP. The ideas grew out of the discussion on pep-284. Comments are invited. Dart throwing is optional. Raymond Hettinger ------------------------------------------------------------- PEP: 323
21
1758
by: André | last post by:
Short version of what I am looking for: Given a class "public_class" which is instantiated a few times e.g. a = public_class() b = public_class() c = public_class() I would like to find out the name of the instances so that I could create a list of them e.g.
1
5152
by: Dotnet Gruven | last post by:
I've posted this in the adonet group, however it was suggested I might have better luck here.... ============================================================= I'm trying to use a typed dataset and ObjectDataSource binding to a SQLX db using a foreign key to filter the returned result set to display in a GridView. The error message in the subject line is generated when I try to bind the following GridView to the ObjectSource that follows...
7
1514
by: Garry Jones | last post by:
I have an entry page which can be used to key in data for ten people. My assigned variables for each field are in line with $personage1 $personage2 ....etc $personage9 $personage10 and so on. (I have 8 fields for every person, 80 values in all).
1
1236
by: Rob Meade | last post by:
Hi all, I thought I was being clever - no I'm doubting my abilities :o( My project reads in the content from an XML file, this is made up of a series of "courses", each "course" has a series of items. As I bring in the data I map it all off to my own classes, and add each Course class to my collection of courses.
4
1511
by: arak123 | last post by:
consider the following oversimplified and fictional code public void CreateInvoices(Invoice invoices) { IDbCommand command=Util.CreateDbCommand(); foreach(Invoice invoice in invoices) //lets say you have 200 invoices { command.CommandText+="INSERT INTO Invoice(Amount)
10
1698
by: geoff.houdmont | last post by:
Hi, I transfered one of my websites to another provider because I was asked to do that. The problem I have is it seems like the parameters after the ? are not readable in the page. Whereever I make an echo on that page there is nothing happening. php 5.0.5 is on the server Is there anyone who can help me?
0
1196
by: =?Utf-8?B?ZGF2aWQ=?= | last post by:
When I create a tree view control from XML document, I use XmlNode.Name in the node list iteration. But sometime, it is supposed that it got the element name. But sometimes it got the element name and first attribute together. For eaxmple, I use the following iteration code after creating the root from DOM.DocumentElement.Name. ----- private void AddNode2(XmlNode inXmlNode, TreeNode inTreeNode) { XmlNode xNode;
1
3793
by: aashishn86 | last post by:
i create dynamic rows using this function : function addRow() { var tbl = document.getElementById('applications'); var lastRow = tbl.rows.length; var iteration = lastRow; var row = tbl.insertRow(lastRow);
0
8638
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8578
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9120
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8998
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8831
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
5841
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4345
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
2278
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
1979
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.