Having difficuly using a switch statement with classess and for loops - javascript

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);
}
}

Related

Not able to append a paragraph to the image element

I made this favImages array and added some image objects to it. Then I am trying to append a paragraph element(removeButton) to each of them which will be triggered by clicking the images.
var favImages = new Object();
for (var i = 0; i < 5; i++) {
favImages[i] = document.getElementById("fav" + (i + 1));
}
var removeButton = document.createElement("p");
removeButton.id = "removebutton";
removeButton.innerHTML = "Remove Image";
for (var i = 0; i < 5; i++) {
var newImage = document.getElementById(favImages[i].id);
newImage.addEventListener("click", function() {
newImage.appendChild(removeButton)
}, false);
}
Don't use a loop. Use an event listener on the container and test what was clicked using event.target. You cannot add a child to an image
You COULD use a div, put the image as a background and the span to click as content
Anyway here are some examples
document.getElementById("container").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("remove")) tgt.closest("div").remove()
})
#container div {
width: 200px
}
.remove {
float: right
}
<div id="container">
<div>
<span class="remove">X</span>
<img src="https://via.placeholder.com/150/0000FF/000888?text=image1" />
</div>
<div>
<span class="remove">X</span>
<img src="https://via.placeholder.com/150/FF00FF/000888?text=image2" />
</div>
<div>
<span class="remove">X</span>
<img src="https://via.placeholder.com/150/FF0000/000888?text=image3" />
</div>
</div>
From an array:
const images = [
"https://via.placeholder.com/150/0000FF/000888?text=image1",
"https://via.placeholder.com/150/FF00FF/000888?text=image2",
"https://via.placeholder.com/150/FF0000/000888?text=image3"
];
const container = document.getElementById("container");
container.innerHTML = images.map(img => `<div><span class="remove">X</span>
<img src="${img}" /></div>`).join("");
container.addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("remove")) tgt.closest("div").remove()
})
#container div {
width: 200px
}
.remove {
float: right
}
<div id="container">
</div>

onClick event calling function, but not firing

Okay, so I'm getting a weird problem with my onClick elements.
I'm using PHP to echo some code, and here it is:
<div class = \"dropdown\">
<i id = \"elipses_$id\" onClick = \"dropDown_$id()\" style = \"color:#777\" class=\"fas fa-ellipsis-v\"></i>
<div id = \"dropdown_$id\" class = \"dropdown-content\">
[html code here isn't relevant]
</div>
</div>
When I open inspect element, and I click the button, it outputs the function name:
And when I type the function name into the console, the dropdown opens like it should. So why doesn't it do it when I click?
Not sure if it is needed, but here is the script I am using to open/close the dropdown.
function dropDown_$id() {
document.getElementById(\"dropdown_$id\").classList.toggle(\"show\");
}
window.onclick = function(event) {
console.log(event.target);
if (!event.target.matches('#dropdown_$id') && !event.target.matches('#elipses_$id')) {
var dropdown = document.getElementById(\"#dropdowm_$id\");
var c;
if(dropdown != null){
for (c = 0; c < dropdown.length; c++) {
var openDropdowns = dropdown[c];
if (openDropdowns.classList.contains('show')) {
openDropdowns.classList.remove('show');
}
}
}
}
}
EDIT: This is the raw HTML of the dropdown that is spat out after PHP is run:
<div id="dropdown_26" class="dropdown-content">
<div id="names" style="border-bottom: thin solid #BDBDBD;">
<h2 class="dropdown-contenth2">Francois van Kempen</h2>
<p style="color:grey;margin-top:-20px; margin-left: 16px;">#Bork_Bork</p>
</div>
div id="settings" style="border-bottom: thin solid #BDBDBD;">
<a id="a1" class="dropdown-contenta" href="settings.php">Accout Settings</a>
<form id="dark_mode_form" action="nightmode.php" method="POST" style="padding: 10px; display:flex;justify-content:flex-start;align-content:center">
<label style="" class="switch">
<input onchange="this.form.submit()" type="checkbox" name="darkmode" value="checked">
<span class="slider round"></span>
</label>
<p class="dropdown-contentp" style="margin:0;padding:0; margin-left:5px;margin-top:5px;">Night mode</p>
</form>
</div>
<a id="a2" class="dropdown-contenta" href="logout.php">Log out #Bork_Bork</a>
<a id="a3" class="dropdown-contenta" href="reset-password.php">Reset password #Bork_Bork</a>
</div>
EDIT 2: Added the raw script:
<script id="dropdown-settings" type="text/javascript">
function dropDown() {
document.getElementById("dropdown").classList.toggle("show");
}
function dropDown_26() {
document.getElementById("dropdown_26").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
console.log(event.target);
if (!event.target.closest('#dropdown') && !event.target.closest('#navPFP')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
if (!event.target.matches('#dropdown_26') && !event.target.matches('#elipses_26')) {
var dropdown = document.getElementById("#dropdowm_26");
var c;
if(dropdown != null){
for (c = 0; c < dropdown.length; c++) {
var openDropdowns = dropdown[c];
if (openDropdowns.classList.contains('show')) {
openDropdowns.classList.remove('show');
}
}
}
}
}
</script>

Find duplicates by one of multiple classes

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/

How can i make an image set a class to display:none and then set a specific id to display:inline

I'm trying to create a function that hides a class of divs then shows one of those divs by it's id. Here is what I have but I'm not sure if this is the right way to do it. If there is a better way I'm open to it, or if someone can identify an error in this code. What I would like is for the page to load with none of the bio classes visible, then when an image is clicked the bio with the corresponding id appears in its place. Searching only gave me this answer which did not help me. The code below has the bio class divs invisible when the page loads, the image can be clicked but the div does not appear on click. Hopefully this all makes sense.
.bio {
display: none;
}
#id1 {
display: none;
}
#id2 {
display: none;
}
<script language="JavaScript">
function setVisibility(name, id) {
document.getElementByClassName(name).style.display = "none";
document.getElementById(id).style.display = "inline";
}
</script>
<input type="image" src="name1_staff.jpg" onclick="setVisibility('bio', 'id1');" ;>
<input type="image" src="name2_staff.jpg" onclick="setVisibility('bio', 'id2');" ;>
<div class="bio" id="id1">
<h3>text</h3>
<p>more</p>
</div>
<div class="bio" id="id2">
<h3>text</h3>
<p>more</p>
It's wrong way I think. Let's do so:
function removeHidden(className)
{
var classes = className.split(' ');
var newClasses = [];
while (classes.length > 0) {
var name = classes.shift();
if (name != 'hidden' && newClasses.indexOf(name) < 0) {
newClasses.push(name);
}
}
return newClasses.join(' ');
}
function addHidden(className)
{
return removeHidden(className) + ' hidden';
}
function setVisibility(name, id)
{
var x = document.getElementsByClassName(name);
var i;
for (i = 0; i < x.length; i++) {
if (x[i].id == id) {
x[i].className = removeHidden(x[i].className);
} else {
x[i].className = addHidden(x[i].className);
}
}
}
setVisibility('bio', 'id1');
.bio {
/* don't put here display: none */
/* you can delete it if you have no other styles */
}
.hidden {
display: none;
}
<input type="image" src="http://www.hanselman.com/blog/content/binary/WindowsLiveWriter/Hans.NETMVCJeffAtwoodandhistechnicalteam_1349C/stackoverflow-logo-250_3.png" onclick="setVisibility('bio', 'id1');" ;>
<input type="image" src="http://www.hanselman.com/blog/content/binary/WindowsLiveWriter/Hans.NETMVCJeffAtwoodandhistechnicalteam_1349C/stackoverflow-logo-250_3.png" onclick="setVisibility('bio', 'id2');" ;>
<div class="bio" id="id1">
<h3>FIRST DESCRIPTION</h3>
<p>description description description description description</p>
</div>
<div class="bio" id="id2">
<h3>SECOND DESCRIPTION</h3>
<p>description description description description description</p>
</div>
Try this
<script type="text/javascript">
function setVisibility(name, id) {
var x = document.getElementsByClassName(name);
var i;
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
document.getElementById(id).style.display = "inline";
}
</script>
<input type="image" src="name1_staff.jpg" onclick="setVisibility('bio', 'id1');">
<input type="image" src="name2_staff.jpg" onclick="setVisibility('bio', 'id2');">
<div class="bio" id="id1">
<h3>text</h3>
<p>more</p>
</div>
<div class="bio" id="id2">
<h3>text</h3>
<p>more</p>
</div>
Try using the visibility property. In this case, you won't have to deal with your .bio container. You can simply focus on showing and hiding your content. See here.
Keep in mind: With your solution you're setting your containers are always visible. You may also attach a visible property to your container to not get a blank space (if you trigger your 2nd button first).

JQuery Remove not removing specified div

I have a small page on which you can add squares of different colors to a div with a button. After adding them, you can remove them by double clicking any of the squares created.
My code works well, when adding elements. However when I want to remove a square, I just get to remove one and after that I can´t make the element disappear on HTML even though the counter does decrease. I´m a doing something wrong with the remove() function? Right now I´m just focusing on the blue (Azul) color.
Here´s my code
https://jsfiddle.net/kdwyw0mc/
var azules = 0;
var rojos = 0;
var amarillos = 0;
var verdes = 0;
function eliminar(cuadro){
azules = parseInt(jQuery('#num-azules').text());
verdes = parseInt(jQuery('#num-verdes').text());
rojos = parseInt(jQuery('#num-rojos').text());
amarillos = parseInt(jQuery('#num-amarillos').text());
if(cuadro[0].classList[1]=='blue'){
azules = azules -1;
}
else if(cuadro[0].classList[1]=='red'){
rojos--;
}
else if(cuadro[0].classList[1]=='yellos'){
amarillos--;
}
else if(cuadro[0].classList[1]=='green'){
verdes--;
}
cuadro.remove();
jQuery('#num-azules').text(azules);
jQuery('#num-verdes').text(verdes);
jQuery('#num-rojos').text(rojos);
jQuery('#num-amarillos').text(amarillos);
}
function agregar(){
jQuery('span#num-azules').val(azules);
var numCuadros = jQuery("#numero").val();
var color = $('#color option:selected').text();
for( i = 0; i< numCuadros; i++){
if(color=='Azul'){
/*jQuery(".square").append(function(){
return jQuery('<div class="square blue"> </div>').ondblclick(eliminar);
})*/
var newSquare = jQuery('<div class="square blue"> </div>')
var a = jQuery(".squares").append(newSquare);
newSquare.dblclick(function(){eliminar(newSquare);})
azules += 1;
}
else if(color=='Rojo'){
jQuery(".squares").append('<div class="square red"> </div>')
rojos+= 1;
}
else if(color=='Amarillo'){
jQuery(".squares").append('<div class="square yellow"> </div>')
amarillos+= 1;
}
else if(color=='Verde'){
jQuery(".squares").append('<div class="square green"> </div>')
verdes+= 1;
}
}
jQuery('#num-azules').text(azules);
jQuery('#num-verdes').text(verdes);
jQuery('#num-rojos').text(rojos);
jQuery('#num-amarillos').text(amarillos);
}
/*
* jQuery("#agregar").click(function(){
agregar();
});
VS
jQuery("#agregar").click(agregar());
* */
jQuery('#num-azules').text(azules);
jQuery('#num-verdes').text(verdes);
jQuery('#num-rojos').text(rojos);
jQuery('#num-amarillos').text(amarillos);
jQuery("#agregar").click(function(){
agregar();
});
HTML:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="styles/reset.css"/>
<link rel="stylesheet" href="styles/main.css"/>
</head>
<body>
<div class="main-content">
<div class="toolbar">
Numero Cuadrados: <input id="numero"type="text"/>
<select id="color" name="color">
<option value="azul">Azul</option>
<option value="rojo">Rojo</option>
<option value="amarillo">Amarillo</option>
<option value="verde">Verde</option>
</select>
<button id="agregar">Agregar</button>
</div>
<div class="squares">
</div>
<div class="numeros">
<p>Azules: <span id="num-azules">0</span> </p>
<p>Rojos: <span id="num-rojos">0</span></p>
<p>Verde: <span id="num-verdes">0</span></p>
<p>Amarillo: <span id="num-amarillos">0</span></p>
</div>
</div>
<script src="scripts/jquery-1.11.3.min.js"></script>
<script src="scripts/main.js"></script>
</body>
</html>
This is an inefficient way of registering / listening to events, it is better to delegate the event handling to a wrapper (parent) container:
$("#container").on("dblclick", ".square", function(){
$(this).remove();
)};
on works for dynamically created elements; since the container was already in the DOM, it can continue listening to events coming from any other, newly created child element that has class .square.
http://api.jquery.com/on/
Edit:
One way of solving the counter problem would be to do something like this:
var StateObj = function(){
this.counter = 0;
this.arrSquares = [];
this.increaseCounter = function(){
this.counter += 1;
},
this.decreaseCounter = function(){
this.counter -= 1;
},
this.addSquare = function(id, color){
this.arrSquares.push({id: id, color: color});
},
this.getSquareById = function(id){
return square = $.grep(this.arrSquares, function(){ return id == id; });
}
}
var stateObj = newStateObj();
$("#container").on("dblclick", ".square", function(e){
$(this).remove();
var id = $(e.currentTarget).attr("id");
stateObj.increaseCounter();
console.log(stateObj.counter);
)};

Categories

Resources