So I know this is probably horrible programming practice, but I'm in a bit of a time crunch, and basically I have a tag within my code, and upon clicking a button on the screen, I'm trying to append a bunch of code inside that div. However, I've noticed two things. One, my other javascript crashes UNLESS the appended code is all on one line, and two, my css style sheets aren't being applied to the code even though I've assigned classes. Here's the relevant code:
$("#results").append("<ul class='sdt_menu'>");
for(i=0; i < progression[max].length;i++)
{
$("#results").append(
"<li><a href='#'><img src='images/youAreHere.jpg' alt=''/><span class='sdt_active'></span><span class='sdt_wrap'><span class='sdt_link'>"+progression[max][i]+"</span><span class='sdt_descr'>hover to view description</span></span></a><div class='sdt_box'>"+jobs[progression[max][i]]['description']+"</div></li>");
}
$("#results").append("</ul>");
Any help demystifying this would be greatly appreciated.
When you append, you should be appending an entire, complete, closed set of tags. It doesn't work like a stringbuilder. Try instead something like:
var tag = '<ul class="sdt_menu">';
for(var i = 0; i < progression[max].length; i++) {
tag += '...all of your other list items';
tag += "</ul>";
$(tag).appendTo("#results");
In your current code, as soon as you add the <ul> it gets automatically closed by the browser (since it's impossible to have unclosed tags in the DOM) and then your <li> are being added to #results too. Or at least, they would be, if it were legal to have an <li> be a child of a <div>.
Instead, you need to append your <li> elements to the <ul>, not to #results:
var $ul = $("<ul class='sdt_menu'>");
for (i = 0; i < progression[max].length; i++) {
$ul.append(...);
}
$ul.appendTo('#results');
Try this:
var tag = [];
var ic=0;
tag[++ic] = '<ul class="sdt_menu">';
for(var i = 0; i < progression[max].length; i++) {
tag += '...all of your other list items';
}
tag[++ic] = "</ul>";
$("#results").append(tag.join(''));
Related
I have the following code below, where I am trying to create a ul tag, and inside it a for loop to dynamically create li elements. A separate closing ul tag is created after the loop is completed.
The code works. Except for the problem that the code does not run in order like I want it to. The ul tags are closed before the for loop can be processed into the page, resulting in the html looking more like:
<ul></ul><li>0</li><li>1</li>...
var insidethediv = document.getElementById("insidethediv");
var numero = 5;
insidethediv.innerHTML = "<ul>";
for (i = 0; i < 5; i++){
insidethediv.innerHTML += "<li>"+i+"</li>";
}
insidethediv.innerHTML += "</ul>";
<div id="insidethediv"></div>
Assigning directly to innerHTML is a bad idea here. innerHTML expects a complete html fragment, i.e. all open tags should be closed. But here you are assigning to a partial html fragment while you are building it. Try to create the complete html first and then assign it to innerHTML, e.g. like so:
var insidethediv = document.getElementById("insidethediv");
var numero = 5;
var s = "<ul>";
for (i = 0; i < 5; i++){
s += "<li>"+i+"</li>";
}
s += "</ul>";
insidethediv.innerHTML = s;
I personally prefer to use document.createElement(tag name) and Element.append(created element reference) functions. In this way we are able to manipulate each individual <li> tag (such as assign different colors) and render the HTML tags dynamically instead of jamming everything into a string then insert it as an innerHTML element.
var insidethediv = document.getElementById("insidethediv");
var numero = 5;
var ul_element = document.createElement("ul");
insidethediv.append(ul_element);
var li_element;
for (var i = 0; i < 5; i++){
li_element = document.createElement("li");
ul_element.append(li_element);
li_element.innerHTML = i;
}
<div id="insidethediv"></div>
I am new with js and playing with replace method.
I have had no problems when replacing string for another string etc., but when im trying to do same with tags nothing happens..
Im trying to replace every tags for -tags. My function is below:
function bonus() {
var list = document.getElementsByTagName('li');
for (var i = 0; i < list.length; i++) {
newList = document.getElementsByTagName('li')[i].innerHTML;
newList = newList.replace('<li>', '<strong>');
newList = newList.replace('</li>', '</strong>');
document.getElementsByTagName('li')[i].innerHTML = (newList);
//console.log(newList);
}
}
function bonus(){
var list=document.getElementsByTagName('li');
var len = list.length;
for(var i=len-1; i>-1; i--){
var tmpItem = list[i]
newList = tmpItem.outerHTML;
newList = newList.replace('<li>','<strong>');
newList = newList.replace('</li>','</strong>');
tmpItem.outerHTML = newList;
}
}
I thought you might change your code like above, and there was still much space to optimize your code. go ahead <( ̄︶ ̄)>
First of all you should never replace a list-item with another element like that. A list item must always be a child of an ul or ol elelment, and ul and ol elements should not have any other immediate child that isn't a li.
However, this doesn't work because the li is an html element and not a text string and the inner HTML of an html elemnt doesn't contain the tag itself. It may contain children and those children's tags are part of the innerHTML, everything inside the element/tag itself is the innerHTML.
An example to clarify:
<ul>
<li>one<strong>second one</strong></li>
<li>two<strong>second two</strong></li>
<li>three<strong>second three</strong></li>
<li>four</li>
</ul>
Looping through all list items accessing elements as you've describe
for(var i=0; i<list.length;i++) {
console.log("==>> " + document.getElementsByTagName("li")[i].innerHTML);
}
Will output the following to the console:
==>> one<strong>second one</strong>
==>> two<strong>second two</strong>
==>> three<strong>second three</strong>
==>> four
If you want to make all li elements strong they should be nested as this:
<li><strong>Some text</strong></li>
To Achieve this one way to do it would be:
var list = document.getElementsByTagName("li");
for(var i=0; i<list.length; i++) {
var listItem = list[i];
listItem.innerHTML = "<strong>" + listItem.innerHTML + "</strong>";
}
If you want to convert all li elements to strong elements you must first remove them from the list...
Thanks alot for all of you. I knew that i can't change li for strong in real world, but i just tried to figure out if its possible to do so with simple loop.
My example html is full of lists, so thats why i used li instead of h2 to h3 or something like that. Outer html was new thing for me, and solution for this one. However Kim Annikas answer helped me with other question about modifying lists: I did this:
function replace(){
var list=document.getElementsByTagName('li');
for(var i=0;i<list.length;i++){
newText="<strong>Replaced!</strong>";
var listItem=list[i];
listItem.style.color="red";
listItem.innerHTML=newText;
}
}
..and now it seems that i have learnt how to modify tags as well as text inside of it ;)
I am adding a simple toggle button through Javascript. Then I want to add three span tags inside it.
So, I am creating variable of span and trying to append it inside our very own basic FOR loop. Iteration count is 3 times.
Here's my basic code below. Please let me know what has been missing or misplaced that my span tag refuses to append more than once. I checked this in the inspect mode.
Then, I brought up console tab and the value of i was 3. Append is meant to append and NOT replace the element. Right ?
var $navbar_header = $('<div class="navbar-header"></div>');
var $button = $("<button></button>");
var $span = $('<span class="icon-bar"></span>');
for (var i = 0; i < 3; i++) {
$button.append($span);
}
$button.addClass('navbar-toggle');
$navbar_header.append($button);
$("#menu").append($navbar_header);
Here's a link to fiddle.
The DOM is a tree, where any element points to its parent (see parentNode). An element can have only one location. So when you append an element, you're removing it from its precedent location.
The solution here is either to clone the element:
$button.append($span.clone());
or just to create it in the loop:
for (var i = 0; i < 3; i++) {
$button.append('<span class="icon-bar"></span>');
}
for(var i=0; i<num_cols; i++)
{
//Wrapper for column
$('#cupcake-list').append('<div>');
//end wrapper
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
$('#cupcake-list').append('<p>'+cupcakeData[d].name+'</p>');
}
//Wrapper for column
$('#cupcake-list').append('</div>');
//end wrapper
}
I just want to encapsulate my p tags within div tags to act as rows, however all I get are <div></div><p>ssdfsdf</p><p>sdfsdfdsf</p><div></div>etc....
What's the best way of doing it?
Start with a fragment so that you don't access the DOM more than once, and append it all at the end. You can skip the wrap by starting with your empty fragment, like so:
var $fragment;
for(var i=0; i<num_cols; i++)
{
$fragment = $('<div />');
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
$fragment.append('<p>'+cupcakeData[d].name+'</p>');
}
//Wrapper for column
$('#cupcake-list').append($fragment);
//end wrapper
}
This is a much faster way to do it! Append parts of a string to an array and then you only have to update the DOM once.
var a = [];
for(var i=0; i<num_cols; i++)
{
a.push('<div>');
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
a.push('<p>'+cupcakeData[d].name+'</p>');
}
a.push('</div>');
}
$('#cupcake-list').append(a.join(''));
EDIT:
I'll explain why yours wasn't working. When you were calling $('#cupcake-list').append('<div>'); you thought it would only add the opening div tag, but that is not the case. jQuery won't let you do this is because they want to make sure the html is valid after every function call. If you were to just add the opening div and then do some other stuff, the next closing div (</div>) in the document would close the div you just opened, changing the structure of the document entirely.
In summation:
$('#cupcake-list').append('<div>'); and $('#cupcake-list').append('</div>'); will both append <div></div> to the document. Also, access and update the DOM as if it costs you a million dollars because it is among the slowest things you can do in javascript.
jQuery has a method called .wrap, and some similar ones (.wrapAll).
If you are having the output that you showed, your code is not reaching the inner for, so you have a logic problem. I think your way of doing this is correct. When i need to build some structure on the fly i usually do the same thing.
JQuery append adds DOM nodes, not HTML. So you can accomplish your task like this:
for(var i=0; i<num_cols; i++)
{
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
$('#cupcake-list').append($('<div></div>').append('<p>'+cupcakeData[d].name+'</p>'));
}
}
First, $('<div></div>') creates a new empty div element not yet attached to the page (you can also do $('<div>') as a shorthand if you want). Then .append('<p>...</p>') adds a p element inside the div. Finally, $('#cupcake-list').append(...) adds the whole div to the end of #cupcake-list.
I'm trying to change the name of a link, however, I have some restrictions. The link is placed in code that looks like this:
<li class='time'>
Review Time
<img alt="Styled" src="blah" />
</li>
Basically, I have a class name to work with. I'm not allowed to edit anything in these lines, and I only have a header/footer to write Javascript / CSS in. I'm trying to get Review Time to show up as Time Review, for example.
I know that I can hide it by using .time{ display: hide} in CSS, but I can't figure out a way to replace the text. The text is also a link, as shown. I've tried a variety of replace functions and such in JS, but I'm either doing it wrong, or it doesn't work.
Any help would be appreciated.
You could get the child elements of the li that has the class name you are looking for, and then change the innerHTML of the anchor tags that you find.
For example:
var elements = document.getElementsByClassName("time")[0].getElementsByTagName("a");
for(var i = 0, j = elements.length; i<j; i++){
elements[i].innerHTML = "Time Review";
}
Of course, this assumes that there is one element named "time" on the page. You would also need to be careful about checking for nulls.
Split the words on space, reverse the order, put back together.
var j = $('li.time > a');
var t = j.text();
var a = t.split(' ');
var r = a.reverse();
j.text(r.join(' '));
This could have some nasty consequences in a multilingual situation.
Old school JavaScript:
function replaceLinkText(className, newContents) {
var items = document.getElementsByTagName('LI');
for (var i=0; i<items.length; i++) {
if (items[i].className == className) {
var a = items[i].getElementsByTagName('A');
if (a[0]) a[0].innerHTML = newContents;
}
}
}
replaceLinkText("time", "Review Time");
Note that modern browsers support getElementsByClassName(), which could simplify things a bit.
You can traverse the DOM and modify the Text with the following JavaScript:
var li = document.getElementsByClassName('time');
for (var i = 0; i < li.length; i++) {
li[i].getElementsByTagName('a')[0].innerText = 'new text';
}
Demo: http://jsfiddle.net/KFA58/