I need to create divs with nested divs inside it - javascript

have a look at the code
Html Code :
<div class="container content-rows" id="contentdisplay">
<div class="col-md-1" id="snocontent">abcd</div>
<div class="col-md-3" id="pgnamecontent">abcd</div>
<div class="col-md-3" id="cmpcontent">abcd</div>
<div class="col-md-2" id="datecontent">abcd</div>
<div>
<button onclick="createdivs()"><span class="glyphicon glyphicon-king" class="addtrainersbutton" id="addtrainersbutton" title="Add Trainers"></span></button>
<button onclick="edit_program()"><span class="glyphicon glyphicon-pencil" id="editprogrambutton" title="Edit Program"></span></button>
<span class="glyphicon glyphicon-user" id="assigntrainersbutton" title="Assign Trainers for the Program"></span>
<span class="glyphicon glyphicon-remove" id="deleteprogrambutton" title="Delete the Program"></span>
</div>
Javascript Code:
function createdivs() {
var i;
for (i = 0;i < 10;i++)
{
divc = "<div>.container.content-rows";
var list = document.createElement("divc");
document.body.appendChild(list);
list.className = "proglist";
}
}
I have a few questions, please clarify them or explain with code:
10 divc's are created but there are no other div elements inside them, only the first div has some content in it.. other divs are just created and they dnt even occupy space inside the webpage
I want the div to be aligned to the first div, ie., instead of document.body.appendChild I need something like document.div.appendChild, whereas the created divs should be appeneded with the first div..
Please let me know how can I get them with explanation.. Thank you in advance..

10 divc's are created but there are no other div elements inside them, only the first div has some content in it.. other divs are just created and they dnt even occupy space inside the webpage
Space isn't occupied because they don't have any content added to them. You add content to an element just like you do with document.body - appendChild() for example.
I want the div to be aligned to the first div, ie., instead of document.body.appendChild I need something like document.div.appendChild, whereas the created divs should be appeneded with the first div..
Elements have such a method:
function createdivs() {
var i;
for (i = 0; i < 10; i++) {
divc = "<div>.container.content-rows";
var divc = document.createElement("div");
divc.classList.add("container");
divc.classList.add("content-rows");
divc.classList.add("proglist");
divc.textContent = "I'm div #" + i;
document.getElementById('contentdisplay').appendChild(divc);
createNestedDivs(divc);
}
}
function createNestedDivs(selector) {
function appendToNode(node, content) {
// ideally content would also be a Node, but for simplicity,
// I'm assuming it's a string.
var inner = document.createElement('span');
inner.textContent = content;
node.appendChild(inner);
}
if (selector instanceof Node) {
appendToNode(selector, "inner");
return;
}
var selected = Array.prototype.slice.call(document.querySelectorAll(selector));
selected.forEach(function(el) {
appendToNode(el, "inner");
});
}
<div class="container content-rows" id="contentdisplay">
<div class="col-md-1" id="snocontent">abcd</div>
<div class="col-md-3" id="pgnamecontent">abcd</div>
<div class="col-md-3" id="cmpcontent">abcd</div>
<div class="col-md-2" id="datecontent">abcd</div>
<div>
<button onclick="createdivs()"><span class="glyphicon glyphicon-king" class="addtrainersbutton" id="addtrainersbutton" title="Add Trainers"></span>
</button>
<button onclick="edit_program()"><span class="glyphicon glyphicon-pencil" id="editprogrambutton" title="Edit Program"></span>
</button> <span class="glyphicon glyphicon-user" id="assigntrainersbutton" title="Assign Trainers for the Program"></span>
<span class="glyphicon glyphicon-remove" id="deleteprogrambutton" title="Delete the Program"></span>
</div>
The createNestedDivs() function takes care of if you want to append another child to each created element. You can pass it a Node or string and it will treat them as expected. createNestedDivs() works by the same principles as the modifications I made to createdivs(). The case for handling a Node is simple enough, but the string handling is a little less clear:
The Array.prototype.slice.call is necessary because document.querySelectorAll returns a NodeList, which isn't an array, and I can't use Array.prototype.forEach() on it.
Also, related reading here: http://www.w3.org/wiki/The_principles_of_unobtrusive_JavaScript

Related

Get the table row id on click (HTML+JS)

I have this tag:
<td align="center">
<div class="dropdown">
<button onclick="DropdownShow(this)" class="btn btn-default glyphicon glyphicon-picture"></button>
<div id="#TableRowId" class="dropdown-content">
Show
Edit
</div>
</div>
</td>
and JS function:
function DropdownShow(element) {
var elm = document.getElementById(element.querySelector(".dropdown-content").id);
elm.classList.toggle('show');
}
I want when I click on the image glyphicon at the table, to show the dropdown div tag with the class="dropdown-content". To do that I need the each row ID, and I have it on the variable #TableRowId. How can I do that?
You are passing the reference of clicked button so you need to get the element by getting its parent element where parent node can get from parentNode property.
function DropdownShow(element) {
var elm = element.parentNode.querySelector('.dropdown-content')
elm.classList.toggle('show');
}
FYI: If there is no whitespace after the button then you can use nextSibling property to get the element.
var elm = element.nextSibling;
or use nextElementSibling property to get the element even there is a text node.
var elm = element.nextElementSibling;
Check polyfill option for ie8.
I would pass the #TableRowId to the button as a data attribute like this:
<td align="center">
<div class="dropdown">
<button data-dropdown-content-id="#TableRowId" onclick="DropdownShow(this)" class="btn btn-default glyphicon glyphicon-picture"></button>
<div id="#TableRowId" class="dropdown-content">
Show
Edit
</div>
</div>
</td>
And then your javascript would simply be:
function DropdownShow(element) {
var dropDownContentId = element.getAttribute("data-dropdown-content-id");
var elm = document.getElementById(dropdownContentId);
elm.classList.toggle('show');
}
This would give you the most robust code, because it doesn't depend on the relationships (sibling/parent/child etc) between the two elements.

How to toggle a class in my code, and what am I doing wrong?

I have CSHTML code as follows. I need to toggle a class on click, which is given in the below Javascript code.
<div class="accordion bar-heading-padding" id="#accordion2" onclick="getclassofitag(this)">
<div class="accordion-group">
<div class="accordion-heading datalist" data-toggle="collapse" data-parent="#accordion2" href="##i.Id">
#*<i class="fa fa-chevron-up table-middle icon-width" aria-hidden="false"></i>*#
<i class="fa fa-chevron-down table-middle icon-width" aria-hidden="true"></i>
<h1 class="accordion-toggle table-middle">
#Html.Raw(#i.Name)
</h1>
</div>
<div id="#i.Id" class=" collapse out">
<div class="accordion-inner">
<img ng-src="#i.ImagePath" alt="logo" class="img-thumbnail img-wrap content-image" />
<h1>#Html.Raw(#i.Name)</h1>
<h3>#Html.Raw(#i.Title)</h3>
<br />
#Html.Raw(#i.BioDetail)
</div>
</div>
</div>
</div>
and the Javascript code for toggling class of the i element.
function getclassofitag(element) {
iTags = element.getElementsByTagName("i");
iTags.classList.toggle('fa-chevron-down');
itags.classList.toggle('fa-chevron-up');
}
I want to toggle the classes of the i element (<i) on click. What code do I have to write to do that? Where did I go wrong?
document.getElementsByTagName() returns an HTMLCollection object which contains a collection of DOM objects. The collection itself does not have a .classList property (like you are trying to do). That is a property of a DOM element, not the collection object. Thus, your iTags variable does not have a .classList` property on it.
So, you need to iterate the iTags HTMLCollection and use .classList on each individual DOM element.
function getclassofitag(element) {
var item, iTags = element.getElementsByTagName("i");
for (var i = 0; i < iTags.length; i++) {
item = iTags[i];
item.classList.toggle('fa-chevron-down');
item.classList.toggle('fa-chevron-up');
}
}
Note: I also declared your iTags variable as a local variable so you aren't using an implicit global (which is a bad practice).
hope this will solve your problem
$(document).ready(function () {
$('.collapse').on('shown.bs.collapse', function () {
$(this).parent().find(".fa-chevron-down").removeClass("fa-chevron-down").addClass("fa-chevron-up");
});
$('.collapse').on('hidden.bs.collapse', function () {
$(this).parent().find(".fa-chevron-up").removeClass("fa-chevron-up").addClass("fa-chevron-down");
});
});

Issues with find() when inserting html dynamically using jquery

I have a modal with a grid of buttons representing different html components. When one of the buttons is pressed, some html is supposed to be injected into the page once the modal closes. However, I'm having trouble targeting the specific column where the html is to be injected. Here's my code:
<div class="row" id="newRow">
<div class="col-md-12 column">
<button class="btn addElement" href="#" data-toggle="modal" data-target="#add-element"><i class="fa fa-plus fa-3x add-item"></i></button>
</div>
</div>
And in my js file I have some code to assign an id to the column div (since there could potentially be many columns with this addElement button) that looks like this:
...
$(this).parent().next().children().find('.column').assignId();
...
Up to this point, everything works well. I'm having no trouble getting the column a unique id (defined in my assignId() function).
As I mentioned, the addElement button gets clicked, opening a modal which is when this code is executed:
$(document).on('click', 'button.addElement', function (e) {
e.preventDefault();
$('#add-element').modal('show').draggable();
var col = $('button.addElement').parent();
// debugging in the browser verifies that the colId
// successfully stores the id attribute for the column
var colId = col.attr('id');
addElements(colId);
});
...
function addElements(colId) {
$('#insert-paragraph').on('click', function () {
var html_content = '<div class="box" data-type="paragraph">...</div>';
$("#newRow").find("#"+colId).html(html_content)
$('#add-element').modal('hide');
});
}
It's on this line: $("#newRow").find(colId).html(html_content); that I'm having the issue. My guess is that the formatting for find(...) is wrong and that I can't just insert a variable like that, but I've tried a few different things and nothing seems to be working.
Any help is very much appreciated.
Thanks!
UPDATE:
#juvian suggested writing a few of the variables' values to the console:
console.log(colId);
console.log($("#newRow")).length;
console.log($("#newRow").find("#"+colId).length);
console.log($("#newRow").find("#"+colId).html());
I logged these values twice. First, just before passing colId into the addElements function and in the addElements function immediately after $(#newRow").find("#"+colId).html(html_content); The results of those two tests are as follows:
Values prior to running addElements:
console.log(colId); = 8153-1076-641d-3840
console.log($("#newRow")).length; = Object[div#newRow.row.clearfix]
console.log($("#newRow").find("#"+colId).length); = 1
console.log($("#newRow").find("#"+colId).html()); = <button class="btn addElement"...>...</button>
Values after the insert-paragraph button is pressed:
console.log(colId); = 8153-1076-641d-3840
console.log($("#newRow")).length; = Object[div#newRow.row.clearfix]
console.log($("#newRow").find("#"+colId).length); = 1
console.log($("#newRow").find("#"+colId).html()); = <div class="box box-element" data-type="paragraph">...</div>
Interestingly enough, it appears like everything is working like I'd expect it to, however, when it's all said and done, the addElement button remains and the page still renders this:
<div id="newRow" class="row clearfix">
<div id="32aa-ab91-f50d-c3b3" class="col-md-12 column ui-sortable">
<button class="btn addElement" data-target="#add-element" data-toggle="modal" href="#">
<i class="fa fa-plus fa-3x add-item"></i>
</button>
</div>
</div>
.find as most jquery functions, takes a css selector as parametre. Unfortunately, colId is just a string, so it matches no elements (unless colId is html, span or something like that)
You are just missing adding the id selector at the beginning to do an id match:
.find("#"+colId)
I guess The parent of button is a div here which has no id.
var col = $('button.addElement').parent();
thus var colId is getting no value.give that div an id and it should be fine.

How to get a DIV element's value, put them into array and use them later. JS/Jquery

I'd like to get the data-league values of all of those divs, and put them into an array.
What I want to do: Get all those values, save them, and then loop through them, and call a .click on those divs.
I don't know if there's an easier way to do this.
I guess it also has to loop through the divs where ID=128, and find the data-league values, right?
Honestly I'm completely stuck, so any help whatsoever would be appriciated.
Thank you.
Extra info: Basically the end result being, on click of a button, all those 'thumbnails' should open in a new tab. All tabs being different streams.
(See image)
In the example you provided the same id (128) has been used multiple times. This is not allowed. Iterating through the ids will not work.
This means you have to look for another possibility. Getting all div elements with a certain class would be possible, like in the example:
var divs = document.getElementsByClassName('videoPanel');
Now you can iterate through this collection, extract the values for the attribute data-league and save them somewhere, for example in an array:
var dataLeagueValues = [];
for (var i = 0; i < divs.length; i++) {
dataLeagueValues.push(divs[i].getAttribute('data-league'));
}
Now you have all values in the array dataLeagueValues. You can use them further in your script.
You could use the $('[attribute]') selector to select elements with data-league, you can then use .each(); to loop them.
The following example triggers a click on every element with a data-league attribute:
$('[data-league]').each(function() {
$(this).trigger('click');
});
You could also make the selector more specific to only match these elements by their shared class name videoPanel e.g.
$('.videoPanel[data-league]').each(...);
Will target all elements with a class of videoPanel and an attribute data-league
To match what you need the full example would be:
var leagues = [];
$('.videoPanel[data-league]').each(function() {
leagues.push($(this).attr('data-league'));
});
Following code snippet will your insert all data-league into an array.
var leagues=[];
$('.vedioPnnel').each(function() {
var league = $(this).data('league');
leagues.push(league);
});
console.log(leagues);
I propose to use the javascript forEach function like in the folowing snippet.
Alternatively you can use:
document.querySelectorAll('[id="127"]');
or
document.querySelectorAll('[data-league]')
function getAllDataLeague()
{
var leagues = [];
Array.prototype.forEach.call(document.getElementsByTagName('div'), function (value, index, traversed) {
var attrVal = value.getAttribute('data-league');
if (attrVal) {
leagues.push({'obj': value, 'data-league': attrVal});
}
});
return leagues;
}
var eleFound = getAllDataLeague();
// print result in the html body
document.body.innerHTML += '<p>To access elements: eleFound[index]["data-league"]</p>';
document.body.innerHTML += '<p>To trigger the click event: eleFound[index]["obj"].click()</p>';
document.body.innerHTML += '<p>Elements found:</p>';
for (var i = 0; i < eleFound.length; i++) {
document.body.innerHTML += '<div>data-league:' + eleFound[i]["data-league"] + '</div>';
}
<div class="game-listing-group">
<div class="bold game-listing-name">CS:GO</div><div class="videoPanel vu-channel-tab" id="127" data-channel="https://www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf?channel=m0e_tv" data-league="1284">
<div class="video-thumbnail-con hidden-xs hidden-sm">
<img class="img-responsive video-thumbnail full-width" src="https://static-cdn.jtvnw.net/previews-ttv/live_user_m0e_tv-320x180.jpg">
</div>
<div class="videoPanelTextBg">
<p class="indexVideoPanelTitle">Dragon lore giveaway NOW</p>
<span class="indexVideoPanelGoldCount vu-league-gold pull-right" style="display: none;"></span>
</div>
<div class="indexVideoPanelGoldCount video-upcoming">
<i class="glyphicon glyphicon-time"></i>
<span class="vu-league-start"></span>
</div>
</div><div class="videoPanel vu-channel-tab" id="127" data-channel="https://www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf?channel=freakazoid_tv" data-league="1296">
<div class="video-thumbnail-con hidden-xs hidden-sm videoPanelTextBgActive">
<img class="img-responsive video-thumbnail full-width" src="https://static-cdn.jtvnw.net/previews-ttv/live_user_freakazoid_tv-320x180.jpg">
</div>
<div class="videoPanelTextBg">
<p class="indexVideoPanelTitle">BIRTHDAY IN 24HOURS! #c9freakazoid</p>
<span class="indexVideoPanelGoldCount vu-league-gold pull-right" style="display: none;"></span>
</div>
<div class="indexVideoPanelGoldCount video-upcoming">
<i class="glyphicon glyphicon-time"></i>
<span class="vu-league-start"></span>
</div>
</div><div class="videoPanel vu-channel-tab" id="127" data-channel="https://www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf?channel=gripex90" data-league="1301">
<div class="video-thumbnail-con hidden-xs hidden-sm">
<img class="img-responsive video-thumbnail full-width" src="https://static-cdn.jtvnw.net/previews-ttv/live_user_gripex90-320x180.jpg">
</div>
<div class="videoPanelTextBg">
<p class="indexVideoPanelTitle">Gripex - Most dedicated Lee sin! Top 50 Challenger</p>
<span class="indexVideoPanelGoldCount vu-league-gold pull-right" style="display: none;"></span>
</div>
<div class="indexVideoPanelGoldCount video-upcoming">
<i class="glyphicon glyphicon-time"></i>
<span class="vu-league-start"></span>
</div>
</div><div class="videoPanel vu-channel-tab" id="127" data-channel="https://www-cdn.jtvnw.net/swflibs/TwitchPlayer.swf?channel=phantoml0rd" data-league="1346">
<div class="video-thumbnail-con hidden-xs hidden-sm">
<img class="img-responsive video-thumbnail full-width" src="https://static-cdn.jtvnw.net/previews-ttv/live_user_phantoml0rd-320x180.jpg">
</div>
<div class="videoPanelTextBg">
<p class="indexVideoPanelTitle">Level 400 Gambler LOL - Cycled over 3,000,000 in s</p>
<span class="indexVideoPanelGoldCount vu-league-gold pull-right" style="display: none;"></span>
</div>
<div class="indexVideoPanelGoldCount video-upcoming">
<i class="glyphicon glyphicon-time"></i>
<span class="vu-league-start"></span>
</div>
</div></div>

Factorize use of repeated similar div blocks with javascript

I'm building an app with html/javascript.
I feel my code could be made cleaner and factorized with some javascript but don't know how to find this code (while keeping a very efficient page load performance).
<div id="deal-zone">
<div class="deal">
<span class="beamer" data-toggle="modal" data-target="#myModal"/></span>
</div>
<div class="deal">
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
<div class="deal">
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
<div class="deal">
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
<div class="deal" >
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
<div class="deal" >
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
<div class="deal">
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
<div class="deal">
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
<div class="deal">
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
<div class="deal">
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
</div>
As you see it's really very very repetitive as I have 10 times the exact same block.
What I am trying to do is simply something like this and i lack the javascript chops for it:
function(){display in the html make 10 times repeatedly
<div class="deal">
<span class="beamer" data-toggle="modal" data-target="#myModal"></span>
</div>
}
Note: if you wonder by the way, javascript is dynamically giving each a certain position on the page.
$(document).ready(function(){
function getRandomInt(min, max) {
return Math.random() * (max - min + 1) + min;
}
$(".deal").each(function () {
var topPosition = getRandomInt(8, 70);
var leftPosition = getRandomInt(8, 92);
$(this).css({
"top": topPosition+"%",
"left": leftPosition+"%",
});
});
});
How can I do this ?
Here are some tips that might you.
If you want to use jQuery to generate the HTML for you, you can do the following:
var numBlocks = 10;
var $dealZone = $("#deal-zone");
var $toAppend = $('<div class="deal"><span class="beamer" data-toggle="modal" data-target="#myModal"></span></div>');
for(var c = 0; c < numBlocks; c++)
$dealZone.append($toAppend.clone());
JSFiddle to demonstrate (used <li>, sorry)
However, I just want to point out, that is not a great SEO way to do things. Dynamic HTML is not picked up so well by Search Engine crawlers, so it would look to the Search Engines that your content was missing.
Your first <span> tag has a closing slash. This is not valid HTML. Should be:
data-target="#myModal">
and not
data-target="#myModal"/>
It looks like your HTML is a list of some sort. Semantically, you might want to consider using a list structure with <ul> and <li> tags. You can still style these to remove the padding, margin, and bullets to display them any way you would like.
To simplify CSS classes, (using your current HTML) you could remove the class="deal" and class="beamer" from every child element. If you need this class for CSS styling, you can use the descendant selector (which targets all immediate children of the parent) as follows:
#deal-zone > div { /*styles here*/ } /* targets the current "deal" class */
#deal-zone > div > span { /*styles here*/ } /* targets the current ".beamer" class */
You could also use the descendant selector in your jQuery function. Use the following JavaScript to target the children without having the "deal" class:
$("#deal-zone > div").each(function () { ... }
In addition, you most likely don't need the repetitive data-toggle and data-target attributes on all of the children. Since they are all the same, you can assign these attributes to the parent and access them with the following jQuery:
var $dealZone = $('#deal-zone');
var data-toggle = $dealZone.attr('data-toggle');
var data-target = $dealZone.attr('data-target');
In summary, here is a working example in JSFiddle

Categories