Need javascript help
March 13, 2005 6:18 PM   Subscribe

I'm having a problem with some javascript, and comp.lang.javascript has not been much help. Any mefites care to try their hand?

I normally work on the middle tier objects, but have been tasked with working on some front end stuff. Unfortunately, my javascript skills are not up to stuff. Anyways:


I have a javascript file called 'PMP.WEBSITE/Scripts/Popups.js' (PMP.WEBSITE is the root of the website). In that file is the following function:

function OpenTutorial(sTutID)
{
var sURL = '../support/tutorials.aspx?tutid=' = sTutID;
var sProperties = 'center:yes;etc..';
window.showModalDialog(sURL, self, sProperties);
}

where ../support is actually PMP.WEBSITE/support.

Most of the website pages are located in sub folders from the root of the website. When editing is to be done on a record, a popup window is called from the main page. The popup pages are in another sub folder (i.e. pmp/review would be where review.aspx resides and the edit page would be located at pmp/review/popups). We give the user a tutorial icon to click on which calls the OpenTutorial function on a button click event.

Each page that calls the popup function has the following reference to .js file:
[script language="javascript" src="../scripts/popups.js" type="text/javascript"][/script] with the src attribute changing as required based on the page's location in the site

The problem is the tutorial popup page won't load properly when called from another popup page. I've tried variations of location.href, location.pathname, location.hostname etc.. but can't seem to get the pages to open correctly. The most common error i get is that the url is not correct. here is a sample of the urls being called by the function:

pmp/review/support/tutorials.aspx
pmp/feedback/support/tutorials.aspx
pmp/thirdparty/support/tutorials.aspx.

Any suggestions on how i can get the function to point to pmp/support/tutorials.aspx regardless of where the function is being called from? One reply from newsgroups said '/pmp.website/support/tutorials.aspx' but that didn't work.
posted by smcniven to Computers & Internet (10 answers total)
 
Your newsgroup reply was correct. An absolute address will absolutely specify a resource.

However, your tutorial.aspx pages apparently expect a tutid parameter. Is it possible that different tutorials expect different parameters, and return an empty page or error page id the expected parameter is not given?

The OpenTutorial function implies that its sTutID parameter includes a closing but not an opening single quotation mark. (This is sloppy.) When you are attempting to invoke other tutorial pages, are you "correctly" including the closing but not the opening single quotation mark?

A slightly more robust solution would be to replace your OpenTutorial function with this one (note that the replacement starts with a lower-case letter to adhere more closely to accepted Javascript style):

function openTutorial( sTutID, path ) // use default path unless other path is given
{
path = ( path ? path : "../support/tutorials.aspx" ) + "?tutid='" + sTutID;
var sProperties = 'center:yes;etc..';
window.showModalDialog(path, self, sProperties);
}

Some other notes:

The line:
var sURL = '../support/tutorials.aspx?tutid=' = sTutID;
is very suspicious, although probably legal. Is the second assignment operator really meant to be the catenation ("+") operator?
posted by orthogonality at 6:35 PM on March 13, 2005


Response by poster: orthogonality: thanks for the reply. that line is actually a transcription error, my keyboard shift key is acting up. It should read var sURL = '../support/tutorials.aspx?tutid=' + sTutID;

Also, our tutorial id numbers are actually global constants that point to a record in our database. For example, on pages that have a tutorial associated to them, we add the following to the image button that the user would click:

ibTutorial.Attributes.Add("onclick", pmp.base.globalconstants.tut_howto) where tut_howto equals "return OpenTutorial(10);"

it kludgy, but at this point in the game I don't have the luxery to make to many changes.

I'll try what you suggested when I get to work tomorrow, but I'll need a further explanation for the 'path ? path:) portion.
posted by smcniven at 7:21 PM on March 13, 2005


x = A ? B : C

is shorthand for

if (A)
  x = B;
else
  x = c;


So it uses the path variable if it's defined; if not, it uses "../support/tutorials.aspx".
posted by DrJohnEvans at 7:52 PM on March 13, 2005


Best answer: So are you invoking a tutorial with the wrong ID?

As far as my code, that's just the ternary operator (as seen in C, C++, Java, and JavaScript (and PHP too, I think)):

path = ( path ? path : "../support/tutorials.aspx" ) + "?tutid='" + sTutID;

x ? y : z

means the same as:
if( x )
y ;
else
z ;

except the ternary is a an expression that yields a value. If x is true, the value yielded is y, otherwise it's z

(Note that there are subtle differences between C and C++: in C++, if the second and third operands of the ternary are l-values, the result of the ternary is an l-value; in C, the result of the ternary is an r-value regardless; this need not concern us here.)

so:

path ? path : "foo"
yields path if path is defined and not the empty string, "foo" otherwise

we could re-write the statement:
path = ( path ? path : "../support/tutorials.aspx" ) + "?tutid='" + sTutID;

as

if( ! path ) path = "../support/tutorials.aspx" ;
path += "?tutid='" + sTutID;

But I like to minimize my writing.

We could also re-write it -- BUT ONLY IN JAVASCRIPT, not C, C++, or Java -- as
path = ( path || "foo" ) + "?tutid='" + sTutID;

Because JavaScript logical operators (unlike in real languages) yield their values in addition to short-circuiting. (This is a misfeature, as it breaks some time-honored idioms from real languages.)
posted by orthogonality at 7:59 PM on March 13, 2005


So plugging in '/pmp.website/support/tutorials.aspx' didn't work? What happened when you tried it? Could it be because you have the pmp.website directory mapped so the web server only sees it as 'pmp'?

Try substituting 'pmp/support/tutorials.aspx' in the sURL assignment line. If that doesn't work, try prepending a slash to it. Relative URLs are always problematic, and I strongly suggest you move away from them.
posted by cerebus19 at 8:53 PM on March 13, 2005


Because JavaScript logical operators (unlike in real languages) yield their values in addition to short-circuiting. (This is a misfeature, as it breaks some time-honored idioms from real languages.)

There are some who would disagree. Not to threadjack, I'm just sayin'...

You could, I suppose, make the argument that JavaScript should act more like the languages it borrows from, though.
posted by RikiTikiTavi at 10:54 PM on March 13, 2005


I think there's a really easy solution to this, If I understand your problem correctly...Let me see if I have this right. You have a root directory, and under this root directory you have a bunch of subdirectories. In each subdirectory, there's another subdirectory called popups that has the code for the various popup windows.

When you call the tutorial function from a page that is in one of the main subdirectories, everything is fine. But when you call the tutorial function from one of the pages that resides in the /something/popups directory, it doesn't work.

If what I said is correct, you should be able to remedy your problem by simply removing the ".." at the beginning of the variable sURL.

The ".." at the beginning of a URL means "up one directory from where you are." With your browser pointed to /reviews/reviews.aspx, ".." points to the root directory ("/"). But, with your browser pointed at /reviews/popups/edit.aspx, ".." points to /reviews (up one directory from /reviews/popups). I think what you want is no matter where you call the function from, you always want the browser to load /support/tutorials.aspx.

You might want to also convert the src attributes of your script tags to absolute URLs instead of relative ones. Then instead of having to change them "...as required based on the page's location in the site," You can use the same URL each time.
posted by mfbridges at 11:08 AM on March 14, 2005


RikiTikiTavi writes "You could, I suppose, make the argument that JavaScript should act more like the languages it borrows from, though."

Precisely, the principle of least surprise. Then if you need an "improved" logical operator, use "&&<" or "||<" as the tokens to mean, "logical operation yielding the right operand's value rather than a boolean truth value".

No surprises. Sticks-in-the-mud like me who are used to C can use the traditional token and get the traditional meaning, whiz kids with better ideas can use the new token and its new meaning.



As it happens, when I designed an (in house, proprietary) interpreted language myself, I was tempted to do precisely what Javascript does: have logical operators yield their right operand's value rather than true -- it seemed like a really cool trick. The temptation arises because you can get away with it in typeless languages, and interpreted languages lend themselves to being typeless. If I recall correctly, I did do it the JavaScript way at first (long before I knew JavaScript in fact did this), but soon realized that, because of the implicit type conversions typeless languages rely on, doing it could cause major problems.

Consider: most languages have an implicit conversion from bool to the language's integral type (or numeric type, as in the case of Javascript, which doesn't have a type that's strictly integral): true converts to 1, false to zero.
typeless languages additionally have a conversion from string type to bool: null to false, a non-empty string to true, and they split the difference on whether an empty but non null string is false.
typeless languages also have a conversion from string type to numeric type, (accomplished by a call to the C-language strtod or similar function)

Consider the following example: Unaware of Javascript's improvements, I decide to index an array based on a boolean value:

function pes() { return "3 dog night" ; }
function testA() { return true ; } ;

var response = [ "False", "True", "What the hell?" ] ;
var b = testA() && pes() ;
alert( response[ b ] ) ;


Now I expect b to have a boolean value, so it's either zero or one.
But pes() actually returns the string "3 dog night"
That string according to JavaScript semantics is true, but it's numeric value is three.
And I've just indexed beyond the end of my array.
posted by orthogonality at 1:08 PM on March 14, 2005 [1 favorite]


Response by poster: orthogonality:

I used a modified version of your suggestion up-thread. I did some poking around and found that the only tutorial with a problem was being called 8 times, 6 from a popup window. I added a property to the user control that modified the attribute being added to the image button. In the javascript i checked for a path being passed and voila! got it to work.

Many many thanks. that was my last outstanding bug to fix. hopefully tommorrow's round of QA goes well.
posted by smcniven at 6:20 PM on March 14, 2005


smcniven writes " I used a modified version of your suggestion up-thread. "

An invoice is in the mail. ;) Glad you got your problem fixed.
posted by orthogonality at 6:30 PM on March 14, 2005


« Older In the market for a moped / scooter   |   Where to find a dictionary of words that are... Newer »
This thread is closed to new comments.