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...
Related
I have a situation where i have to take the CKeditor text from an iframe, in javascript, following some answers to similar problems (but not exactly the sames) i've arrived to get the inner html of the page and what i get is the textarea of the CKeditor.
To get what i've written above i've used this method:
document.getElementById(id).contentDocument.body
Now from here i would like to do one of those two things, but i don't know how or if it's possible:
1) First and more preferable, i would like to parse the body as a CKEDITOR instance, so that i can use the libray methods to get the text inside, is it possible?
2) Second (if the first option is not possible) i would like to navigate more inside but the only way that i have in mind is another getElementsById, but by reading some answer around i've seen that this is not a good practice to do what i need, why?
What's the best practice between the two? (Or if there is another way, what is it?)
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.
Here's what I'm trying to do:
I am doing a few things to my text input via "oninput=myFunction()"
When I start typing I wanted to do a few things:
I have the function removing a few elements and adding a textNode already, however, I need it to add 35-40 lines of HTML as well.
Would this be bad to do?
I'm not exactly sure how I should set it up to call this HTML through the function yet.
What's the best/cleanest way to go about doing this?
Should I just keep the HTML wrapped with a hidden display:none class, and have the function add a visible class?
I feel like that wouldn't be the best method, so that's why I'm here asking!
Any advice is appreciated. I'm typing on my phone so sorry if I wasn't very clear.
The better way in my opinion is have a script that will add your event handler after the element is ready (after page load). This function should take care of creating and removing any element that are part of the script on the fly.
Doing this will make sure your HTML is clean and that the JavaScript will do what it is responsible for. There are good ways to create HTML with JavaScript by using methods such as document.createElement and document.createTextNode. When your elements are created, you can append them in the right positions.
To help get the best rendering on all browsers, it is usually a good practice to make your elements display: none before everything is ready to display.
The most obvious example I can think of is for outputting nested comments. Let's say you have a tree of comments and you want to output it as nested html (let's say lists inside lists or divs inside divs) using your template.
The "comment" block/function/tag/helper/whatever would have to be able to call itself somehow for the comment's children.
Are there template engines that would support that sort of thing inside one template file?
I am aware that you can just pre-compute the "indent" or "depth-level" of each comment and send them to the template as one flat list in the correct order, but let's just say I don't want that. And let's say I don't want to stitch snippets together in code / outside the template - I want the whole page self contained in one template or theme file.
Update: I want to generate nested html. I want the comments to be nested, not appear nested. I know how to indent things with CSS. :) Whether it is done in the browser or on the server is irrelevant because the point is I want the template to be self-contained in one file.
As in:
var html = render(template, {comments: aTreeOfNestedComments});
(see? that could be node.js, a brower plugin, some "jQuery" as some people like to call javascript these days...) It looks like jade can do this using mixins. Any tag-based templating engines that can do something similar?
Template engines can solve generic, run-off-the-mill problems. While nesting templates seems like a common use case, I haven't encountered many template engines who can do that.
Since the market didn't offer a good solution, I'm building my applications from JavaScript objects that know how to render themselves. I never use templates; every block gets a reference to the DOM (like the parent element to which is should attach itself) or the renderers return the child container and the parent element can add that in a suitable place.
This allows me to use the full power of JS without the limitations of template engines.
[EDIT] Here is a workaround: If you need a recursive element, add a span (if the recursive element should be inline) or div (if it's a block element). Give it the class recursiveTemplate and a data attribute data-template-name="..."
Run the template with your standard template engine. Afterwards, use jQuery or the like to find all elements with the class recursiveTemplate and replace them yourself.
Distal templates has an example here of a nested tree:
http://code.google.com/p/distal/wiki/UseCaseExamples#Building_a_nested_tree
as #TJHeuvel said, you can use the server side script to produce the desired otput, this would be the best way to do what you require. However if you must use JavaScript, I would advise jQuery this will also allow you to product the desired result.
for example:
$("ul li").css("margin-left", "10px");
As a learner I like to look at lots of source code. Since I started learning JavaScript about a year ago, I notice a trend of people not using traditional event handlers as in onclick="doSomething()", but are more and more using methods like document.getElementById("someId").onclick = function(){..some code..};
What's the reason behind this trend?
Assigning the handlers in Javascript puts all of the code in one place instead of scattering it throughout the HTML.
This helps separate content from script, just like CSS helps separate content from style.
It's also faster, since the browser won't need to fire up a Javascript parser for each handler attribute.
This is an example of Unobtrusive Javascript.
The other answers haven't touched on this, so:
Your example uses the (reflected) onclick attribute even in the JavaScript code:
document.getElemenbyId("someId").onclick = function(){..some code..};
...which for me misses out one of the primary reasons for doing this without using attributes: Playing nicely with others. The DOM2 way of attaching handlers (addEventListener, or attachEvent on IE [IE9 has the standard addEventListener finally]):
document.getElementById("someId").addEventListener("click", function() { ... }, false);
// or
document.getElementById("someId").attachEvent("onclick", function() { ... });
... is non-exclusive — more than one handler can be attached at the same time. Whereas if you assign to onclick, you're kicking any previous handler off and taking over.
To me, this "playing nicely" thing is a big sell. Well, that and keeping code and markup separate, but that's been well-covered in other answers.
HTML should be only markup, pure content.
Design should be in CSS style sheet.
Dynamic scripting should be in JavaScript code, separate file is good.
Just feels better and looks better - as far as I can tell it's not more efficient just more elegant and easier to maintain when all the script is in one place instead of being spread all across the HTML. :)
As mentioned by other answers, the main reason is separation of concerns (in this case, keeping behaviour separate from content), which is entirely sensible. However, that isn't always the only consideration. I've previously written a lengthy answer to a related question.
I think most people are using jQuery. $("#someId").click(function(){}) and when you want to attach an event to many elements jQuery makes it easy and puts your function in one place.