My problem is related to jQuery and the DOM elements. I need a template like the following:
var threadreply = " <li class='replyItem'>"
+ " <div class='clearfix'>"
+ " ${tittle}"
+ " </div>"
+ " </li>"
;
$.template( "threadreply", threadreply );
As you can see, this is a list element. My problem is when I parse it with $.tmpl, which retrieves a valid DOM element without the <li> </li> tags.
liElement = liElement + $.tmpl("threadreply", {"tittle": "hello"} ).html();
Is there any way I can retrieve the element without reformatting?
I know I can do it with a template with a valid ul tag and inside an each jQuery template loop, but I'm not working with JSONs, I can't convert my data structures to JSON.
The full example is as follow:
var threadreply = " <li class='replyItem'>"
+ " <div class='clearfix'>"
+ " ${tittle}"
+ " </div>"
+ " </li>"
;
$.template( "threadreply", threadreply );
var liElement = "";
for( var i = 0; i < 150; i ++ ){
liElement = liElement + $.tmpl("threadreply", {"tittle": "hello"} ).html();
}
$(liElement).appendTo("#ULElement");
EDITED
I found a workaround with this thread: JQuery Object to String wich consists on wraping each DOM element returned by the $.tmpl in a div before get the .html() of the object:
liElement = liElement + $('<div>').append( $.tmpl("threadreply", {"tittle": "hello"} )).html();
With 300 elements it takes aprox 290ms in process all elements. With the appendTo() inside the loop, it takes more than 800ms.
you do not get the 'li' element because when you do
liElement = liElement + $.tmpl("threadreply", {"tittle": "hello"} ).html();
you get the contained html (or innerhtml) of the 'li' element.
html:
<ul id="titleList">
</ul>
js:
$.tmpl("threadreply", {"tittle": "hello"}).appendTo('#titleList');
You just need the string and not a real DOM element. Just use:
liElement = liElement + $.tmpl("threadreply", {"tittle": "hello"});
Outside the loop, you need to wrap the HTML you just generated into a new element, and then replace the former li:
$('<li />').html(liElement).replaceAll('li#existingLiID');
Related
I generate with a loop for every section on my html site a list element.
<section class="page1" id="name1"></section>
<section class="page2" id="name2"></section>
<section class="page3" id="name3"></section>`
In my jQuery function, see below, I create for every section a link.
for( var i = 0; i < sections.length; i++){
_addClass(sections[i], "ops-section")
sections[i].dataset.index = i + 1;
sections[i].id=document.getElementById(sections[i].id);
if(settings.pagination == true) {
paginationList += '<li><a data-index="'
+ (i + 1) + '" href="#' + (i + 1)
+ '"></a><p class="lead">'
+ sections[i].id + '</p></li>';
}
with sections[i].id=document.getElementById(sections[i].id); I want to read out the text behind id, for example: name1. name2, name3 and so on. I want to add the id-name then as text between the p-tag, so that I get the following list element:
<li><a data-index="1" href="#1" class="active"></a><p class="lead">name1</p></li>
but actually I get this:
<li><a data-index="1" href="#1" class="active"></a><p class="lead">[object HTMLElement]</p></li>
Where is my mistake? What's wrong?
I think you are going about this the wrong way and making the code harder to follow in the process. Your issue is that you are concatenating an entire DOM node, rather than a value of one of the attributes of that node because of this line:
sections[i].id = document.getElementById(sections[i].id)
.getElementById() returns a DOM node so later, when you use:
sections[i].id
You aren't referring to the id at all, you are referring to the entire element returned from:
document.getElementById(sections[i].id)
You don't really even need any of that entire line anyway.
If you use a .forEach() loop to enumerate the section elements, you won't have to set up or manage a counter.
If you create the elements via the DOM API (instead of building a string), you can configure each element much more simply and get out of concatenation hell.
Look at the solution below, it's a little more overall code than your solution, but it is so much cleaner and easier to follow.
// Get the section elements into an array
var theSections = Array.prototype.slice.call(document.querySelectorAll("section[class^='page']"));
// Loop over the elements in the array
theSections.forEach(function(section, index){
// Create li, a and p elements
var li = document.createElement("li");
var a = document.createElement("a");
var p = document.createElement("p");
// Configure each new element
a.setAttribute("data-index", index + 1);
a.href = index + 1;
a.classList.add("active");
p.classList.add("lead");
p.textContent = section.id;
// Inject new elements into the DOM
li.appendChild(a);
li.appendChild(p);
document.body.appendChild(li);
// Just for testing
console.log(a, p);
});
<section class="page1" id="name1"></section>
<section class="page2" id="name2"></section>
<section class="page3" id="name3"></section>
Why is it not working?
First, document.getElementById retrieves an HTML element. Then, you are overriding the id in sections[i].id with the HTML element, resulting in [object HTMLElement].
Solution
As suggested by Liora Haydont, simply remove the line sections[i].id=document.getElementById(sections[i].id);.
for( var i = 0; i < sections.length; i++){
_addClass(sections[i], "ops-section")
sections[i].dataset.index = i + 1;
if(settings.pagination == true) {
paginationList += '<li><a data-index="'
+ (i + 1) + '" href="#' + (i + 1)
+ '"></a><p class="lead">'
+ sections[i].id + '</p></li>';
}
In your code you're attaching an entire HTML element to the section id which is why you're getting that error. Scott just beat me with his answer, but I'm in agreement with him. Using forEach will allow you to make your life a little easier.
In this example I'm also using template literals to create the HTML. YMMV, however.
const sections = document.querySelectorAll('section');
const out = document.getElementById('out');
const settings = {
pagination: true
}
sections.forEach((section, i) => {
const index = i + 1;
const id = section.id;
section.classList.add('ops-section');
section.dataset.index = index;
if (settings.pagination) {
const para = `<p class="lead">${id}</p>`;
const li = `<li><a data-index="${index}" href="#${index}" class="active">test</a>${para}</li>`;
out.insertAdjacentHTML('beforeend', li);
}
});
<section class="page1" id="name1">section1</section>
<section class="page2" id="name2">section2</section>
<section class="page3" id="name3">section3</section>
<ul id="out"></ul>
Why not using JQuery ? This is a small demo on how you can get the id attribute of your section and use it in the JQuery code:
$(document).ready(function() {
$('section').each(function( key, value ) {
// alert($(this).attr('id') + " - " + key + ": " + value );
$('pagination').append("<p class='lead'>* <a data-index='"+ key +"' href=#></a>" + $(this).attr('id') + '</p>');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="page1" id="name1"></section>
<section class="page2" id="name2"></section>
<section class="page3" id="name3"></section>
<pagination></pagination>
The queryString to find all the input elements with ID ends with '-0', '-1' etc ..
the below code works fine
var queryString = ':input:focusable[id$="-' + index + '"]';
I also want to find the div elements ending with the same scenario .. How i can change the query ??
You can use comma to add additional selectors:
var queryString = ':input:focusable[id$="-' + index + '"],div[id$="-' + index + '"]';
make it
var queryString = ':input:focusable[id$="-' + index + '"], div[id$="-' + index + '"]';
Using comma , you can add selectors to the same query string.
Edit
but the select element am having present inside the div element and
the div element has the ID
try this
var queryString = 'div[id$="-' + index + '"]:input:focusable';
I am bringing a big html string inside an ajax call that I want to modify before I use it on the page. I am wondering if it is possible to edit the string if i store it in a variable then use the newly edited string. In the success of the ajax call this is what I do :
$.each(data.arrangement, function() {
var strHere = "";
strHere = this.htmlContent;
//add new content into strHere here
var content = "<li id=" + this.id + ">" + strHere + "</li>";
htmlContent is the key for the chunk of html code I am storing in the string. It has no problem storing the string (I checked with an alert), but the issue is I need to target a div within the stored string called .widgteFooter, and then add some extra html into that (2 small divs). Is this possible with jquery?
Thanks
Convert the string into DOM elements:
domHere = $("<div>" + strHere + "</div>");
Then you can update this DOM with:
$(".widgetFooter", domHere).append("<div>...</div><div>...</div>");
Then do:
var content = "<li id=" + this.id + ">" + domHere.html() + "</li>";
An alternative way to #Barmar's would be:
var domHere = $('<div/>').html( strHere ).find('.widgetFooter')
.append('<div>....</div>');
Then finish with:
var content = '<li id="' + this.id + '">' + domHere.html() + '</li>';
You can manipulate the string, but in this case it's easier to create elements from it and then manipulate the elements:
var elements = $(this.htmlContent);
elements.find('.widgteFooter').append('<div>small</div><div>divs</div>');
Then put the elements in a list element instead of concatenating strings:
var item = $('<li>').attr('id', this.id).append(elements);
Now you can append the list element wherever you did previously append the string. (There is no point in turning into a string only to turn it into elements again.) Example:
$('#MyList').append(item);
I have created my dynamic unordered list and trying to append it to the div tag. Its not getting reflected. I have written the below JS code
var mydiv= $('#itemList');
var myul=$('<ul/>');
var li1 = $('<li/>').html(''+'Varun Mehta'+''+'<span>'+ '9834562873' +'</span>');
myul.append(li1);
var li2=$('<li/>').html('Varun Mehta');
myul.append(li2);
mydiv.append(myul);
HTML:
<div id="csd" class="myClass">
<br>
<div id="itemList">
</div>
</div>
No error is coming in console and list is not getting reflected on screen.
put it in document.ready and there need quote for Varun Mehtha
$(document).ready(function () {
var mydiv = $('#itemList');
var myul = $('<ul/>');
var li1 = $('<li/>').html('' + 'Varun Mehta:' + '' + '<span>' + 9834562873 + '</span>');
myul.append(li1);
var li2 = $('<li/>').html('Varun Mehta');
myul.append(li2);
mydiv.append(myul);
});
I have a string with multiple elements with id's like below:
var data = "<div id='1'></div><input type='text' id='2'/>";
Now I'm using this regex to find all the id's in the string:
var reg = /id="([^"]+)"/g;
Afterwards I want to replace all those id's with a new id. Something like this:
data = data.replace(reg, + 'id="' + reg2 + '_' + numCompare + '"');
I want reg2, as seen above, to return the value of the id's.
I'm not too familiar with Regular Expressions, so how can I go about doing this?
Instead of using regex, parse it and loop through elements. Try:
var data = "<div id='1'></div><div id='asdf'><input type='text' id='2'/></div>",
numCompare = 23,
div = document.createElement("div"),
i, cur;
div.innerHTML = data;
function updateId(parent) {
var children = parent.children;
for (i = 0; i < children.length; i++) {
cur = children[i];
if (cur.nodeType === 1 && cur.id) {
cur.id = cur.id + "_" + numCompare;
}
updateId(cur);
}
}
updateId(div);
DEMO: http://jsfiddle.net/RbuaG/3/
This checks to see if the id is set in the first place, and only then will it modify it.
Also, it is safe in case the HTML contains a comment node (where IE 6-8 does include comment nodes in .children).
Also, it walks through all children of all elements. In your example, you only had one level of elements (no nested). But in my fiddle, I nest the <input /> and it is still modified.
To get the get the updated HTML, use div.innerHTML.
With jQuery, you can try:
var data = "<div id='1'></div><div id='asdf'><input type='text' id='2'/></div>",
numCompare = 23,
div = $("<div>"),
i, cur;
div.append(data);
div.find("[id]").each(function () {
$(this).attr("id", function (index, attr) {
return attr + "_" + numCompare;
});
});
DEMO: http://jsfiddle.net/tXFwh/5/
While it's valid to have the id start with and/or be a number, you should change the id of the elements to be a normal identifier.
References:
.children: https://developer.mozilla.org/en-US/docs/DOM/Element.children
.nodeType: https://developer.mozilla.org/en-US/docs/DOM/Node.nodeType
jQuery.find(): http://api.jquery.com/find/
jQuery.attr(): http://api.jquery.com/attr/
jQuery.each(): http://api.jquery.com/each/
Try using
.replace(/id='(.*?)'/g, 'id="$1_' + numCompare + '"');
Regex probably isn't the right way to do this, here is an example that uses jQuery:
var htmlstring = "<div id='1'></div><input type='text' id='2'/>";
var $dom = $('<div>').html(htmlstring);
$('[id]', $dom).each(function() {
$(this).attr('id', $(this).attr('id') + '_' + numCompare);
});
htmlstring = $dom.html();
Example: http://jsfiddle.net/fYb3U/
Using jQuery (further to your commments).
var data = "<div id='1'></div><input type='text' id='2'/>";
var output = $("<div></div>").html(data); // Convert string to jQuery object
output.find("[id]").each(function() { // Select all elements with an ID
var target = $(this);
var id = target.attr("id"); // Get the ID
target.attr("id", id + "_" + numCompare); // Set the id
});
console.log(output.html());
This is much better than using regex on HTML (Using regular expressions to parse HTML: why not?), is faster (although can be further improved by having a more direct selector than $("[id]") such as giving the elements a class).
Fiddle: http://jsfiddle.net/georeith/E6Hn7/10/