Find duplicates by one of multiple classes - javascript

I have divs with multiple classes (brand and color) like:
<div id="pad">
<div class="bmw white"> </div>
<div class="porsche yellow"> </div>
<div class="porsche red"> </div>
<div class="bmw white"> </div>
<div class="bmw blue"> </div>
<div class="bmw white"> </div>
</div>
<div id="same"></div>
And when I need to know how many duplicate brands I have in #pad I use this code:
function sameCars() {
var elems = $("#pad div").length;
var brands = ['bmw', 'porsche'];
for (var i=0; i<brands.length; i++) {
var k = 0;
for (var j=0; j<elems; j++) {
var mainDiv = document.getElementById('pad'),
childDiv = mainDiv.getElementsByTagName('div')[j];
if(childDiv.className.split(' ')[0] == brands[i]) {
k = k+1;
}
}
addiv = document.getElementById("same");
addiv.innerHTML += brands[i] + ": " + k;
}
}
Now I want to make changes in my code:
1) to find duplicates for all classes (there could be more classes, first one is brand, the second one is color, etc) like bmw: 4, porsche: 2, white: 3, black: 3, sedan: 2, coupe: 3
2) not to use list of brands, colors, etc. I don't want to make a long list of all possible colors or car brands. Just get colors from classname
3) Make my code shorter and more elegant

You just have to dynamically gather all classes fists:
$(document).ready(function () {
var duplicates = {};
var $pad = $('#pad');
$('#pad > div').each(function () {
var classes = $(this)[0].classList;
for (var i = 0; i < classes.length; i++) {
if (typeof duplicates[classes[i]] === 'undefined') {
duplicates[classes[i]] = 1;
} else {
duplicates[classes[i]]++;
}
}
});
for (var j in duplicates) {
$pad.append('<div>'+j+':'+duplicates[j]+'</div>');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pad">
<div class="bmw white"> </div>
<div class="porsche yellow"> </div>
<div class="porsche red"> </div>
<div class="bmw white"> </div>
<div class="bmw blue"> </div>
<div class="bmw white"> </div>
</div>
<div id="same"></div>

You can use jquery to get classes dynamically and apply logic to get unique counts like this.
sameCars();
function sameCars() {
var brands = [];
var colors = [];
$("#pad div").each(function(){
brands.push($(this).attr("class").split(' ')[0])
colors.push($(this).attr("class").split(' ')[1])
});
//console.log(brands)
//console.log(colors)
var cars_count = {};
$.each(brands, function( index, value ) {
cars_count[value] = cars_count[value] + 1 || 1;
});
console.log("Unique cars count :")
console.log(cars_count);
var count_color = {};
$.each(colors, function( index, value ) {
count_color[value] = count_color[value] + 1 || 1;
});
console.log("Unique Colors count :")
console.log(count_color);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pad">
<div class="bmw white"> </div>
<div class="porsche yellow"> </div>
<div class="porsche red"> </div>
<div class="bmw white"> </div>
<div class="bmw blue"> </div>
<div class="bmw white"> </div>
</div>
<div id="same"></div>

Here is a nice way of getting what you want. Note I do not manipulate the DOM, I'll leave that up to you.
function classIsDup(className, setOfClasses)
{
return (setOfClasses.indexOf(className) > -1);
}
function getDuplicates()
{
var setOfClasses = [];
var listOfDuplicates = [];
$('#pad').children('div').each(function( index ) {
if(classIsDup($(this).attr('class'), setOfClasses))
{
listOfDuplicates.push($(this).attr('class'));
}
else
{
setOfClasses.push($(this).attr('class'));
}
});
// just in case dups exist within the list of dups
$.uniqueSort(listOfDuplicates);
}
getDuplicates();

Javascript example (no jquery required)
var parentWrapper = document.getElementById('pad');
var displayWrapper = document.getElementById('same');
var classesList = getUniqueClassList(parentWrapper);
displayCounts(classesList);
function displayCounts(list) {
for (var className in list) {
var number = list[className];
displayWrapper.innerHTML += className + ' ' + number + '<br>';
}
}
function getUniqueClassList(wrapper) {
var list = {};
for (var elem of wrapper.getElementsByTagName('div')) {
for (var cssClass of elem.classList) {
if (!list[cssClass]) {
list[cssClass] = 1;
} else {
list[cssClass]++;
}
}
}
return list;
}
Fiddle https://fiddle.jshell.net/r1rk1xL3/5/

Related

Cycle through divs up and down with Jquery

I need to cycle up and down through two sets of divs simultaneously. This code works well for cycling up the list (button1) but when I tried to create a down button (button2) it messes up the div order and doesn't cycle correctly. How can I alter this code to make it successfully cycle up and down through the list in the correct order?
$(document).ready(function() {
var divs = $('div[id^="num-"]').hide(),
i = 0;
function cycleone() {
divs.hide().eq(i).show();
i = ++i % divs.length;
};
cycleone()
$('#button1').click(function() {
cycleone()
})
});
$(document).ready(function() {
var divsv = $('div[id^="numv-"]').hide(),
iv = 0;
function cycletwo() {
divsv.hide().eq(iv).show();
iv = ++iv % divsv.length;
};
cycletwo()
$('#button1').click(function() {
cycletwo()
})
});
$(document).ready(function() {
var divs = $('div[id^="num-"]').hide(),
i = 0;
function cycleonedown() {
divs.hide().eq(i).show();
i = --i % divs.length;
};
cycleonedown()
$('#button2').click(function() {
cycleonedown()
})
});
$(document).ready(function() {
var divsv = $('div[id^="numv-"]').hide(),
iv = 0;
function cycletwodown() {
divsv.hide().eq(iv).show();
iv = --iv % divsv.length;
};
cycletwodown()
$('#button2').click(function() {
cycletwodown()
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="num-1">1</div>
<div id="num-2">2</div>
<div id="num-3">3</div>
<div id="num-4">4</div>
<div id="num-5">5</div>
<div id="num-6">6</div>
<div id="num-7">7</div>
<div id="numv-1">A</div>
<div id="numv-2">B</div>
<div id="numv-3">C</div>
<div id="numv-4">D</div>
<div id="numv-5">E</div>
<div id="numv-6">F</div>
<div id="numv-7">G</div>
<button id="button1">Up</button>
<button id="button2">Down</button>
As i can see you are using jquery, try the snippet below
$(document).ready(function(){
var lettersArray=[];
var step=1;
var lastStep=parseInt($(document).find('.num').length);
if($(document).find('.numv').length){
$(document).find('.numv').each(function(){
var letter=$(this).html();
lettersArray.push(letter);
});
}
showCycle=function(step){
var stepLetter=lettersArray[step-1];
$('#number').html(step);
$('#letter').html(stepLetter);
}
$(document).on('click','#button1',function(){
step=step+1;
step=step > lastStep ? 1 : step;
showCycle(step);
});
$(document).on('click','#button2',function(){
step=step-1;
step=step < 1 ? lastStep : step;
showCycle(step);
});
});
.num, .numv{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<div id="num-1"class="num">1</div>
<div id="num-2"class="num">2</div>
<div id="num-3"class="num">3</div>
<div id="num-4"class="num">4</div>
<div id="num-5"class="num">5</div>
<div id="num-6"class="num">6</div>
<div id="num-7"class="num">7</div>
<div id="numv-1"class="numv">A</div>
<div id="numv-2"class="numv">B</div>
<div id="numv-3"class="numv">C</div>
<div id="numv-4"class="numv">D</div>
<div id="numv-5"class="numv">E</div>
<div id="numv-6"class="numv">F</div>
<div id="numv-7"class="numv">G</div>
<div id="number">1</div>
<div id="letter">A</div>
<button id="button1">Up</button>
<button id="button2">Down</button>

JQuery Boostrap append row every 2 iterations but columns are ignored

I'm using JQuery 3 and Bootstrap 3. I'm trying to add dynamically row and col but I don't understand my error.
Every 2 iterations I want to add <div class="row"></div> in my dom and in this row I want to add 2 columns.
I'd like to get this HTML :
<div class="row">
<div class="col-xs-6">test</div>
<div class="col-xs-6">test</div>
</div>
<div class="row">
<div class="col-xs-6">test</div>
<div class="col-xs-6">test</div>
</div>
<div class="row">
<div class="col-xs-6">test</div>
</div>
But the current result what I get is :
<div class="row">
<div class="col-xs-6">test</div>
</div>
<div class="row">
<div class="col-xs-6">test</div>
</div>
I don't understand why some col are ignored. Here is my javascript code :
for (var i = 1; i < 5; i++) {
let row = $("<div>", {"class": "row"});
if (i % 2) {
$('.container').append(row);
}
let col = '<div class="col-xs-6">test</div>';
row.append(col);
}
And my jsfiddle : https://jsfiddle.net/gkn4vmx8/
Please try this
let row=null;
for (var i = 1; i < 5; i++) {
if (i % 2) {
row= $("<div>", {"class": "row"});
$('.container').append(row);
}
let col = '<div class="col-xs-6">test</div>';
row.append(col);
}
You can try this:
for (var i = 1; i < 5; i++) {
let row = $("<div>", {"class": "row"});
let col = '<div class="col-xs-6">test</div>';
if (i % 2) {
$('.container').append(row);
row.append(col);
}
row.append(col);
}
You have to reinitialize the row every 2 loops not every time so you can append on the same row to childs
let row;
for (var i = 1; i < 5; i++) {
if (i % 2) {
row= $("<div>", {"class": "row"});
$('.container').append(row);
}
let col = '<div class="col-xs-6">test</div>';
row.append(col);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container"></div>

Having difficuly using a switch statement with classess and for loops

I'm trying to create a photo-view display similar to pintrest except there is a preference checkbox where you can choose the types of images you see.
The problem I'm having is that some of these images fall under multiple catergories, for example there might be a driving shot in the city, so I want that particular image to show if either the city checkbox or drivng images checkbox is clicked.
Currently I have it so say for example, City checkbox is clicked and becomes unchecked, then all images with the city class get a class of displayNone which does the obvious. But I want to make it so if it also has another class that is currently checkedthen it doesnt get the class of displayNone, only when all the classes of that particular image are unchecked is when that image gets the class of displayNone.
I know that the switch statement would be ideal for this scenario but I can't seem to figure out exactly how I'd implement it.
HTML
<!--PREFERENCE CHECKBOX-->
<div class = "preferanceCheckbox">
<form class ="formBox">
<div>
<input type="checkbox" class = "cBDrivingShot">
Driving Shots <br>
</div>
<input type="checkbox" class = "cBCyberPunkShot">
Cyberpunk <br>
<input type="checkbox" class = "cBcityRelated">
city related <br>
</form>
</div>
<div class ="photoSectionAlignment pintrestView imgZ displayNone">
<!-- CYBERPUNK SHOTS -->
<img src="cyberPunkOne.jpg" class = "pImgCyberPunk pImgDrivingShot displayNone">
<img src="cyberPunkTwo.jpg" class = "pImgCyberPunk pImgCity displayNone">
<img src="cyberPunkTwo.jpg" class = "pImgCyberPunk pImgtext displayNone">
<!-- DRIVING SHOTS -->
<img src="drivingShotOne" class = "pImgDrivingShot pImgCity displayNone">
<img src="drivingShotTwo" class = "pImgDrivingShot pImgCity displayNone">
<img src="drivingShotThree" class = "pImgDrivingShot pImgCyberPunk displayNone">
<!-- CITY SHOTS -->
<img src="cityShotOne" class = "pImg pImgCity displayNone">
</div>
CSS
img {
width: 200px;
}
.displayNone {
display: none;
}
JAVASCRIPT
//GLOBAL VARIABLES
//....................................................................
var pintrestView = document.querySelector(".pintrestView");
var dnPintrest = pintrestView.classList.contains("displayNone");
// GLOBAL PREFERANCES CODE
//..................................................................
var drivingCheckBox = document.querySelector(".cBDrivingShot");
var cyberPunkCheckBox = document.querySelector(".cBCyberPunkShot");
var cityCheckBox = document.querySelector(".cBcityRelated");
//PREFERANCES CODE
//..................................................................
// pintrest class variables
var pImgDrivingShot = document.querySelectorAll(".pImgDrivingShot");
var pImgCyberPunk = document.querySelectorAll(".pImgCyberPunk");
var pImgCity = document.querySelectorAll(".pImgCity");
//DRIVING SHOT FUNCTIONALITY
drivingCheckBox.addEventListener("click",drivingShotImgFunctionPintrest);
function drivingShotImgFunctionPintrest(){
if (drivingCheckBox.checked === true){
for (var i = 0; i < pImgDrivingShot.length; i++){
if (pImgDrivingShot[i].classList.contains("displayNone")) {
pImgDrivingShot[i].classList.remove("displayNone");
}
}
}else{
if (drivingCheckBox.checked === false) {
for (var i = 0; i < pImgDrivingShot.length; i++){
if (pImgDrivingShot[i].classList.contains("displayNone") === false) {
pImgDrivingShot[i].classList.add("displayNone");
}
}
}
}
}
//CYBERPUNK FUNCTIONALITY
cyberPunkCheckBox.addEventListener("click",cyberPunkImgFunctionPintrest);
function cyberPunkImgFunctionPintrest(){
if (cyberPunkCheckBox.checked === true){
for (var i = 0; i < pImgCyberPunk.length; i++){
if (pImgCyberPunk[i].classList.contains("displayNone")) {
pImgCyberPunk[i].classList.remove("displayNone");
}
}
}else{
if (cyberPunkCheckBox.checked === false) {
for (var i = 0; i < pImgCyberPunk.length; i++){
if (pImgCyberPunk[i].classList.contains("displayNone") === false) {
pImgCyberPunk[i].classList.add("displayNone");
}
}
}
}
}
//CITY FUNCTIONALITY
cityCheckBox.addEventListener("click",cityImgFunctionPintrest);
function cityImgFunctionPintrest(){
if (cityCheckBox.checked === true){
for (var i = 0; i < pImgCity.length; i++){
if (pImgCity[i].classList.contains("displayNone")) {
pImgCity[i].classList.remove("displayNone");
}
}
}else{
if (cityCheckBox.checked === false) {
for (var i = 0; i < pImgCity.length; i++){
if (pImgCity[i].classList.contains("displayNone") === false) {
pImgCity[i].classList.add("displayNone");
}
}
}
}
}
Here's another take using CSS rules and just one event listener:
<!-- Place this inside your <head> -->
<style id="preferences"></style>
<!--PREFERENCE CHECKBOX-->
<div class = "preferanceCheckbox">
<form class ="formBox">
<input id="drive" type="checkbox" value=".pImgDrivingShot">
<label for="drive">Driving Shots</label><br>
<input id="cyber" type="checkbox" value=".pImgCyberPunk">
<label for="cyber">Cyberpunk</label><br>
<input id="city" type="checkbox" value=".pImgCity">
<label for="city">City Related</label>
</form>
</div>
<div class ="photoSectionAlignment pintrestView imgZ">
<!-- CYBERPUNK SHOTS -->
<img src="https://picsum.photos/id/1018/100/50" class = "pImgCyberPunk pImgDrivingShot displayNone"> <img src="https://picsum.photos/id/1022/100/50" class = "pImgCyberPunk pImgCity displayNone">
<img src="https://picsum.photos/id/1023/100/50" class = "pImgCyberPunk pImgtext displayNone">
<!-- DRIVING SHOTS -->
<img src="https://picsum.photos/id/1041/100/50" class = "pImgDrivingShot pImgCity displayNone">
<img src="https://picsum.photos/id/1015/100/50" class = "pImgDrivingShot pImgCity displayNone">
<img src="https://picsum.photos/id/1019/100/50" class = "pImgDrivingShot pImgCyberPunk displayNone">
<!-- CITY SHOTS -->
<img src="https://picsum.photos/id/1080/100/50" class = "pImg pImgCity displayNone">
</div>
.displayNone {
display: none;
}
const selected = {};
document.querySelector("form").addEventListener("click",(e)=>{
if ( e.target.type === "checkbox" ){
const cssClass = e.target.value;
if (e.target.checked){
selected[cssClass] = true;
} else {
delete selected[cssClass];
};
const cssRules = `${Object.keys(selected).join(",")}{ display: block !important; }`;
document.querySelector("style#preferences").textContent = cssRules;
}
});
Codepen
The code is much more easy to extend: you just add a pair of label/input:checkbox (2 lines) in the form for each new class of images.
<input id="summer" type="checkbox" value=".pImgSummer">
<label for="summer">Summer Related</label>
very first used change event rather than click for the checkbox.
JS
var pintrestView = document.querySelector(".pintrestView");
var dnPintrest = pintrestView.classList.contains("displayNone");
// GLOBAL PREFERANCES CODE
//..................................................................
var drivingCheckBox = document.querySelector(".cBDrivingShot");
var cyberPunkCheckBox = document.querySelector(".cBCyberPunkShot");
var cityCheckBox = document.querySelector(".cBcityRelated");
//PREFERANCES CODE
//..................................................................
// pintrest class variables
var pImgDrivingShot = document.querySelectorAll(".pImgDrivingShot");
var pImgCyberPunk = document.querySelectorAll(".pImgCyberPunk");
var pImgCity = document.querySelectorAll(".pImgCity");
//DRIVING SHOT FUNCTIONALITY
drivingCheckBox.addEventListener("change", drivingShotImgFunctionPintrest);
function drivingShotImgFunctionPintrest() {
for (var i = 0; i < pImgDrivingShot.length; i++) {
if (this.checked) {
pImgDrivingShot[i].classList.remove('displayNone')
} else {
pImgDrivingShot[i].classList.add('displayNone');
}
}
}
//CYBERPUNK FUNCTIONALITY
cyberPunkCheckBox.addEventListener("change", cyberPunkImgFunctionPintrest);
function cyberPunkImgFunctionPintrest() {
for (var i = 0; i < pImgCyberPunk.length; i++) {
if (this.checked) {
pImgCyberPunk[i].classList.remove("displayNone")
} else {
pImgCyberPunk[i].classList.add("displayNone");
}
}
}
//CITY FUNCTIONALITY
cityCheckBox.addEventListener("change", cityImgFunctionPintrest);
function cityImgFunctionPintrest() {
for (var i = 0; i < pImgCity.length; i++) {
if (!this.checked) {
pImgCity[i].classList.remove("displayNone");
} else {
pImgCity[i].classList.add("displayNone");
}
}
}
HTML: remove display none for your parent div
<div class = "preferanceCheckbox">
<form class ="formBox">
<div>
<input type="checkbox" class = "cBDrivingShot">
Driving Shots <br>
</div>
<input type="checkbox" class = "cBCyberPunkShot">
Cyberpunk <br>
<input type="checkbox" class = "cBcityRelated">
city related <br>
</form>
</div>
<div class ="photoSectionAlignment pintrestView imgZ">
<!-- CYBERPUNK SHOTS -->
<img src="cyberPunkOne.jpg" class = "pImgCyberPunk pImgDrivingShot displayNone">
<img src="cyberPunkTwo.jpg" class = "pImgCyberPunk pImgCity displayNone">
<img src="cyberPunkTwo.jpg" class = "pImgCyberPunk pImgtext displayNone">
<!-- DRIVING SHOTS -->
<img src="drivingShotOne" class = "pImgDrivingShot pImgCity displayNone">
<img src="drivingShotTwo" class = "pImgDrivingShot pImgCity displayNone">
<img src="drivingShotThree" class = "pImgDrivingShot pImgCyberPunk displayNone">
<!-- CITY SHOTS -->
<img src="cityShotOne" class = "pImg pImgCity displayNone">
</div>
I would try to reduce the numbers of loops that are in the Javascript code. I think that you really want the same logic, but there are some variables in the styles. If you can identify the variables, then the looping can all be handled in one place. Here's how I approached the problem:
// GLOBAL PREFERENCES CODE
//..................................................................
var drivingCheckBox = document.querySelector(".cBDrivingShot");
var cyberPunkCheckBox = document.querySelector(".cBCyberPunkShot");
var cityCheckBox = document.querySelector(".cBcityRelated");
drivingCheckBox.addEventListener("click", updateFromCheckbox);
cyberPunkCheckBox.addEventListener("click", updateFromCheckbox);
cityCheckBox.addEventListener("click", updateFromCheckbox);
function updateFromCheckbox(evt) {
console.log('In updateFromCheckbox');
var selector = ""; // The class that corresponds to the current checkbox
var otherSelectors = []; // Array of classes that correspond to the OTHER checkboxes
var otherCheckboxes = []; // The boolean settings of the OTHER checkboxes
if (evt.currentTarget === drivingCheckBox) {
selector = "pImgDrivingShot";
otherSelectors = ["pImgCyberPunk", "pImgCity"];
otherCheckboxes = [cyberPunkCheckBox.checked, cityCheckBox.checked];
} else if (evt.currentTarget === cyberPunkCheckBox) {
selector = "pImgCyberPunk";
otherSelectors = ["pImgDrivingShot", "pImgCity"];
otherCheckboxes = [drivingCheckBox.checked, cityCheckBox.checked];
} else if (evt.currentTarget === cityCheckBox) {
selector = "pImgCity";
otherSelectors = ["pImgDrivingShot", "pImgCyberPunk"];
otherCheckboxes = [drivingCheckBox.checked, cyberPunkCheckBox.checked];
}
// Safety check
if (otherSelectors.length != otherCheckboxes.length) {
console.log("otherSelectors AND otherCheckboxes ARE PARALLEL ARRAYS AND SHOULD BE THE SAME LENGTH!");
}
var images = document.querySelectorAll("img");
for (var i = 0; i < images.length; i++) {
var image = images[i];
var isDisplayed = false;
if (image.classList.contains(selector) && evt.currentTarget.checked) {
isDisplayed = true;
} else {
for (var j = 0; j < otherSelectors.length; j++) {
var otherSelector = otherSelectors[j];
var otherCheckboxIsChecked = otherCheckboxes[j];
if (image.classList.contains(otherSelector) && otherCheckboxIsChecked) {
isDisplayed = true;
break;
}
}
}
if (isDisplayed) {
image.classList.remove("displayNone");
} else {
image.classList.add("displayNone");
}
console.log('Got one ', image.src, 'isDisplayed = ', isDisplayed, 'classList = ', image.classList);
}
}

Use a javascript function in a generated html code

I'm programming a simple html form with generated code from javascript.
When i run the code in HTML itself it works, but when i put the script in a separate file, it doesn't work anymore. I tried to change the onclick event, generate the code in html, giving my elements a class and add a eventlistner to that, but nothing worked.
this is a part of my javascript code
function print(){
for (var j =0;j<3;j++){
document.getElementById(idlist[j]).getElementsByTagName("UL")[0].innerHTML="";
for (var i = 0; i<omschList.length;i++){
var li = document.createElement("LI");
if (j==0){
li.innerHTML = (idlist[j+3][i]+"<object align=\"right\" onclick=\"verwijder("+i+")\"><u>verwijder</u></object>");
} else {
li.innerHTML = (idlist[j+3][i]);
}
document.getElementById(idlist[j]).getElementsByTagName("UL")[0].appendChild(li);
}
}
}
function verwijder(index){
for (var i=0;i<3;i++){
idlist[i+3].splice(index, 1);
}
print();
}
EDIT
the full javascript code
(function ($) {
$( document ).ready( function() {
/* VIEWPORT FIXES (http://timkadlec.com/2013/01/windows-phone-8-and-device-width/) */
if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
var msViewportStyle = document.createElement('style');
msViewportStyle.appendChild(
document.createTextNode(
'#-ms-viewport{width:auto!important}'
)
);
document.querySelector('head').appendChild(msViewportStyle);
}
document.getElementById("factuurFormSend").onclick = addLine;
var omschList=[];
var uurprList=[];
var aantalList=[];
var idlist=["omschrijving",
"uurprijs",
"aantal",
omschList,
uurprList,
aantalList]
function addLine(){
omschList.push(document.getElementById("formOmschrijving").value);
uurprList.push(document.getElementById("formUurprijs").value);
aantalList.push(document.getElementById("formUren").value);
print()
}
/*print de lijnen verticaal uit*/
function print(){
for (var j =0;j<3;j++){
document.getElementById(idlist[j]).getElementsByTagName("UL")[0].innerHTML="";
for (var i = 0; i<omschList.length;i++){
var li = document.createElement("LI");
if (j==0){
li.innerHTML = (idlist[j+3][i]+"<object align=\"right\" onclick=\"verwijder("+i+")\"><u>verwijder</u></object>");
} else {
li.innerHTML = (idlist[j+3][i]);
}
document.getElementById(idlist[j]).getElementsByTagName("UL")[0].appendChild(li);
}
}
/*bereken lijntotaal*/
document.getElementById("lijntotaal").getElementsByTagName("UL")[0].innerHTML=""
var subtotaal=0;
for (var i=0; i<uurprList.length;i++){
var totaal = uurprList[i]*aantalList[i];
subtotaal +=totaal;
var li = document.createElement("LI");
li.innerHTML=totaal;
document.getElementById("lijntotaal").getElementsByTagName("UL")[0].appendChild(li);
}
/*subtotaal en btwtotaal wegschrijven*/
document.getElementById("subtotaal").innerHTML=subtotaal;
document.getElementById("btwbedrag").innerHTML=(subtotaal*0.21);
document.getElementById("totaal").innerHTML=(subtotaal*1.21);
}
function verwijder(index){
for (var i=0;i<3;i++){
idlist[i+3].splice(index, 1);
}
print();
}
} );
})(jQuery);
And the HTML code that worked
<body>
<div class="page">
<header class="header">
</header>
<div role="main" class="cf">
<div class="container" id="factuur">
<section id="header">
<div class="col-sm-8">
<h1>Factuur</h1>
</div>
<div class="col-sm-8">Factuur nr. 1</div>
<div class="col-sm-6">
<div>Naam onderneming<br />
Straatnaam nr<br />
Postcode Gemeente<br />
BE 0123 456 789</div>
</div>
<div class="col-sm-6">
<div>Naam Klant<br />
Straatnaam nr<br />
Postcode Gemeente<br />
BE 0123 456 789</div>
</div>
</section>
<section id="content-header">
<div class="col-sm-6">Omschrijving</div>
<div class="col-sm-2">Uurprijs</div>
<div class="col-sm-2">Aantal</div>
<div class="col-sm-2">Totaal</div>
</section>
<section id="content">
<div class="col-sm-6" id="omschrijving"><ul></ul></div>
<div class="col-sm-2" id="uurprijs"><ul></ul></div>
<div class="col-sm-2" id="aantal"><ul></ul></div>
<div class="col-sm-2" id="lijntotaal"><ul></ul></div>
</section>
<section id="totalen">
<div class="col-sm-offset-7 col-sm-3 text-right">Subtotaal</div>
<div class="col-sm-2" id="subtotaal"></div>
<div class="col-sm-offset-7 col-sm-3 text-right">BTW</div>
<div class="col-sm-2" id="btw">21 %</div>
<div class="col-sm-offset-7 col-sm-3 text-right">BTW Bedrag</div>
<div class="col-sm-2" id="btwbedrag"></div>
<div class="col-sm-offset-7 col-sm-3 text-right" style="border-top:1px solid black;">Totaal</div>
<div class="col-sm-2" id="totaal" style="border-top:1px solid black;"></div>
</section>
<section id="factuurknop">
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#factuurModal">
Voeg een factuurlijn toe
</button>
</section>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="factuurModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Voeg een factuur item toe</h4>
</div>
<form>
<div class="modal-body">
<input style="width:30%" type="text" name="formOmschrijving" id="formOmschrijving" placeholder="Omschrijving">
<input style="width:30%" type="text" name="formUurprijs" id="formUurprijs" placeholder="Uurprijs">
<input style="width:30%" type="text" name="formUren" id="formUren" placeholder="uren">
</div>
<div class="modal-footer">
<button type="button" id="factuurFormSend" class="btn btn-primary">Verzenden</button>
</div>
</form>
</div>
</div>
</div>
<script>
document.getElementById("factuurFormSend").onclick = addLine;
var omschList=[];
var uurprList=[];
var aantalList=[];
var idlist=["omschrijving",
"uurprijs",
"aantal",
omschList,
uurprList,
aantalList]
function addLine(){
omschList.push(document.getElementById("formOmschrijving").value);
uurprList.push(document.getElementById("formUurprijs").value);
aantalList.push(document.getElementById("formUren").value);
print()
}
/*print de lijnen verticaal uit*/
function print(){
for (var j =0;j<3;j++){
document.getElementById(idlist[j]).getElementsByTagName("UL")[0].innerHTML="";
for (var i = 0; i<omschList.length;i++){
var li = document.createElement("LI");
if (j==0){
li.innerHTML = (idlist[j+3][i]+"<object align=\"right\" onclick=\"verwijder("+i+")\"><u>verwijder</u></object>");
} else {
li.innerHTML = (idlist[j+3][i]);
}
document.getElementById(idlist[j]).getElementsByTagName("UL")[0].appendChild(li);
}
}
/*bereken lijntotaal*/
document.getElementById("lijntotaal").getElementsByTagName("UL")[0].innerHTML=""
var subtotaal=0;
for (var i=0; i<uurprList.length;i++){
var totaal = uurprList[i]*aantalList[i];
subtotaal +=totaal;
var li = document.createElement("LI");
li.innerHTML=totaal;
document.getElementById("lijntotaal").getElementsByTagName("UL")[0].appendChild(li);
}
/*subtotaal en btwtotaal wegschrijven*/
document.getElementById("subtotaal").innerHTML=subtotaal;
document.getElementById("btwbedrag").innerHTML=(subtotaal*0.21);
document.getElementById("totaal").innerHTML=(subtotaal*1.21);
}
function verwijder(index){
for (var i=0;i<3;i++){
idlist[i+3].splice(index, 1);
}
print();
}
} );
</script>
Place your functions in the global scope if you want to assign the click events inline. Not in the load event handler.
Better would be is not to add the click event inline but use event delegation for it. jQuery has great tools for this. Also your code is a weird combination between plain javascript and jQuery functions. It will work, but in my opinion it's better to stay to one style for readability
(function($) {
$(document).ready(function() {
/* VIEWPORT FIXES (http://timkadlec.com/2013/01/windows-phone-8-and-device-width/) */
if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
var msViewportStyle = document.createElement('style');
msViewportStyle.appendChild(
document.createTextNode(
'#-ms-viewport{width:auto!important}'
)
);
document.querySelector('head').appendChild(msViewportStyle);
}
document.getElementById("factuurFormSend").onclick = addLine;
});
function addLine() {
omschList.push(document.getElementById("formOmschrijving").value);
uurprList.push(document.getElementById("formUurprijs").value);
aantalList.push(document.getElementById("formUren").value);
print()
}
})(jQuery);
var omschList = [];
var uurprList = [];
var aantalList = [];
var idlist = ["omschrijving",
"uurprijs",
"aantal",
omschList,
uurprList,
aantalList
]
/*print de lijnen verticaal uit*/
function print() {
for (var j = 0; j < 3; j++) {
document.getElementById(idlist[j]).getElementsByTagName("UL")[0].innerHTML = "";
for (var i = 0; i < omschList.length; i++) {
var li = document.createElement("LI");
if (j == 0) {
li.innerHTML = (idlist[j + 3][i] + "<object align=\"right\" onclick=\"verwijder(" + i + ")\"><u>verwijder</u></object>");
} else {
li.innerHTML = (idlist[j + 3][i]);
}
document.getElementById(idlist[j]).getElementsByTagName("UL")[0].appendChild(li);
}
}
/*bereken lijntotaal*/
document.getElementById("lijntotaal").getElementsByTagName("UL")[0].innerHTML = ""
var subtotaal = 0;
for (var i = 0; i < uurprList.length; i++) {
var totaal = uurprList[i] * aantalList[i];
subtotaal += totaal;
var li = document.createElement("LI");
li.innerHTML = totaal;
document.getElementById("lijntotaal").getElementsByTagName("UL")[0].appendChild(li);
}
/*subtotaal en btwtotaal wegschrijven*/
document.getElementById("subtotaal").innerHTML = subtotaal;
document.getElementById("btwbedrag").innerHTML = (subtotaal * 0.21);
document.getElementById("totaal").innerHTML = (subtotaal * 1.21);
}
function verwijder(index) {
for (var i = 0; i < 3; i++) {
idlist[i + 3].splice(index, 1);
}
print();
}
If you want to be able to delete an object on click you could do this with jQuery and event delegation pretty easily.
//Wait till the initial DOM loading is done
$(document).ready(function() {
//Attach an event handler to the click event to the button the adds a new object
$("#addObject").on('click', function() {
$('#staticParent').append("<div class='deletableObject'>deletable on click</div>")
});
//Attach event delegation from the element with id staticParent to place a function on
//the click event of all elements with the class deletableObject inside the element with
//id staticParent. Because it's event delegation it will work also for elements with this
//class the will be added later dynamicly.
$("#staticParent").on('click', '.deletableObject', function() {
$(this).remove();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="staticParent" style="min-height: 100px">
<div class="deletableObject">deletable on click</div>
</div>
<button id="addObject">Add</button>

JavaScript Toggle Display

I'm trying to use vanilla JavaScript to toggle display: none and display: block on elements with the same class. It mostly works, but for some reason you need to click the button twice for it to work and it's eating away at me. The code and a link to CodePen is below.
The HTML:
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
<button onclick="toggle('a')">Toggle A</button>
<button onclick="toggle('b')">Toggle B</button>
<button onclick="toggle('c')">Toggle C</button>
<button onclick="toggle('d')">Toggle D</button>
The JS:
function toggle(div) {
var divs = document.getElementsByClassName(div);
for(var i = 0; i < divs.length; i++) {
if(divs[i].style.display === "block") {
divs[i].style.display="none";
}
else {
divs[i].style.display="block";
}
}
}
The Demo:
CodePen
add the style attribute to the divs..
<div class="a" style="display:block">a</div>
<div class="b" style="display:block">b</div>
<div class="c" style="display:block">c</div>
<div class="d" style="display:block">d</div>
I would do this instead:
<div class='a'>a</div>
<div class='b'>b</div>
<div class='c'>c</div>
<div class='d'>d</div>
<input type='button' id='aT' value='Toggle A' />
<input type='button' id='bT' value='Toggle B' />
<input type='button' id='cT' value='Toggle C' />
<input type='button' id='dT' value='Toggle D' />
Put external JavaScript tag in <head> for caching:
var pre = onload;
onload = function(){
if(pre)pre();
var doc = document, bod = doc.body;
function E(e){
return doc.getElementById(e);
}
function C(n){
if(doc.getElementsByClassName){
return doc.getElementsByClassName(n);
}
var t = doc.getElementsByTagName('*'), a = [];
for(var i=0,l=t.length; i<l; i++){
if(t[i].className.match(new RegExp('\\b'+n+'\\b'))){
a.push(t[i]);
}
}
return a;
}
function getStyleProp(elem, prop){
return getComputedStyle(elem).getPropertyValue(prop) || elem.currentStyle[prop];
}
function toggle(elem){
elem.style.display = getStyleProp(elem, 'display').match(/^block$/i) ? 'none' : 'block';
return elem;
}
var btns = ['a', 'b', 'c', 'd'];
for(var i=0,l=btns.length; i<l; i++){
(function(i){
var b = btns[i], c = C(b);
E(b+'T').onclick = function(){
for(var n=0,q=c.length; n<q; n++){
toggle(c[n]);
}
}
})(i);
}
}
Add display: block; to the CSS definition for the DIV.
your var divs = document.getElementsByClassName(div); will only return one element because there is only one element with that class.
<div id="blocks'>
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
</div>
function toggle(div) {
var divs = document.getElementById('blocks');
var ele = blocks.getElementsByTagName("div');
var sty = "";
for(var i = 0; i < ele.length; i++) {
sty = ( ele[i].className.indexOf( div ) ) ? 'block' : 'none';
ele[i].style.display = sty;
}
}
}

Categories

Resources