runat="server" functions execute, but variables don't exist - ASP

I

iporter

Hi, throw the following example into a text file, save with an ASP
extension, and execute it in IIS6/7. Can anyone explain why Test 1
works fine, and Test 2 doesn't? Is it something to do with variable
scope?

Thanks,
Iain


<%@ language="javascript"%>
<script type="text/javascript" language="JScript" runat="server">
function myFunction() {return 'Hello Functional World'};

var myVariable = 'Hello Variable World';
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>Test</title>
</head>
<body>
<% Response.Write('Test 1: ' + myFunction());%>
<br />
<% Response.Write('Test 2: ' + myVariable);%>
</body>
</html>
 
E

Evertjan.

iporter wrote on 08 jan 2008 in comp.lang.javascript:
Hi, throw the following example into a text file, save with an ASP
extension, and execute it in IIS6/7. Can anyone explain why Test 1
works fine, and Test 2 doesn't? Is it something to do with variable
scope?

<%@ language="javascript"%>
<script type="text/javascript" language="JScript" runat="server">
function myFunction() {return 'Hello Functional World'};

var myVariable = 'Hello Variable World';
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>Test</title>
</head>
<body>
<% Response.Write('Test 1: ' + myFunction());%>
<br />
<% Response.Write('Test 2: ' + myVariable);%>
</body>
</html>

Let's first get the crap out:

<%@ language='javascript'%>
<script language='javascript' runat='server'>
function myFunction() {return 'Hello Functional World'};
var myVariable = 'Hello Variable World';
</script>
<% Response.Write('Test 1: ' + myFunction());%><br>
<% Response.Write('Test 2: ' + myVariable);%>

Because of the order of things, as I believe they are:

1 the functions are build
2 runats of the non globally declared language are run
3 the global code is run
4 runats of the globally declared language are run.

so the var is not jet executed when needed by the response write.
 
I

iporter

Evertjan, many thanks for cleaning up my example and offering an
explanation.

I am very keen to include parts of the prototype library on the server
side, and to declare objects ( var object = Class.create({...}); )
in an external .js file that I can then include on both the server and
client. This would, for example, allow me to use the same object to
write html to the page before it's sent to the client, and then
rewrite that html on the client-side.

Given your understanding of the order of execution, can you say
whether this is possible? For example, might there be a way to say,
'once the global code is run, do xyz'?

Thanks again,
Iain
 
E

Evertjan.

iporter wrote on 09 jan 2008 in comp.lang.javascript:

[please always quote on usenet, this is not email. others should be able
to follow the thread, and not all newsservers are getting postings in
reasonable chronological order to switch back. NEtiquette is sensible.]
Evertjan, many thanks for cleaning up my example and offering an
explanation.

I am very keen to include parts of the prototype library on the server
side, and to declare objects ( var object = Class.create({...}); )
in an external .js file that I can then include on both the server and
client. This would, for example, allow me to use the same object to
write html to the page before it's sent to the client, and then
rewrite that html on the client-side.

Given your understanding of the order of execution, can you say
whether this is possible? For example, might there be a way to say,
'once the global code is run, do xyz'?

Serverside you could just include the script file as a text include:

<%@ language='javascript'%>

<%
<!--#include virtual ="/libs/myJs.js"-->
%>

There is no advantage of calling libraries as done clientside, because
caching them is not usefull IMHO.
 
I

iporter

iporter wrote on 09 jan 2008 in comp.lang.javascript:

[please always quote on usenet, this is not email. others should be able
to follow the thread, and not all newsservers are getting postings in
reasonable chronological order to switch back. NEtiquette is sensible.]


I had wondered why we always had all this quoting cluttering up the
page - I will leave it from now on.

Serverside you could just include the script file as a text include:

<%@ language='javascript'%>

<%
<!--#include virtual ="/libs/myJs.js"-->
%>

There is no advantage of calling libraries as done clientside, because
caching them is not usefull IMHO.

No doubt I'm making a mistake here. However, I don't appear to be
able to use the include syntax within <% %> brackets. Assuming
test.js consists of the single line Response.Write('test');, the first
of the following examples yeilds 'Response.Write('test');' on the page
as text, and the second yeilds a blank page.

<%@ language="javascript"%>
<!--#include virtual="/test.js"-->

<%@ language="javascript"%>
<%
<!--#include virtual="/test.js"-->
%>

Are you sure this is possible?
 
E

Evertjan.

iporter wrote on 10 jan 2008 in comp.lang.javascript:

[please do not quote signatures on usenet, and quote only the bare
essential, skipping the rest]
No doubt I'm making a mistake here. However, I don't appear to be
able to use the include syntax within <% %> brackets. Assuming
test.js consists of the single line Response.Write('test');, the first
of the following examples yeilds 'Response.Write('test');' on the page
as text, and the second yeilds a blank page.

<%@ language="javascript"%>
<!--#include virtual="/test.js"-->

this works if test.js contains:

<%
Response.Write('2')
%>

==========================================
<%@ language="javascript"%>
<%
<!--#include virtual="/test.js"-->
%>

This does NOT work if test.js contains:

Response.Write('3')

But why not??????????
 
I

iporter

[please do not quote signatures on usenet, and quote only the bare
essential, skipping the rest]

Ok, please forgive any future netiquette faux-pas!
this works if test.js contains:

<%
Response.Write('2')
%>

==========================================


This does NOT work if test.js contains:

Response.Write('3')

But why not??????????

I think your example may confuse the issue - in the first, you the
include outside <% %> brackets, AND <% %> brackets in the .js file.
In the second, you have the include INSIDE <% %> brackers, BUT NO <%
%> in the .js file.

My tests show that regardless of contents of the .js file, the include
only works if outside angle brackets.

Let me share another example. Consider a javascript file 'test.js'
containing:
---------------------------
var myVariable = 'test'
Response.Write('-' + myVariable);


and an ASP file containing:
--------------------------------------------------------------------
<%@ language="javascript"%>
<script src="test.js" language="javascript" runat="server"></script>
<%
Response.Write('-' + myVariable);
%>


I would expect this would output '-test-test', but it outputs '-
undefined-test'.

Any further thoughts?

Thanks,
Iain
 
I

iporter

Let me share another example. Consider a javascript file 'test.js'
containing:
---------------------------
var myVariable = 'test'
Response.Write('-' + myVariable);

and an ASP file containing:
--------------------------------------------------------------------
<%@ language="javascript"%>
<script src="test.js" language="javascript" runat="server"></script>
<%
Response.Write('-' + myVariable);
%>

I would expect this would output '-test-test', but it outputs '-
undefined-test'.

Any further thoughts?

Thanks,
Iain

Another example:
-----------------------------------------------------
<%@ language="javascript"%>
<script language="javascript" runat="server">
var global = 'global';
Response.Write('1' + global);

function function1() {
Response.Write('2:' + global);
}
function function2() {
var local = 'local';
Response.Write('3:' + local);
}
</script>
<%
Response.Write('4:' + global);
Response.Write(function1());
Response.Write(function2());
%>

This produces the output:
 
N

news

Evertjan, many thanks for cleaning up my example and offering an
explanation.

I am very keen to include parts of the prototype library on the server
side, and to declare objects ( var object = Class.create({...}); )
in an external .js file that I can then include on both the server and
client. This would, for example, allow me to use the same object to
write html to the page before it's sent to the client, and then
rewrite that html on the client-side.

Given your understanding of the order of execution, can you say
whether this is possible? For example, might there be a way to say,
'once the global code is run, do xyz'?

Execution order of .asp files is not that obvious - particularly
blocks in <% %> and in <script runat="server"> execute at different
times - and not in source order.
See http://classicasp.aspfaq.com/general/does-order-matter-when-using-different-languages-in-asp.html
for details, but basically it's
1. scripts in non-default language
2. scripts using <% %>
3. scripts in default language

You can include code in two ways, using <!-- #include --> and
specifying a src for <script runat="server">

#include must be outside of a <% %> block (the SSI processor seems not
to see them there, even though they are processed first before any
script executes), so either in the HTML body or within a <script
runat="server"> block.

If the #include is in the body, your js code just gets output to the
client. No good.
Using #include in the <script> is exactly equivalent to using a src
attribute on the <script>, either way it is executed after any <% %>
blocks.

So the only way you'll get this to work is to ONLY use <script> blocks
and eschew any <% %>, even for quick document.writes.

You could possibly set <%@ language="vbscript"%> and use vbscript to
write to the client (it'll see your js objects just fine, you just
need to change the syntax), whereupon your <script> blocks will have
executed already.


That said, I've no idea if prototype.js will work serverside - it's
bad enough within a browser, no idea what will happen to it if it
suddenly finds itself in an environment that doesn't have a DOM.
 
N

news

Another example:
-----------------------------------------------------
<%@ language="javascript"%>
<script language="javascript" runat="server">
var global = 'global';
Response.Write('1' + global);

function function1() {
Response.Write('2:' + global);
}
function function2() {
var local = 'local';
Response.Write('3:' + local);
}
</script>
<%
Response.Write('4:' + global);
Response.Write(function1());
Response.Write(function2());
%>

This produces the output:

Altering the script ever so slightly (and yes I've deliberately left
out some semicolons for reasons that will become clear:

<%@ language="javascript"%>
<script language="javascript" runat="server">
var globalvar = 'global';
Response.Write('1' + globalvar);

function function1() {
Response.Write('2:' + globalvar);
}
function function2() {
var local = 'local';
Response.Write('3:' + local);
}
</script>
<%
Response.Write("4:" + globalvar)
Response.Write(function1())
Response.Write(function2())
%>

You do indeed get 4:undefined2:undefined3:local1global

Note the execution order - the function calls in the <% %> block take
place before those in the <script> block. I hadn't expected the
functions (or their local vars) to be defined at all, but clearly they
are.

Now change the first line to
<%@ language="vbscript"%>

You will get 1global4:global2:global3:local

because the script block is nolonger in the default language, it
executes first, defining the global vars, but also executing the first
response.write as a sideeffect.

Now you see how mixing <% %> blocks and <script> blocks can lead to
madness and nasty side-effects.

The only way I can think of to achieve what you want to do is to use
#include to insert the files server-side, put <% and %> around all
your javascript and then write a filter for your webserver that strips
them when the files are requested over HTTP by a client
 
S

stevenmoberg

Altering the script ever so slightly (and yes I've deliberately left
out some semicolons for reasons that will become clear:

<%@ language="javascript"%>
<script language="javascript" runat="server">
var globalvar = 'global';
Response.Write('1' + globalvar);

function function1() {
Response.Write('2:' + globalvar);
}
function function2() {
var local = 'local';
Response.Write('3:' + local);
}
</script>
<%
Response.Write("4:" + globalvar)
Response.Write(function1())
Response.Write(function2())
%>

You do indeed get 4:undefined2:undefined3:local1global

Note the execution order - the function calls in the <% %> block take
place before those in the <script> block. I hadn't expected the
functions (or their local vars) to be defined at all, but clearly they
are.

Now change the first line to
<%@ language="vbscript"%>

You will get 1global4:global2:global3:local

because the script block is nolonger in the default language, it
executes first, defining the global vars, but also executing the first
response.write as a sideeffect.

Now you see how mixing <% %> blocks and <script> blocks can lead to
madness and nasty side-effects.

The only way I can think of to achieve what you want to do is to use
#include to insert the files server-side, put <% and %> around all
your javascript and then write a filter for your webserver that strips
them when the files are requested over HTTP by a client

I've recreated the Prototype v1.6 on the server and it comes in very
handy. Gives you OOP properties in classic ASP.

First, within the script runat="server", the methods are processed
first, but in-line code (to include variable declaration) is not
executed until the end.

Try the following
<script language="javascript" runat="server">
var globalvar = 'global';
Response.Write('1' + globalvar);
function initVars(){
globalvar = 'G.L.O.B.A.L.';
}
function function1() {
Response.Write('2:' + globalvar);
}
function function2() {
var local = 'local';
Response.Write('3:' + local);
}
</script>
<%
initVars()
Response.Write("4:" + globalvar)
Response.Write(function1())
Response.Write(function2())
%>
 
T

Thomas 'PointedEars' Lahn

I've recreated the Prototype v1.6 on the server and it comes in very
handy. Gives you OOP properties in classic ASP.

What the authors of Prototype and you failed to observe is that J(ava)Script
is by default an object-oriented programming language. It just uses
prototype-based instead of classed-based inheritance.

http://javascript.crockford.com/javascript.html

Furthermore, with ASP .NET server-side you already have a class-based
object-oriented programming language available, JScript .NET (JScript 7.0+),
which implements features of Netscape's latest proposal for Edition 4 of the
ECMAScript Specification.

Your misguided attempt to port an already faulty approach and error-prone
junk code to the server side is not going to do any good. Search the
archives for discussions about Prototype.js.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top