PDA

View Full Version : Problem with onLoad getlanguage() (It doesn't do it)



Yorixz
05-02-2005, 07:13 AM
Hello,

I made (well, put together mainly, I'm not that great with javascript) a script that is *supposed* to only show a layer to someone with the language nl-NL (Dutch) and otherwise show another layer. (To be able to show relevant data)

The main problem is that the script just does nothing; I dont get errors, warnings or whatever; it just doesn't do anything. I expect it's a problem with the "body onload" code but I can't really find the problem.

Thanks for your time; hopefully someone can help me with this, I will be gratefull :) (I already posted this a week ago on another (dutch) tech forum but they didn't really see what could be wrong)



<head>
<script type="text/javascript">
function getlanguage()
{
language = navigator.browserLanguage;
if (language) { language = language.substring(0,2); } else { language = "z"; }
switch (language)
{
case "nl" :
MM_showHideLayers('Layer1','','show');
break;
MM_showHideLayers('Layer2','','show');
}
}
</script>
</head>

<BODY onLoad="getlanguage()">
<!-- the 2 layers, the data inside them and their color/size doesn't matter for the script, only did it to keep it a bit clear -->
<div id="Layer1" style="position:absolute; left:22px; top:181px; width:100px; height:50px; z-index:2; background-color: #FFFF00; layer-background-color: #FFFF00; border: 1px none #000000; visibility: hidden;"><font color="#FF0000">Layer1</font></div>
<div id="Layer2" style="position:absolute; left:22px; top:81px; width:100px; height:50; z-index:1; background-color: #FF0099; layer-background-color: #FF0099; border: 1px none #000000; visibility: hidden;">Layer2</div>
</BODY>


I ran a Javascript debug in Opera and got this error:
Event thread: onload
Error:
name: ReferenceError
message: Statement on line 9: Reference to undefined variable: No such variable 'MM_showHideLayers'
Backtrace:
Line 9 of inline#1 script in file://Test.htm
MM_showHideLayers("Layer1", "", "show");
In unknown script
getlanguage();
At unknown location
{event handler trampoline}
(It seems like "MM_showHideLayers" isn't a good value, but what would be the correct replacement?)

Thanks for your help!

Yorixz
05-02-2005, 11:56 AM
I did it like this now:

<html>
<head>
<script type="text/javascript">
var ie4 = (document.all) ? true : false;
var ns4 = (document.layers) ? true : false;
var ns6 = (document.getElementById && !document.all||window.opera) ? true : false;
var w3c = (document.all && w3c) ? true : false;
function showlayer(lay) {
if (ie4) {document.all[lay].style.visibility = "visible";}
if (ns4) {document.layers[lay].visibility = "show";}
if (ns6) {document.getElementById([lay]).style.display = "block";}
if (w3c) {document.getElementById([lay]).style.display = "block";}
}
function getlanguage()
{
language = navigator.browserLanguage;
if (language) { language = language.substring(0,2); } else { language = "z"; }
switch (navigator.browserLanguage)
{
case "nl" :
showlayer('Layer1');
break;
default:
showlayer('Layer2');
}
}
</script>
</head>

<BODY onLoad="getlanguage()">
<div id="Layer1" style="position:absolute; left:22px; top:181px; width:100; height:50; z-index:2; background-color: #FFFF00; layer-background-color: #FFFF00; border: 1px none #000000; visibility: hidden;"><font color="#FF0000">Layer1</font></div>
<div id="Layer2" style="position:absolute; left:22px; top:81px; width:100px; height:50; z-index:1; background-color: #FF0099; layer-background-color: #FF0099; border: 1px none #000000; visibility: hidden;">Layer2</div>
</BODY>
</html>

It works perfectly in IE and Opera now but I can't seem to get the right value's for FireFox which is kinda important; I'm hoping someone can help me with it.

mwinter
05-02-2005, 02:03 PM
Before I start, I'd like to point out that critism in this post may not necessarily be aimed at you, but more likely 'cult' beliefs that follow client-side scripting and Web authoring.


I made [...] a script that is *supposed* to only show a layer to someone with the language nl-NL (Dutch) and otherwise show another layer.If you really want to show language-specific content, the best way would be to use content negotiation. This would serve different resources based upon the Accept-Language header sent by user agents. You can Google for more information. The Apache Server documentation is particularly good.

I'll skip the rest of the first post as it isn't really relevant now.


var ie4 = (document.all) ? true : false;
var ns4 = (document.layers) ? true : false;
var ns6 = (document.getElementById && !document.all||window.opera) ? true : false;
var w3c = (document.all && w3c) ? true : false;This form of "detection" (all forms, actually) is flawed. IE is not the only user agent to support the all collection, nor is NN4 the only user agent to support the layers collection. The identifier, ns6 is a misnomer as many user agents will produce assign true, and I have no idea how w3c is useful as it will be false in every single scriptable user agent.

There is no need to determine what a user agent is. Your only concern should be what it supports. The functions below demonstrate this principle.


var getRef = isGenericObject(document.getElementById)
? function(id) {
return document.getElementById(id);
}
: function() {return null;};

function isFunction(object) {return 'function' == typeof object;}
function isGenericObject(object) {return isObject(object) || isFunction(object);}
function isObject(object) {return !!object && ('object' == typeof object);}
function isString(object) {return 'string' == typeof object;}

function setDisplay(element, value) {var style;
if(isString(element)) {element = getRef(element);}

if(isGenericObject(element) && isGenericObject(style = element.style)) {
style.display = value;
}
}The assignment to getRef is fairly simple. First, the getElementById property is examined: if it is an object or a function (IE considers it an object - don't ask me why), it is assumed that the host supports this particular DOM method. A wrapper is then created that calls gEBI. If the method is not supported, the wrapper will always return null. Whilst it doesn't provide a reference, it does prevent errors from calling non-existent functions. This approach could be extended to include the all and layers collections, but the only user agents that need these fallbacks are generally considered obsolete. If you're unfortunate enough to have visitors with these browsers, by all means add support. If not, I wouldn't bother.

The isX functions are just for support. They aren't really worth any time.

Ths setDisplay function accepts either a string or an object as its first argument. If this argument is a string, it assumes an id and uses getRef to obtain an object reference. If an object reference is available and it provides a style object, the display property is changed. This mechanism will work in various user agents including IE4 (if an object is passed, or getRef is extended), but not NN4. The best approach for solving the latter issue is probably:


function setDisplay(element, value) {var style;
if(isString(element)) {element = getRef(element);}

if(isGenericObject(element)) {
if(isGenericObject(style = element.style)) {
style.display = value;
} else if(isString(element.visibility)) {
style.visibility = ('none' == value) ? 'hide' : 'show';
}
}
}with an extension to getRef. In both versions, the use of isGenericObject may be excessive, with isObject being sufficient. I don't have access wide enough range of user agents to decide that, though.

As for determining the language client-side, Gecko-based user agents use the language property, not browserLanguage. Using the isString and isObject functions defined above:


function getLanguage() {
if(isObject(this.navigator)) {
if(isString(navigator.language)) {return navigator.language;}
if(isString(navigator.browserLanguage)) {return navigator.browserLanguage;}
}
return 'unknown';
}Note that this doesn't necessarily reflect the language preferences of the user; both properties return the language version of the user agent itself. For example, a Welsh user might prefer Welsh pages but can only get hold of an English user agent. This, coupled with reliability of a server-side solution, is why the latter is preferred.


switch(getLanguage().substring(0, 2)) {
case 'nl': setDisplay('english', 'none'); break;
default: setDisplay('dutch', 'none');
}Note that the code above reverses your logic. You shouldn't rely on a script to reveal information hidden by CSS. If the features required by the script are not available, the user will not be able to get that information. Instead, allow things to be visible initially, and hide them via a script.

Finally, you really shouldn't let Dreamweaver (or any WYSIWYG software) generate junk like those "layers". It's ugly, unnecessary bloat. I'd need a URL for an alternative suggestion.

Mike

Yorixz
05-02-2005, 02:47 PM
Thanks for your reply; I dont totally understand your post, my programming knowledge is a way to limited sadly. Myself I'd prefer to use php, pretty easy to do it then, sadly the header of IPB (2.0.0) isn't parsed for php; it can only contain client sided data thus I'm limited to that. (iFrames aren't an option since AdSense won't support that)


If you're unfortunate enough to have visitors with these browsers, by all means add support. If not, I wouldn't bother.
My visitors excist of about 70% IE, 25% FireFox, I mainly want to aim on that ones but I'm totally out of idea's of how to do it.

mwinter
05-02-2005, 06:12 PM
I dont totally understand your post, my programming knowledge is a way to limited sadly.If you have specific areas of interest, I could try to explain things differently. It would be helpful to know what knowledge you do have, and if there was anything specific that you didn't understand.

That said, it's not really necessary to understand what I wrote, just beneficial if you have any interest in scripting. The code that I posted in the getRef- and getLanguage-containing blocks will form the basis of a replacement of your code. The code in the last block demonstrates one way to use it. Perhaps a better demonstration would be:


/* The regular expression below checks for
* a language code that matches 'nl',
* optionally followed by '-XX' (a hyphen
* and two uppercase letters).
*/
if(/nl(-[A-Z]{2})?/.test(getLanguage())) {
/* Code in this branch will be executed
* if the language code matches...
*/
} else {
/* ...and when code is executed here
* should be obvious. :p
*/
}A switch statement is only necessary with lots of options based on the same value. Just the one specified value (nl) is a bit pointless.

Mike

Yorixz
05-03-2005, 07:18 AM
It's crystal clear now for me, thanks a lot. I'm going to try and play some with this code ;)