Re: Javascript problems from a lightweight - xmlhttprequest and html fragments



Phil_Harvey wrote:

function insert(url,id)
{
var element = document.getElementById(id)

End this assignment with an ";" (code style, avoids unexpected
effects with automatic semicolon insertion by the script engine),
and do a feature test before you call the method.
<URL:http://pointedears.de/scripts/test/whatami#inference>

try
{
req = new XMLHttpRequest();

This will fail in IE < 7. The entire code will break in IE < 5,
despite of and because of the try..catch exception handling.

req.open('GET', url, false);

You want to consider asynchronous requests, as synchronous ones
lock up the user agent:

var returnedText;
...
req.open('GET', url);
req.onreadystatechange = function()
{
if (req.readyState == 4 && /^2|0/.test(req.status))
{
returnedText = req.responseText;
req = null;
}
};

req.send(null);

(Of course you will have to queue commands somehow then.)

req.send(null);
returnedText=req.responseText;

The identifier is not declared so far, therefore a property of the Global
Object is modified or created. Bad style.

}
catch(e)
{
returnedText='Unable to retrieve data on that currently'

;

}

The better approach is not to running the risk of throwing the exception,
but to do a feature test before you use the feature.

// in global context
var _global = this;

// in global or local context
function isMethod(a)
{
var t;
return (a && ((t = typeof a) == "function" || t == "object"));
}

var req = null;

if (isMethod(_global.XMLHttpRequest))
{
req = new XMLHttpRequest();
if (req)
{
req.open('GET', url, false);
req.send(null);
var returnedText = req.responseText;
}
}
else
{
// ActiveX/COM solution for IE,
// see http://jibbering.com/2002/4/httprequest.html
}

if (req)
{

if (lastCommand=='')

It would be simpler if you used

if (!lastCommand)

This will yield `true' if lastCommand was not initialized yet or is the
empty string, `false' otherwise (as it is supposed to be a string value).

{
element.innerHTML = previous+req.responseText;

Note that `innerHTML' is a proprietary property, so at least you want to
feature-test it before you use it. At most, you want to target Web
standards first, and use `innerHTML' and other proprietary features only
as fallback.

if (!(url=='frag_home.htm'))

if (url != 'frag_home.htm')


{
previous+=returnedText;

Push to and join an array instead.

var a = new Array();
...
a.push("...");
...
... a.join("") ...

}
}
else
{
var extra = '<table width="80%" border="0" cellpadding="0"
cellspacing="0" bgcolor="#000000">' +

Don't use presentational attributes anymore; use CSS. And if you provide
the background color, always provide the foreground color, and vice-versa.

<URL:http://www.w3.org/QA/Tips/color>

'<tr><td>> ' + lastCommand + '</td></tr>' +
^[1] ^^[2]^
[1] Is this by intention?

'</table>' + returnedText;
^^[2]

[2] You must escape ETAGO delimiters (`</'), preferably with `<\/',
iff you use them within the HTML `script' element.

element.innerHTML = previous + extra

First concatenate (or join) the string values, then assign them to
`innerHTML'.

if (!(url=='frag_home.htm'))

See above.

{
previous+=extra

; and see above.

}
}

}

Don't use tabs to indent code, at least not when you post it; use
multiples of two spaces.

<form id="frmCommandLine" name="Command Line" method="post"

Probably your `form' element does not need an ID or a name. And, as I said,
if you omit the `action' attribute, the resulting markup is not Valid.

style="background-color:#000000">

So you know about CSS after all. See above.

<label>&gt;

A `label' element does not make much sense if it is not specified what it
is labeling. Give your input element an ID, then use

<label for="input_id">label:</label> <input ... id="input_id" ...>

<input name="tf_command" type="text"
style="background-color:#000000; border:none; color:#FFFFFF;
font:'Courier New', Courier, monospace';"

You want to move that to a declaration in a `style' element or to an
external style*** to avoid such spaghetti code. Remove any newlines in
the attribute value, and declare the default style*** language, if you
don't:

<meta http-equiv="Content-Style-Type" content="text/css">

onchange="doCommand(tf_command.value);tf_command.value=''" size="100"

This is also something that should be moved into a `script' element or
an external script resource to avoid spaghetti code.

Remove any newlines from the attribute value, and declare the default
scripting language, if you don't:

<meta http-equiv="Content-Script-Type" content="text/javascript">

/>

Your markup is (currently invalid) HTML, not XHTML. In HTML, "<.../>"
equals "<...>&gt;" (HTML SHORTTAG syntax). Besides, IE does not support
XHTML, and you do not need it here, so serve HTML 4.01 as text/html, and
omit the trailing "/" for elements with empty content.

</label>

As I said, this `label' element does not make any sense.

</form>

As you can see your guess was correct I am not using the 'action'
attribute of the form.

Which is not Valid. <URL:http://validator.w3.org/>

THe behaviour may be what the user expects in a normal webpage, but that
is not what I am trying to create. I need to dynamically add fragments of
HTML to the main page as the user types commands.

As I said, you want to cancel the submit event of the form if the required
script support is present. If not, the server-side application should take
over.

When you say I should have a server side solution, how do you mean?
The forms action attribute should call ....what exactly? [...]

For example:

function makeXMLHttpRequest()
{
var req = null;
...
return req;
}

<form action="foobar.php" onsubmit="return !makeXMLHttpRequest();">
...
</form>

Where you suggest that I should use a frameset, are you suggesting that
I load the jscript in one frame then make it alter the other frames, so
the main frameset execution context does not get refreshed each time?

Exactly.

Since you probably want a server-side application as fallback, and
apparently you have a `form' element already, that is done already.
All you need to do now is to process the submitted information.

I am afraid I don't follow. I am not so familiar with the difference
between server side and client side with jscript.

JScript != JavaScript. Besides, although possible, the corresponding
server-side application does not need to be written in any ECMAScript
implementation. I preferred PHP, for example.

I already have a
form, yes, but that is part of the page the client sees.

So either you do not want to use a `form' element, only form controls (which
is perfectly Valid); AFAIS, nothing is submitted then if one presses
Return/Enter. Or, if you want to use the form it, which I recommend,
following the concept of graceful degradation, you should provide for a
server-side fallback in case one of the features used for client-side
processing of the input is not available.

[...] thank you very much for your help

You are welcome.


PointedEars
.