JavaScript - Iterate over dynamically create html - javascript

I am trying to write a constructor function with a method that loops over a number of rows (numerical argument), and for each of the individual rows then loops over a number of dots(numerical argument). In Each of the two loops a portion of html will be rendered. I can get the first portion html to render but when i try to loop over second portion using a selector from the previously rendered html nothing happens. What am i missing ?
HTML CODE
<div class="container">
<h1 class="heading">Random Colors</h1>
<div class="row">
<div id="frame" class="col-xs-12">
<!-- CONTENT PUSHED BY JAVASCRIPT -->
</div>
</div><!-- Ends .row -->
</div><!-- Ends .container -->
JAVASCRIPT CODE
var ColorDots = function(rows, dots) {
this.numOfRows = rows;
this.numOfDots = dots;
this.renderDots();
};
ColorDots.prototype.renderDots = function() {
this.rowTemplate = '<div class="color-dot row"></div>';
this.iconTemplate = '<i class="fa fa-circle icon" aria-hidden="true"></i>';
for ( var r = 0; r < this.numOfRows; r++) {
document.getElementById('frame').innerHTML += this.rowTemplate;
for ( var i = 0; i < this.numOfDots; i++) {
document.getElementsByClassName('color-dot').innerHTML += this.iconTemplate;
}
}
};
SOLUTION (javascript only)
var ColorDots = function(rows, dots) {
// Properties
this.numOfDots = dots;
this.numOfRows = rows || 1;
this.iconHtml = '<i class="fa fa-circle icon" aria-hidden="true"></i>';
this.renderRows();
};
ColorDots.prototype.renderRows = function() {
this.rowHtml = '';
for ( var r = 0; r < this.numOfRows; r++) {
this.rowHtml += '<div class="color-dot row">';
for ( var i = 0; i < this.numOfDots; i++) {
this.rowHtml += this.iconHtml;
}
this.rowHtml += '</div>';
}
document.getElementById('frame').innerHTML = this.rowHtml;
};
Thank you #rainerh for giving me the answer to my question. How ever after considering what #shilly said in the comment in regards to using .innerHTML within for loops i made some changes to my code to reflect his suggestion. Hopefully this will be useful for other trying to do something similar to me.

First the css class is color-dot and not color-dots as you have it in your selector.
Secondly getElementsByCLassName returns an array. So have to use an index here.
ColorDots.prototype.renderDots = function() {
this.rowTemplate = '<div class="color-dot row"></div>';
this.iconTemplate = '<i class="fa fa-circle icon" aria-hidden="true"></i>';
for ( var r = 0; r < this.numOfRows; r++) {
document.getElementById('frame').innerHTML += this.rowTemplate;
for ( var i = 0; i < this.numOfDots; i++) {
document.getElementsByClassName('color-dots')[r].innerHTML += this.iconTemplate;
}
}
};

Related

How do I create different button for each item in an array / JavaScript

Here's my code:
var never = [1,2,3,4,7];
function please () {
for (var i = 0; i < never.length; i++) {
document.getElementById("more").innerHTML = "<button>" + never[i] + "</button>";
}
}
I have a button in my HTML that invokes this function but it only creates a button for the last item (7). How can I create a different button for each one of the items in the array? Any help is appreciated.
The best way is to append created buttons in container.Each by each
var never = [1,2,3,4,7];
function please () {
var more=document.getElementById("more");
for (var i = 0; i < never.length; i++) {
var butt=document.createElement("button");
butt.innerHTML=never[i];
more.appendChild(butt);
}
}
By appending to innerHTML instead of assigning, like
var never = [1,2,3,4,7];
function please () {
for (var i = 0; i < never.length; i++) {
document.getElementById("more").innerHTML += "<button>" + never[i] + "</button>";
}
}
please();
<div id="more">
</div>

Jquery code won't run loaded from footer, but run from console

I'm trying to get a value and pass it to a hidden input in order to send form data via $_POST. I have a dropdown button and the following code in order to update the value when a user select an option:
jQuery(document).ready(function($) {
var espSeleccionada = $('button[data-id="select-especialidad"]');
espSeleccionada.on("click", function() {
var x = $(this).text();
$('#boton-prueba').text(x);
});
});
The code is supposed to pass the value from one button to another, as shown in here the example, but, when I load the code from WordPress header/footer/theme nothing happens. Instead, when I write it on the console it works fine. There are no JS errors in console.
Please note that I'm using .text() to test if the code works, but it would have .val() before going live.
This is the button HTML:
<button type="button" class="btn dropdown-toggle btn-default" data-toggle="dropdown" data-id="select-especialidad" title="Hacienda" aria-expanded="false"><span class="filter-option pull-left">Hacienda</span></button>
Here is an example: https://fiddle.jshell.net/t9mvoxj5/
EDIT TO INCLUDE THE FULL CODE:
( function( $ ) {
var num_cols = 3,
container = $('#menu-preparadores-de-oposiciones-en'),
listItem = 'li',
listClass = 'sub-list';
container.each(function() {
var items_per_col = new Array(),
items = $(this).find(listItem),
min_items_per_col = Math.floor(items.length / num_cols),
difference = items.length - (min_items_per_col * num_cols);
for (var i = 0; i < num_cols; i++) {
if (i < difference) {
items_per_col[i] = min_items_per_col + 1;
} else {
items_per_col[i] = min_items_per_col;
}
}
for (var i = 0; i < num_cols; i++) {
$(this).append($('<ul ></ul>').addClass(listClass));
for (var j = 0; j < items_per_col[i]; j++) {
var pointer = 0;
for (var k = 0; k < i; k++) {
pointer += items_per_col[k];
}
$(this).find('.' + listClass).last().append(items[j + pointer]);
}
}
});
if ($("body").hasClass("page-id-64")) {
$('.tab-content').addClass('col-sm-9');
$('#custom-tabs-0').tabCollapse();
}
} ) ( jQuery );
jQuery(document).ready(function($) {
var espSeleccionada = $('button[data-id="select-especialidad"]');
espSeleccionada.on("click", function() {
var x = $(this).text();
$('#boton-prueba').text(x);
});
});
Well, the code is fine, the problem is that the target button[data-id="select-especialidad"] is being used by bootstrap-select and even if bootstrap-select loads before my code, it takes a few seconds (or at least a bit) to process the information.
So the code should be wrapped after a function that checks that the event has been loaded. This is the final code:
$('#select-especialidad').on('loaded.bs.select', function (e) {
var y = $(this).val();
$('#select-especialidad-hidden').val(y);
var espSeleccionada = $('button[data-id="select-especialidad"] > span.filter-option.pull-left');
espSeleccionada.on("click", function() {
var x = $(this).text();
$('#select-especialidad-hidden').val(x);
});
});
loaded.bs.select here more info on the bootstrap-select events.

Insert a page break after specific string from an array javascript

I have made a code that needs to make page-breaks after certain number of new lines or words. I have set up an array that tell me where it should cut in my element. As you can see in my jsFiddle you can see a console.log(); that shows I need to cut the text.
I would like to get help on how to create a closing </div> inserted after the specific string from my array(). I would like to have a closing </div> and a creation of a new <div>
More details about the code
// $(this)
$(this) = $('.c_84');
The HTML example
<div class=" onerow counting_1"><div class="newDiv"></div>
<div class="onefield c_6937">
<!-- This is where I want to generate the new divs -->
<table class="textarea" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="value"><!-- Content String --></td>
</tr>
</tbody>
</table>
</div>
</div>
Here is my code logic so far.
// The class c_6937 is the class test in my jsFiddle
// I did this just to remove extra html and focus on the problem
// Start
$(this).find('.c_6937').parent().prepend('<div class="newDiv">');
var countReqNumberOfPages = newChunk.length;
for (var key in newChunk) {
// If we find the first chunk, insert </div><div class="newDiv"> after it.
}
// End
$(this).find('.c_6937').parent().append('</div>');
Could it be possible to run a str_replace() function inside my array() and replace the current string with the exact same string plus the closing divs?
EDIT 1 : I added extra comments in the code for a better understanding of the problem and added a possible solution.
I'm not sure whether you are after something like this
<script type="text/javascript">
var wordsPerLine = 15;
var minWordsPerLine = 5;
var linesPerPage = 30;
var linesToStopAfter = [];
function checkForDot(pos,masterArray){
if(pos < 0){
return false;
}
var line = masterArray[pos];
if(line.indexOf('.') !== -1){
return line;
}
else{
return checkForDot(pos-1,masterArray);
}
}
function chunk(lines) {
var masterLines = [];
for (i = 0; i < lines.length; i++) {
var sentence = [];
var wordsList = lines[i].split(" ");
var wordCount = 0;
for (j = 0; j < wordsList.length; j++) {
if(wordCount >= wordsPerLine){
wordCount = 0;
masterLines.push(sentence.join(" "));
sentence = [];
sentence.push(wordsList[j]);
}
else{
sentence.push(wordsList[j]);
}
wordCount++;
}
masterLines.push(sentence.join(" "));
}
return masterLines
}
$(document).ready(function()
{
var html = $("#test").html();
$("#test").html('<div class="newDiv">'+html+'</div>');
var lines = chunk($("#test").text().split("\n"));
var count = 0;
for (k = 0; k < lines.length; k++) {
count++;
if(count >= linesPerPage){
count = 0;
linesToStopAfter.push(checkForDot(k,lines));
}
}
for(j=0; j<linesToStopAfter.length;j++)
{
toreplace = $("#test").html().replace(linesToStopAfter[j], linesToStopAfter[j]+"</div><div class='newDiv'>");
$("#test").html(toreplace)
}
cleanedhtml = $("#test").html().replace(/<\s*div[^>]*><\s*\/\s*div>/g,"");
$("#test").html(cleanedhtml)
});
</script>

js - variable to take a certain value

Why is not the variable i accessible in the last line? Or to be more precise, it takes the value of the last value of i in the iteration +1 (which actually makes sense). What I would like it to take is the same value that it takes in li_hotel[i] when registering with the event.
for (var i = 0; i < li_hotel.length; i++) {
li_hotel[i].addEventListener('click', function(event) {
document.querySelector('#content > .left').innerHTML = this.innerHTML;
document.querySelector('#content > .right').innerHTML = i;
})
};
Thank you.
Because by the time that code is hit, the loop is done. You need a closure:
for (var i = 0; i < li_hotel.length; i++) {
(function(i) {
li_hotel[i].addEventListener('click', function(event) {
document.querySelector('#content > .left').innerHTML = this.innerHTML;
document.querySelector('#content > .right').innerHTML = i;
})
})(i)
};
Here's another approach, perhaps somewhat unusual: You can build the function from the Function() constructor, which allows you to concatenate i into the body string.
Warning: Stack Overflow's syntax highlighting is not up to the task.
var li_hotel = document.querySelectorAll('#hotel>li');
for (var i = 0; i < li_hotel.length; i++) {
var body = '\
document.querySelector(\'#content > .left\').innerHTML = this.innerHTML;\
document.querySelector(\'#content > .right\').innerHTML = '+i+';\
';
li_hotel[i].addEventListener('click', new Function('event',body) );
};
<ul id="hotel">
<li>hotel1</li>
<li>hotel2</li>
<li>hotel3</li>
</ul>
<div id="content">
<div class="left"></div>
<div class="right"></div>
</div>
This avoids the overhead of closures.

Clone element and repeat until viewport is filled

Learning JavaScript and this is my first ever real 'project''
I've created a loop to check that the .background element is smaller than the client, if it is then add the the slice node until the .background element is the same height as the client.
The issue is that too many slice nodes are being added and sometimes crashing the browser.
Also, is there a way to clone the HTML node and repeat it instead of using:
background.innerHTML += '<span class=slice></span>';
If is there a better way of doing what I'm trying to do then please do let me know!
JSFiddle
http://jsfiddle.net/8ryAD/11/
HTML
<div class="master">
<a id="btn-nav">
<span></span>
<span>Menu</span>
<span></span>
</a>
<nav id="main-nav">
<div class="background">
<div class="slice"></div>
</div>
</nav>
</div><!-- end master -->
JS
(function () {
'use strict';
var w = document.documentElement.clientHeight;
var menuBtn = document.getElementById('btn-nav');
var slice = document.querySelectorAll('.slice');
var background = document.getElementsByClassName('background')[0];
//var mainNavHeight = document.getElementById('main-nav').clientHeight;
//var slideAdd = slice.cloneNode(true);
//var windowHeight = window.innerHeight;
menuBtn.addEventListener('click', function() {
menuBtn.classList.add('open');
for(var i = background.clientHeight; i < w; i++) {
background.innerHTML += '<span class=slice></span>';
//for(var i = 0; i < slice.length; i++){
// slice[i].style.opacity = 1;
// }
}
}, false);
}());
Done it. If someone knows a better way of doing this then please do let me know! Thanks.
var slice = document.querySelectorAll('.slice');
var menuBtn = document.getElementById('btn-nav');
var b = document.getElementsByClassName('background')[0];
var a = document.getElementById('main-nav').clientHeight
menuBtn.addEventListener('click', function() {
menuBtn.classList.add('open');
for(var i = b.clientHeight; i < a; i++) {
if(b.clientHeight == a) {
break;
} else {
b.innerHTML += '<span class=slice></span>';
}
}
}, false);

Categories

Resources