Switch website language JS/JSON - javascript

I'm building a website and here is basically what I want to achieve using JavaScript:
if browser language = fr then get the text from languageFr.json
else get the text from languageEn.json
Here is what my code looks like for now:
My JSON
{
"h2": "random title",
"p": lorem ipsum
}
My JavaScript, in the head of index.html
<script text="text/javascript">
var lang;
function detect() {
var userLang = navigator.language || navigator.userLanguage;
if (userLang == "fr") {
lang = JSON.parse("languageFr.json");
} else {
lang = JSON.parse("languageEn.json");
}
}
$(document).ready(detect());
</script>
And then in my HTML's body:
<h2><script>document.write(lang.h2);</script></h2>
However this does not seem to work. Chrome's console tells me lang is undefined.
What am I doing wrong?
Thank you

The code <h2><script>document.write(lang.h2);</script></h2> executes before document ready. That's why your detect method has bot been called at the moment and lang has not been initialized.
You use JSON.parse method in a wrong way

Well, one thought is that the Javascript in this block
<h2><script>document.write(lang.h2);</script></h2>
is executing before the function has run.
That Javascript will execute as soon as the browser reaches it; the browser will pause parsing the page to do this. However, your detect function looks like it's waiting for the document ready event to run.
So, the document.write() call happens before the detect() method is called, and lang has no value.

Egor4eg is correct about the problem (actually most of the answers are). I'd advise you to use a different method for filling in any elements that should have language-specific text. Here's a possibility.
<div class="i18nstring" data-message="h2"></div>
//Put this at the bottom of your detect() function (so it's only called after $ ready)
$('.i18nstring').forEach(function() {
$(this).text( lang[this.dataset.message] );
}
That might need just a little bit more work (mostly on the data-message thing) to be fully cross-browser compatible, but JQuery can help with that. Note that each i18nstring node does not have to be a div.

Related

Javascript execution order via HTML5 script tag with async attribute

Aloha. I have been working on a script and though I understand documentation of each constituent of the problem (and have looked over many other questions on SO), I don't understand this specific behavior in practice. Please be aware that the following code is an abbreviated subset that isolates the specific issue. Here is async.html:
<!doctype html>
<html><head><script type="text/javascript" src="asyncTest.js" async="true"></script></head>
<body><ul id="menu"><li>one</li><li>two</li><li>three</li></ul></body></html>
And here is asyncTest.js:
var _site = function() {
var load = function() {
var menuCategory = document.getElementById('menu').getElementsByTagName('li');
for(var i=0; i<menuCategory.length; i++) { alert(i+'['+menuCategory[i]+']'); }
};
return { load:load };
}();
window.addEventListener('load',_site.load(),false);
The problem is that without the async attribute in the <script> tag, this code does not properly store the <li> elements into menuCategory, as though it were running prior to the DOM being loaded (even though I thought it should fire after the entire window "object" loads). I find that strange because I am using the addEventListener() to try and run this only after the whole thing has been loaded (and it appears to run at the appropriate time in Chromium, FF, and Opera -- at least what appears to be the "appropriate time"). If anything, I think that the opposite would cause this behavior.
Can someone explain this, preferably using the old Einstein "explain it like you're explaining it to a six-year-old"? I'm obviously missing something in my reading. Thanks!
As mentioned by RobG in the comments, the problem here is that using _site.load() (with parenthesis after the call) is causing the function to be executed AND THEN assigned to the onload event. The way to correct this behavior to the desired functionality is to call it without the parenthesis: _site.load (or _site().load).

Javascript not storing variables at all. Every variable "undefined"

I was wondering if anyone could help me. The problem is javascript isn't storing any variables and is acting up.
<script type="text/javascript" language="javascript">
var name = document.getElementById('text_field').value;
var test = "foobar";
function test_function(){
alert("hello"+test);
}
alert('test '+test);
</script>
The second alert doesnt happen at all, and when i click on the button to trigger the test_function() it alerts out "helloundefined" .
I just don't know what to do, it was working fine then all of a sudden it stopped. I should mention that this is on a php page but that shouldn't make a difference.
If there is no element with the ID text_field, the rest of the code will not run.
try changing:
var name = document.getElementById('text_field').value;
to
var name = document.getElementById('text_field').value || "some default value;
OR
var name;
if(document.getElementById('text_field')) {
name = document.getElementById('text_field').value
} else {
name = "some value"
}
Without seeing the rest of the code, most likely the culprit is this line:
var name = document.getElementById('text_field').value;
If the script block is run before 'text_field' exists, you get an error and the rest of the javascript doesn't execute. The result is that you don't see the alert, and the test variable is never set. You need to call the code after the DOM exists, either by running it in onload (or a ready function in jQuery) or by putting the script block at the end of the page.
Move that script block to bottom of the page. text_field does not exist yet. If you're debugging in a browser, use Chrome or Firefox and make use of the "Console" window in the dev tool bar. It'll tell you things like this...

JSP Parsing url and matching key words

Here is my question, I am using jsp script, trying to match a key word in requesting url and do something:
<script>
$url = '${pageContext.request.requestURL}';
if("${fn:contains(url, 'key')}" == true){
...
}
....
But this doest work... I am not sure where the problem is but I want it to be like when url contains this string, go in to the if condition.
Thank you
You are mixing JSP/EL and JavaScript as if they run in sync. This is wrong. JSP/EL runs in webserver and produces HTML code which get executed in webbrowser. JavaScript (JS) is part of the generated HTML code and runs in webbrowser only.
You need to do it either fully in JSP/EL, or fully in JavaScript. You can use JSP/EL to dynamically generate JS code which get later executed when the page arrives at browser. Rightclick page in browser, do View Source to see what JSP/EL has generated. You should not see any line of JSP/EL. You should only see HTML/JS code. It's exactly that JS code which get executed then.
You're using a JSP EL function to test a JS variable which isn't in the variable scope at that moment at all. This is not going to work. It can only test JSP/EL variables.
Here's how you could do it in pure JS:
<script>
var url = window.location.href;
if (url.indexOf('key') > -1) {
// ...
}
</script>
If you really insist in doing it using JSP/EL, you could do as follows:
<script>
var url = '${pageContext.request.requestURI}';
if (${fn:contains(pageContext.request.requestURI, 'key')}) {
// ...
}
</script>
This will then generate the following JS code (rightclick page in browser and View Source to see it):
<script>
var url = '/some/uri';
if (true) {
// ...
}
</script>
But this makes no sense. Whatever functional requirement you need to solve, you need to think twice about the right approach. Feel free to ask a new question about solving the concrete functional requirement the proper way.
If you want a parameter that the page was requested with, use ${param.paramName}. So in this case ${param.key}. See implicit objects in the docs. And if you just want to check it has a value try ${not empty param.key}.

Running javascript code called by AJAX

My site uses pushState to load pages. I have one issue, I want to use javascript on one of the pages but can't because it loads everything with AJAX. So what do I do? I've been told something about "parseScript" but I can't find enough information on it.
--Example--
I load using AJAX
On my page I have this script:
<script type="text/javascript">
function go(){
alert('1');
}
</script>
GO!!!
Nothing happens.
--Edit--
If I open up Google Chrome's debugger:
"Uncaught ReferenceError: go is not defined"
And the <script> tag is no where to be found
Browsers don't seem to parse <script> element content that's added to the document via targetElement.innerHTML. That's probably what you're running into.
The best solution is to use a well-tested framework like jQuery for solving problems like this. They've already figured out how to safely and correctly inject scripts into the DOM. There's no sense re-inventing the wheel unless you absolutely can't spare the bandwidth for the library.
One way you might fix this is by separating the JavaScript from the HTML in the Ajax response, either by issuing two requests (probably slower) or by structuring your JavaScript and HTML within a JSON object (probably harder to maintain).
Here's an example:
<script>
function load_content(){
var req = new XMLHttpRequest();
req.open("GET", "ajax.json", true);
req.onreadystatechange = function (e){
if (req.readyState === 4){
if (req.status === 200){
// these three lines inject your JavaScript and
// HTML content into the DOM
var json = JSON.parse(req.responseText);
document.getElementById("target").innerHTML = json.html;
eval(json.js);
} else {
console.log("Error", req.statusText);
}
}
};
req.send(null);
}
</script>
Load more stuff
<div id="target"></div>
The document ajax.json on the server looks like this:
{
"js": "window.bar = function (){ console.log(\"bar\"); return false; }",
"html": "<p>Log a message</p>"
}
If you choose this route, you must either:
namespace your functions: MyApp.foo = function (){ ... };, or
explicitly add your functions to the global namespace: window.foo = function (){ ... };.
This is because eval executes in the current scope, so your function definitions inherit that scope and won't be globally available. In my example, I chose the latter option since it's just a trivial example, but you should be aware of why this is necessary.
Please make sure to read When is JavaScript's eval() not evil? if you decide to implement this yourself.
I think it would be helpful to have a little more detail as to how the Ajax call is made and the content is loaded. That said, a few things of note:
the syntax for javascript:void() is invalid. It should be javascript:void(0). For that matter, using javascript:void() on the href of an anchor tag is generally bad practice. Some browsers do not support it. If you must use an tag, set the href to # and add "return false;" to the click event.
you should use a button tag instead of the a tag in this case anyway.
given what you have provided, it should work (aside from the syntax error with void())
If I were to do this I would use jquery's load call.
That takes care of putting an ajax call ,and parsing tags for script/no-script elements.
IF you dont wanna use jquery, I would suggest you go online and find what the jquery load method does and implement the same as an event handler for your ajax call.

Detect what javascript function is changing a page element on load?

I have lots of jquery that is running on page load and it's causing one of my elements to disappear (making it style=display:none;). I'm guessing the jquery hide() function is being applied to this element by mistake, but I can't find out which statement is causing it.
Is there any javascript,firebug,etc function or tool that will essentially act as a breakpoint/listener for the html element (perhaps one I can run in my browser)? It would be great to see what function is affecting that element on page load.
Hah! I just found the answer I wanted. Firebug has a "break on mutate" function on the HTML tab that will show you what line in the javascript file is changing an html element. It is in Firebug 1.5 and the new 1.5.2 update released today moved the icon, so I noticed it and found it purely by luck!
http://www.softwareishard.com/blog/firebug/firebug-15-break-on-next/
Thanks for your attempts guys!
You can find where the element is being accessed with getters/setters. However, the setter method doesn't seem to work with chrome... it works with the latest version of minefield [firefox beta], though... so you could test it out I guess =)
myElement.style.__defineSetter__("backgroundColor", function(val)
{
var cur = arguments.callee;
var callLog = "";
while(cur != null)
{
callLog = cur.caller + "\n" + callLog;
//alert(cur.caller);
cur = cur.caller;
}
alert(callLog);
}
);
Oh, but it won't let you actually "set" the variable. to do that, you define a dummy variable and set that. Then, when you define your getter [with __defineGetter__] you return that value

Categories