I want to dynamically add divs to my html page. The server sends a list containing the name, description, dates etc. for a task. For each task, a div looking like this, has to be added to the body. So, I have 2 methods of creating it -
Clone the code skeleton shown below ( using cloneNode() ),
Use something like div.childNode[3].childNode[1].textContent = "Task Name" to update each text in it,
Append it to the parent ( using parent.appendChild() )
Create a div ( using createElement() ),
Add classes and styles to it,
Add children containing task name, description, dates etc. to it,
Append it to the parent.
Considering that the list server is going to send can contain up to 100 tasks, so performance wise which method is better ?
Also, are there other ways to do so ?
<div class="task-row min-width900" id="task_row" style="display: none">
<div class="div-inline pull-left min-width25" style="margin-left: 5px">
<input type="checkbox" class="checkbox" id="task_row_checkbox">
</div>
<div class="div-inline pull-left min-width30" style="margin-right: 2px; border-right: 1px solid #dedede;">
<a data-toggle="collapse" data-target="#collapse11" href="#" style="text-decoration:none; color:#4d4d4d; font-size: 20px;" id="subtask_count">
+2
</a>
</div>
<div class="dropdown div-inline pull-left min-width300" style="width: 26%;">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" style="text-decoration:none; color:#4d4d4d; font-size: 15px;" id="name_link">
<strong id="name">Summer's here: Lets clean the house</strong>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li><i class="icon-ok"></i> Done</li>
<li><i class="icon-minus-sign"></i> Dismissed</li>
<li><i class="icon-trash"></i> Delete</li>
</ul>
</div>
<div style="width: 15%;" class="div-inline min-width200 task-tags" id="tags">
<a href="#" style="text-decoration:none">
<span class="label label-important">Work</span>
</a>
<a href="#" style="text-decoration:none">
<span class="label label-warning">Downtown</span>
</a>
</div>
<div class="div-inline task-description" style="width: 32%">
<a href="#" style="text-decoration:none">
<span class="muted" id="description">It's that time of the year again ...</span>
</a>
</div>
<div style="width: 10%" class="div-inline min-width130 pull-right">
<a href="#" style="text-decoration:none; color:#4D4D4D;">
<strong style="font-size: 30px;" id="due_date">13.09.12</strong>
</a>
</div>
<div style="width: 10%" class="div-inline min-width80 pull-right">
<a href="#" style="text-decoration:none; color:#4d4d4d;">
<strong id="start_date">2 days ago</strong>
</a>
</div>
</div>
Thanks
Update:
I am using Django framework for this application ( the task row is a part of it ). So, is adding divs via JS better performance-wise or should Django's {% for loop %} be used to add the task-rows to the page ?
I agree that a JS templating engine might be the best solution.
As for performance, if you still want to do it on your own, regardless of whether you choose to clone or create, most important thing for doing that for 100 items in a loop is, don’t append each element to the document inside the loop, but use a DocumentFragment instead: Append the divs to the fragment, one after another, and after you are done with looping through your items append the fragment, that now contains all of those 100 items, to your document.
(A DocumentFragment is just a “soulless” temporary container – when you finally append the fragment to the document, it will just “dissolve” without leaving a trace, so the effect will be the same as if you had appended the 100 elements individually. As to why it improves performance, see https://stackoverflow.com/a/13771168/1427878.)
In my current project I'm dynamically creating about 600 elements, each with about 10 nested children. They're mostly identical aside from a text node and an src attribute of an image. The best pure-JS way I've found to create and modify these elements takes 10-15ms and works as follows:
Create a DocumentFragment.
Use the fragment to build a template.
Deep clone the fragment.
Modify the clone.
Create the actual root element.
Append the clone to the root element.
Repeat 3-6 as many times as necessary.
According to my tests on Chrome 66/Windows (https://jsperf.com/creating-multiple-nested-elements/1), this is about 10x faster than creating each element from scratch, and about 3x faster than using a non-DocumentFragment as the template root. I would imagine that the benefit becomes greater the more complex the structure you want to clone is.
According to this, cloneNode is slightly better performance:
http://jsperf.com/clonenode-vs-createelement-performance/2
However, I really do suggest you take a look at something like KnockoutJS:
http://knockoutjs.com/examples/simpleList.html
It will save your sanity in the long run.
It's faster to clone the div.
Check out this performance test.
Related
I have a code like this :
<div id="logreg" style="display: none;width:100%;max-width:660px; height:450px;" class="logreg">
my content
</div>
and i need use in many links on my site like this :
<a data-fancybox="logreg" data-src="#logreg" href="javascript:;" class="btnReg float-right">
Register
</a>
<a data-fancybox="logreg" data-src="#logreg" href="javascript:;">
<i class="fas fa-user"></i>
</a>
but doesn't work too many links, only one link work :-(
Please help me.
You are creating gallery that contains two items and both items refer to the same content. Therefore simple use different value for data-fancybox element to not create a group and everything will work fine, demo - https://jsfiddle.net/tecnw6x7/
I am trying to change an image from an old to new using jquery or javascript only. It is the second picture out of three total that has a common parent element and is not separated by any specific parameters.
I believe I need to use a DOM navigation of some sort to get to the exact picture in the common class but haven't had any luck.
As I mentioned the 'make' class is shared between all three images as is 'make-image'. I need to simply swap the image for another updated version, facebook1.jpg.
<li class="make ">
<a href="#">
<img class="make-image" src="facebook.jpg">
<div class="make-info">
<img class="make-logo" src="facebook.jpg">
<div class="clearall"></div>
</div>
</a>
</li>
It should simply swap the existing image for another.
You can query for the image tags inside the list-item and iterate with each over the returned array. Inside that loop you can check if the src of that image-element is what you are looking for and replace it.
$('li.make img').each(function(index){
if ($(this).attr('src') == 'facebook.jpg') {
$(this).attr('src', 'facebook1.jpg');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="make">
<a href="#">
<img class="make-image" src="facebook.jpg">
<div class="make-info">
<img class="make-logo" src="facebook.jpg">
<div class="clearall"></div>
</div>
</a>
</li>
I use react 0.13.3 with babel 5.8.26. I noticed it started rendering strange markup. This is what I have in js file:
<p className="navbar-text navbar-right dropdown hidden-xs">
<a className="navbar-link dropdown-toggle" href="#" id="accountddl" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"><i className="st st-profile st-2"></i></a>
<ul className="dropdown-menu" aria-labelledby="accountddl">
<li>Action</li>
</ul>
</p>
You can see the output there.
But what it renders back is this:
<p class="navbar-text navbar-right dropdown hidden-xs" data-reactid=".0">
<a class="navbar-link dropdown-toggle" href="#" id="accountddl" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" data-reactid=".0.0">
<i class="st st-profile st-2" data-reactid=".0.0.0"/>
</a>
</p>
<ul class="dropdown-menu" aria-labelledby="accountddl" data-reactid=".0.1">
<li data-reactid=".0.1.0">
Action
</li>
</ul>
<p/>
As you can see it closes the p tag before rendering ul and in the end it attaches a self-closed p tag.
How to make ul a part of one parent p tag?
Am I doing something wrong?
If I change p to div it works as expected - result
Update
Thanks to the guys comments. I realized that this is not valid HTML. React is good and does its job well. So, when the browser sees the case, it decides to break it the way shown above.
The HTML spec defines rules for how markup may be nested. In this case:
<p> is:
Content categories: Flow content, palpable content.
Permitted content: Phrasing content.
<ul> is:
Content categories: Flow content
Permitted parent elements: any element that accept flowing content
which translates to <ul> elements not being allowed within <p> elements. To avoid this, React and/or the browser will basically pull the <ul> one level up in the DOM and split the <p> around it, resulting in what you are seeing.
Update
From the release notes of the newly released React 0.14:
React DOM now warns you when nesting HTML elements invalidly, which helps you avoid surprising errors during updates.
Did anyone knew how a tags in the browser are indexed?
I have in my html page 12 items wich are created with a tags, the problem is that when I want to focus the first tag with
document.getElementsByTagName("a")[0].focus(); the browser don't focus the first item! and if I just want to focus the third item by document.getElementsByTagName("a")[2].focus(); it focuses the item number 5.
I am wandering why I have this problem since in my page I have only the wanted items to be focused by a tags and the other html items are div and img tags!
Thanks a lot in advance for your help and reply :)
here is an exmaple of 2 items created in my html page:
<div id="carousel_items">
<div id="indicators" class="carousel-indicators" style="visibility: visible;">
<div id="nextBtn" class="right_indicator">
<img id="indicators_right" src="images/nextbtn.gif" style="width:45px;height:25px;">
</div>
</div>
<div id="div_slides" class="thumbnailList_slides">
<div class="div_vid">
<a id="btn0" class="btn_vid" href="#" onclick="javascript:activate('0');"> </a>
</div>
<div class="div_vid">
<a id="btn1" class="btn_vid" href="#" onclick="javascript:activate('1');"> </a>
</div>
</div>
Elements are returned in the order in which they appear in the DOM.
Various things can make that order different to the order you see them when viewing from left-right and top-bottom including:
text direction
float: right
CSS positioning
Flex order
Made some BBcode for phpBB to allow users to post flickr pics with certain tags.
Each photo div in the thread needs to be unique, and the images load when the thread is loaded.
When it comes to the unique DIV, I'm stuck for a way to insert the uniquely named element into the DOM at the point the BBcode is inserted, THEN load the pics. And it appears I can't use PHP in BBcode, nor the templating tags - if I could easily make a unique photo element from the post ID and the flickr tag I'd be laughing. Oh, and I can't touch the template. It's all got to be within BBcode.
So, here's how I make a unique ID:
var flickrUser = "{URL}".split("/")[4];
var tag = "{URL}".split("/")[6];
var photoDIV = flickrUser + "-" + "tag";
Or...there's an element called with a unique post ID just above I could possibly use:
<div id="p61789" class="post bg2">
I tried
var postnumber=$(this).closest('div[class^="post"]').attr('id');
but it always seemed to return the FIRST matching div on the page, not the NEAREST to the point of the BBcode. This element is two "divs" below
<div class = "content">
and below the user posting area there is:
<div id="sig61789" class="signature">
So where I'm completely stuck is navigating to prev() or closest() or parent() or indeed anywhere from the point where I am without having a $(this) link to reference.
So shouldn't something like:
$(this).prev('content').html('<ul class="thumbs" id=photoDIV></ul>');
or even
$(this).html('<ul class="thumbs" id=photoDIV></ul>');
work? Everytime I think I understand jquery it all goes hazy again...
EDIT: More detail added for Pointy:
<div id="p63167" class="post bg2 online">
<div class="inner">
<span class="corners-top">
<span></span>
</span>
<div class="postbody">
<ul class="profile-icons">
<li class="edit-icon">
<a href="posting.php" title="Edit post">
<span>Edit post</span>
</a>
</li>
<li class="delete-icon">
<a href="posting.php" title="Delete post">
<span>Delete post</span>
</a>
</li>
<li class="report-icon">
<a href="report.php" title="Report this post">
<span>Report this post</span>
</a>
</li>
<li class="info-icon">
<a href="mcp.php" title="Information">
<span>Information</span>
</a>
</li>
<li class="quote-icon">
<a href="posting.php" title="Reply with quote">
<span>Reply with quote</span>
</a>
</li>
</ul>
<h3 class="first">
Re: Testing new bbcode - ignore
</h3>
<p class="author">
<a href="viewtopic.php">
<img src="" alt="Post" title="Post" />
</a>by
<strong>
xxx
</strong>» 13 Jun 2011 14:33</p>
<div class="content">
<script>var
APIkey="xxx";head.js("/forum/jflickrfeed/jflickrfeed.min.js","http://jquery-lazy.googlecode.com/svn-history/r14/trunk/jquery.lazy.source.js",function(){var
flickrUser="http://www.flickr.com/photos/xxx/tags/7thjanuary2010/".split("/")[4];var
tag="http://www.flickr.com/photos/xxx/tags/7thjanuary2010/".split("/")[6];var
photoDIV=flickrUser+"-"+"tag";$(this).html('
<ul class="thumbs" id="photoDIV">
</ul>');$.getJSON("http://www.flickr.com/services/rest/?jsoncallback=?",{method:"flickr.urls.lookupUser",url:"http://www.flickr.com/photos/xxx/tags/7thjanuary2010/",format:"json",api_key:APIkey},function(data){$('#cbox').jflickrfeed({limit:30,qstrings:{id:data.user.id,tags:tag},itemTemplate:'
<li>'+'
<a rel="colorbox" href="{{image}}" title="{{title}}">'+'
<img src="{{image_m}}" alt="{{title}}" />'+'</a>'+'</li>'},function(data){$('#cbox
a').colorbox();});});$.lazy([{src:'/forum/jflickrfeed/colorbox/colorbox/jquery.colorbox-min.js',name:'colorbox',dependencies:{css:['/forum/jflickrfeed/jflickrfeed.css','/forum/jflickrfeed/colorbox/example1/colorbox.css']}}]);});</script>
<ul id="cbox" class="thumbs"></ul>
</div>
<div id="sig63167" class="signature"></div>
</div>
</div>
</div>
the problem is you're assuming that the this context when you're executing within the script block is the script block itself, which is incorrect. If there is no context explicitly given, then your context is the window DOM element. Is there any reason you can't move this code to the page level, and initialize all the posts at page load?
$(function() {
$('.post').each(function(i,item) {
console.log(this); //Post DOM element.
//execute your flick retrieval code here.
});
}
Have you tried Javascript's DOM functions to add it?
http://www.javascriptkit.com/javatutors/dom2.shtml
For example, to insert right after the current script, with id "script1":
document.getElementById("script1").parentNode.appendChild( newelement );
You can add raw html too, just set innerHTML of the new element.