Language redirection with javascript - javascript

I have to build a multi language website in Business Catalyst(not my choice), my only option for the language switcher and the fore the link rel="alternate" is JS.
After a lot of trial and error I got this to work:
<script type="text/javascript">
document.write("<ul>");
document.write("<li>English</li>");
document.write("<li>French</li>");
document.write("<ul>");
</script>
The only problem is that it is slow and probably badly written.
It is there a better way to write the code? Maybe one that load faster and possibly using jQuery?
Thank you very much in advance for your help
Antonio

You can include the following in your html.
<ul id="multilang">
<li>
English
</li>
<li>
French
</li>
</ul>
Then use jQuery to manipulate the url.
$(function () {
$.each($("#multilang a"), function () {
$(this).attr('href', $(this).attr('href') + location.pathname);
});
});

I generally recommend avoiding string based dynamic html since it tends to be hard to maintain over time. Instead I recommend going for some sort of template based solution. There are a few options, but one popular framework is KnockoutJs
http://knockoutjs.com/

1- A a starter. document.write will replace the whole DOM with your list, therefore, I suggest appending the list to an html element.
2- To improve performance, try to have less function call to reduce overhead. Option 1: prepare the html and write it in one string, then append that string. E.g.
var lang = "<ul><li>stuff...</li><li>other stuff....</li></ul>";
Or, for readability,
lang = "<ul>";
lang = "<li>English</li>";
lang = "<li>French</li>";
lang = "</ul>";
Then
$("#change_lang").html(lang);//change_lang is a div <div id="change_lang"> that you have prepared to put the links inside.
3- Maybe you can load the html from your server directly, without having JS to print it on screen for you. Put it in .html page (I'm not sure about your page structure, therefore, I cannot know why this approach might not be suitable for you) but loading html directly without waiting for JS and JQuery to load will make display much faster.
<ul>
<li>English</li>
<li>French</li>
</ul>
4- Also try to put your JS code in separate files, and then minify them to reduce size and hence loading time. Having JS in separate files allows the browser to cache them and eliminate the need to load them every time. Search for PageSpeed to show you various ways to improve your site performance.

Related

Using html tags vs javascript create element

I'm trying to get a grasp on html and javascript and wondering if there is a functional difference between using document.createElement(some_tag) vs <some tag></some tag>. I can see how using javascript's create element might make it easy to create the specific element over and over in different pages/sections of the website (instead of copying and pasting and making your code bulky). But is it bad practice/bad for memory or something to use create element.
For instance, consider the following code:
function createhtml() {
var li1 = document.createElement("li");
var text1 = document.createTextNode("First List Item");
li1.appendChild(text1);
var ul1 = document.createElement("ul");
ul1.appendChild(li1);
document.body.appendChild(ul1);
}
<body onload="createhtml()">
</body>
Is it better to do that, or simply:
<ul>
<li>First List Item </li>
</ul>
Or are they both exactly the same, and the second one is just easier/faster to type.
I've found that keeping things separated will save you a lot of frustration down the road. Defining the objects on your page should go in your HTML, styling and animating those elements should go in your CSS and making things do stuff should go in your javascript. Of course, this isn't a hard and fast rule but keeping things separated by intention makes it easier to read and easier to find what you're looking for. Additionally, in response to which method is faster, the pre-assembled HTML is going to load faster than trying to assemble it in js on the fly.
TLDR; create the elements in your HTML whenever possible.
Your page/browser will:
draw the static HTML
go get the JavaScript and run it
redraw the new elements into the page
In your example here that's a trivial thing that a user would never notice, but on larger pages it can cause issues. The JavaScript method is also less efficient in terms of your time and processing efficiency.
Generally speaking, you would want to use JavaScript when you have to generate something that might be changing after the page loads (eg click stuff, do stuff), or different based on circumstances that are present when it loads (eg go get a list of stuff from elsewhere). Static/unchanging material is better off left as HTML.
For the HTML typed, the page will load and your list will be visible.
For the JavaScript version, the page will load, your script will be parsed and run and then the list will be visible.
This is a very trivial example, but straight HTML will be slightly more performant and for static content, much more maintainable.
For your example if you know the number of elements before then using static html tags are better option because it will take time and memory to append to the body.
where in other case if you don't know how many elements are going to be appended to the body then you have to use dom.
you can see the performance and memory that your elements going to take can be see in the developers tool "F12" timeline.

How to load the contents of a file and insert a variable in it using Javascript?

I'm adding some html to a div using the following jQuery method:
$('#pageTabContent').append($('\
<div class="tab-pane" id="'+ticketId+'">\
And a whole lot more html here..
</div>'));
This works fine, but because I've got way too much html in my javascript I want to move that to a separate file. The problem is that I also need to insert the ticketId in the html. Is there a way using Javascript/jQuery to load the html from a separate file, but still insert the ticketId in it?
[EDIT] Please note that the ticketId is different for every time this piece of code is used. I will be used multiple times within one page load, so I cannot load the ticketId in the html using php. I has to be done client side.
All tips are welcome!
For that specific example, it's pretty straightforward:
$.get("/path/to/file.html", function(html) {
var newStuff = $(html);
newStuff.find("div.tab-pane:first").attr("id", ticketId);
newStuff.appendTo("#pageTabContent");
});
You can generalize that a bit, the basic concept is: 1. Load the HTML, 2. Use jQuery to create DOM elements from it, 3. Use jQuery to find the element in question and modify it, 4. Add to the element.
Another approach is to use some form of templating, either a templating plugin or just DIY:
$.get("/path/to/file.html", function(html) {
html = html.replace("{{ticketId}}", ticketId);
$("#pageTabContent").append(html);
});
Again, there are plugins and templating systems to do that for you, which would offer various features over doing your own.
I generally recommend avoiding dynamic html generation in javascript.
There are several good template based frameworks out there. One I like to use in KnockoutJS http://knockoutjs.com/
Another benefit of this approach is change tracking between your model and your html elements.

Is there a better way to do innerHTML?

I want to know if there is a better way to be doing innerHTML than what I do here. The way I am doing it is causing problems because of the fact that I can't have triple nested quotes. along side that, it is really hard to look at and manage. Thanks!
function buttonClicked(buttonValue)
{
switch (buttonValue)
{
case 1:
soundFolders.innerHTML = "<li onClick='buttonClicked(11);'>Thunder 1</li> <li onClick='buttonClicked(13);'>Light Rain 1</li> <li onClick='buttonClicked(0);'>Back</li>";
break;
case 11:
if(!thunder1Control)
{
thunder1.play();
var thunder1Control = document.createElement("li");
soundList.appendChild(thunder1Control);
thunder1Control.innerHTML = "<h3>Thunder 1</h3> <button class='stopSound' onClick='thunder1.pause(); thunder1.currentTime=0; thunder1Control.parentNode.removeChild(thunder1Control); '>X</button> <button class='volDown' onClick='thunder1.volume -= 0.25;'>-</button> <button class='volUp' onClick='thunder1.volume += 0.25;'>+</button>";
thunder1Control.setAttribute("class", "playingSound");
}
P.S. Do you guys know why the thunder1Control.parentNode.removeChild(thunder1Control) is not working?
To your first question about another way to approach this type of code, "best" is a matter of opinion so I won't really try to address what is best. But, I will give you some alternatives:
Avoid putting code into strings in your HTML. There are all sorts of limitations with that and you generally want to separate code from presentation anyway.
Install event handlers in your code with obj.addEventListener() instead of putting event handlers and code in your HTML.
Use classes and IDs or DOM queries from a particular point in the hierarchy to retrieve specific objects in your page rather than trying to save references to them in global variables. In plain javascript, element.querySelectorAll() is pretty powerful.
In many cases, it's much simpler to just hide and show blocks of HTML using obj.style.display = "none" and obj.style.display = "block" than it is to dynamically create and destroy HTML and this has the added advantage of the HTML is all specified in the page and doesn't have to be shoehorned into a javascript string.
For large blocks of dynamic HTML that wouldn't work well with hide/show for whatever reason, you can dynamically load snippets/templates of HTML from your server using ajax or you dynamically create the HTML using javascript. My first preference is generally hide/show and then if that isn't practical for some reason, it depends upon how much the HTML I want to insert varies based on the state for whether I'd rather load a template or create it dynamically using javascript. If you have large blocks of HTML you have to fit in your javascript, it is messy with quoting, etc... - no way around that if you go that route other than using one quoting scheme for the JS string delimiter and the other in your HTML.
In your particular case, it sure looks like the hide/show method would be simple.
To your second question, this line of code:
thunder1Control.parentNode.removeChild(thunder1Control)
does not work because the thunder1Control variable is long, long out of scope when your click handler is executed because it's a local variable in your buttonClicked() clicked function.
When you put code into a string as part of HTML, it is evaluated in the global scope only so any variables that it tries to reference, must themselves be global in scope.
I'd suggest that you NOT put code into strings in your HTML like that. Use references to actual javascript functions. In that particular case, I'd have to see your HTML to know how to best advise you. If there is only ever one thunder1Control, then I'd suggest you just put an id value on it and retrieve it with document.getElementBtId() when you need it rather than trying to save a reference to it in a variable.
There are essentially two other ways that I can see:
Use a framework that helps with this kind of things. Others have
mentioned jQuery. A commenter is arguing that it might be overkill
to include a framework for just this. I would argue that if you're
doing any javascript at all, you should be using a framework to
make it less terrible. But continue onto suggestion 2 if you
disagree!
You can create each of the elements via plain old javascript and append it to the elements that you need, instead of inserting it directly into innerHTML. ex.
var li = document.createElement("li");
soundFolders.appendChild(li);
etc...
But, honestly, use jQuery with some of the suggestions from others. It's pretty small, and it will heavily clean up all of your javascript. Include it via Google and it will likely already be cached in the users browser.
https://developers.google.com/speed/libraries/devguide#jquery
I think a better alternative is to use jQuery, and then instead of using .html() (equivalent of innerHTML in jQuery), you can create a template with your html and use .load() instead. Works nicer and it's cleaner. And you don't have to worry about triple nesting quotes as you said.
Edit: I'm not sure why I'm getting downvoted so much here... The poster doesn't want to worry about triple nesting quotes. A simple and, to me, elegant solution is to use .load() and to create a template, rather than a really long string of html...

Templating HTML with hidden state instead of comment or custom script tag

Javascript best practices & conventions, such as those emphasized by John Resig and by Nicholas Zachas, author of book Maintainable JavaScript, suggest using HTML comments or script tags with a custom type to store HTML templates.
Comment example:
<div id="myTemplate">
<!-- <ul><li>$item</li></ul> -->
</div>
<script>
var myTemplate = document.getElementById('myTemplate').childNodes[0].data;
var myHtml = myTemplate.replace(/\$item/g, itemValue);
</script>
Script tag example:
<script id="myTemplate" type="text/x-html-template">
<ul><li>$item</li></ul>
</script>
<script>
var myTemplate = document.getElementById('myTemplate').innerHTML;
var myHtml = myTemplate.replace(/\$item/g, itemValue);
</script>
I strongly dislike the comment-based templating because comments are supposed to be just that--comments, intended to be ignored by the functioning application--and as such I'm a little bewildered as to how it even gets to be suggested by JS gurus.
The script tag templating makes a lot more sense, and I'd normally call it a best if not wonderful practice because the purpose and initial non-function are well-delineated. My only issue is that in some modern editors the color highlighting, autocompletion, auto markup validation, etc., are all lost while working within the script tag.
An approach to templating I've taken in the past is to put it all in a container div, then classify the container div as class="template", then in CSS mark it as ".template { display: none; }".
<div id="myTemplate" class="template">
<ul><li>$item</li></ul>
</div>
<script>
var myTemplate = document.getElementById('myTemplate').innerHTML;
var myHtml = myTemplate.replace(/\$item/g, itemValue);
</script>
This has worked fine for me, although the DOM parser and renderer obviously processes the data up front unnecessarily, but I'm not sure whether this is really all that big of an issue or not, as long as the templating constructs do not break HTML validity rules.
My question, then, is, what am I missing? Is the only reason why this third approach to storing template markup--that is, putting it in the DOM as display:none--is discouraged because the DOM parser and renderer will process it anyway? Or are there other reasons, perhaps technical, that I haven't come across yet? I'd like to know because, again, I want to take advantage of my editor's ability to help me fine tune a proper HTML template.
I think that the best method is using the <script> tag. But for your editor,
it must has a solution to add HTML support into the <script> tag with type="html/template-something" too.
For example I code in Sublime Text, and when I want to write a script template tag,
my editor showed me something like this:
As you see, the h1 tag inside the script tag, is different from real h1 in my HTML.
So I search on the internet, and find a solution: finding a file name called HTML.tmLanguage and make this changes:
// change this line
<string>(?:^\s+)?(<)((?i:script))\b(?![^>]*/>)</string>
// to this line
<string>(?:^\s+)?(<)((?i:script))\b(?!([^>]*text/template[^>]*|[^>]*/>))</string>
And after that, I get this result in my editor:
I'm sure there must be a solution for your editor.
Visual Studio 2012
In Visual Studio 2012, if you use the script like this:
<script id="myTemplate" type="text/html">
it will parse the content within it as HTML.
display: none;
Your last solutions, using display: none isn't good, because Search Engines will index the content within it, see this:
Is hidden content (display: none;) -indexed- by search engines?
That unnecessary parsing is why the script tag method is used.
Stating some type other than JS makes the browser ignore that block entirely. Thus, you save processing time and memory. But you might think "Surely users have powerful machines". Not necessarily.
Page performance is a lot slower on mobile, than on the desktop. Mobile has limited memory and processing power. So parsing that hidden block of HTML is unnecessary.
Also, you'll never know what's in the template. It could contain tables with 10k rows. Scripts run in those hidden blocks. It could contain heavy scripts that may contain blocking elements like synchronous XHRs or loops that run 100k times. Who knows!
Additionally, you'd be creating DOM elements and getting them as strings. Why not make them strings in the first place? Skip the DOM building part.
They are templates, you should be running them as needed, not unnecessarily. Unless you know what's inside those hidden tags of yours, then sure, why not? But releasing to the public or making it a generic guideline, I'd stick to the safer method.

Best approach for including bits of Javascript on individual pages in Sitefinity

Frequently, I just want to drop a bit of jQuery on an individual page. Given my early understanding of Sitefinity, I think...
I can't easily put JS in the <head>.
I could put JS in a Generic Content control, but then my JS is sitting inline in the <body>. Maybe I need to relax, but I don't usually like to put much JS in the <body>.
It feels like this kind of scenario is an afterthought. Is JS a 2nd-class citizen in Sitefinity?
JavaScript does not live in the head. Yahoo even says it is better for performance
I agree with epascarello you really shouldn't be putting your javascript in the head anyway.
And just in case you didn't know about this the jQuery framework is part of Sitefinity. The article also shows you how you can include external libraries in sitefinity from anywhere withing your project whether it be master page or user control.
Why not have the jQuery code in a separate .js file and use unobtrusive JavaScript? With jQuery you can separate behavior and markup so nicely that you should never have to include JavaScript in your head or body ever again.
Just use the standard onLoad function in jQuery and put all of your initialization code in there.
Try it, I think that you will like it! If you like using CSS for separation of presentation and markup, then jQuery can do the same thing with behavior and markup.
This is an old question, but one way you can do it now is:
Add a Javascript block (under Scripts & Styles), and then paste the URL to the jquery code:
http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js
Then add another Javascript block with your jquery, like:
$(document).ready(function() {
alert("hello");
});
Or you can also paste the URL to your js file.

Categories

Resources