I have several divs one after anothr.. actually 10 of these.
I want a jquery solution such that it goes through the divs and whenever it finds any images that are similar , the whole div is not displayed or aka display:none is inserted in the css class. Similar divs can only stay adjacent to each other only according to the logic I have in my code. as in below
<div class="tops">
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/AxlRose.png"> </p>
<p class="smallText">Axl<br>Roses</p>
</div>
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/AxlRose.png"> </p>
<p class="smallText">Axl<br>Roses</p>
</div>
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/Eminem.png"> </p>
<p class="smallText">Eminem</p>
</div>
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/Eminem.png"> </p>
<p class="smallText">Eminem</p>
</div>
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/artistA.png"> </p>
<p class="smallText">artistA</p>
</div>
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/artistA.png"> </p>
<p class="smallText">artistB</p>
</div>
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/artistA.png"> </p>
<p class="smallText">artistA</p>
</div>
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/artistG.png"> </p>
<p class="smallText">artistG</p>
</div>
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/artistH.png"> </p>
<p class="smallText">artistH</p>
</div>
<div class="col-xs-2 topleaderBoardSB">
<p class="smallImages"><img class="img-circle img-responsive" src="32399/images/pics/artistI.png"> </p>
<p class="smallText">artistI</p>
</div>
</div>
Also, no more than 5 div will be displayed. ANd if there are less than 5 divs after putting the display:none, then 5 divs will be displayed anyway aka last few display:none will not be there so that 5 divs are always displayed.
A jquery solution will be nice.
Check this out:
var images = [],
img,
count = 0;
$("img").filter(function(){
img = $(this).attr("src");
if($.inArray(img, images) < 0 && count < 5){
images.push(img);
count++;
return false;
}
return true;
}).closest($('div')).hide();
The way this works is that it basically grabs all the img tags on the page, then filters them based on whether or not their src attribute is unique. If it isn't, then it finds the parent div and hides it.
This is a little less-than-optimal because of $.inArray, so you could tweak that if it matters to you.
JSFiddle
EDIT: Now updated to limit to 5 results only.
A plain JS solution is:
function upTo(el, tagName) {
el = el && el.parentNode;
tagName = tagName.toLowerCase();
for ( ;el; el = el.parentNode) {
if (el.tagName && el.tagName.toLowerCase() == tagName) {
return el;
}
}
return null;
}
function hideSimilarImages() {
var image, images = document.images;
var sources = {};
var div;
for (var i=0, iLen=images.length; i<iLen; i++) {
image = images[i]
if (image.src in sources) {
div = upTo(image, 'div');
if (div && div.style) div.style.display = 'none';
} else {
sources[image.src] = '';
}
}
}
Edit
If you want to limit the number of images display, pass a value to the function and apply it when determining whether to hide the div or not:
function hideSimilarImages(limit) {
var image, images = document.images;
var sources = {};
var count = 0;
var div;
limit = typeof limit == 'undefined'? Infinity : --limit;
for (var i=0, iLen=images.length; i<iLen; i++) {
image = images[i]
if (image.src in sources || count > limit) {
div = upTo(image, 'div');
if (div && div.style) div.style.display = 'none';
} else {
sources[image.src] = '';
++count;
}
}
}
If the function isn't passed a value, it will show all unique images. Otherwise it will only show images up to the limit. If 0 is passed, it won't show any.
Related
I have 32 items in my array, all of them have these properties: id, word, image. User has to guess what's in all the images and write their guess in inputs (so 32 inputs in total). I need to check if the input equals my arrays property "word" and then when clicked a button (type submit, all my pic's and inputs are in a form) display some text for example "Oops! Guess again" if wrong and "Yay! You got it correctly" if right. The text should appear below every input. I displayed all the pictures and inputs with a forEach, and i'm using bulma framework for this page:
const wordBox = info.forEach((words) => {
mainColumns.innerHTML += `
<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${words.image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" id="text" type="text" placeholder="Įvesk žodį">
</div>
</div>
<div class="content">
Content
</div>
</div>
</div>
</div>`;
});
Any ideas?
This is how it should look like (the result should appear in content place)
Something like this
I use change instead of a button click
const info = [
{word:"flower",image:"flower.gif"},
{word:"boat",image:"boat.gif"}
];
const mainColumns = document.getElementById("mainColumns");
mainColumns.innerHTML = info.map(({image,word}) =>
`<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" data-word="${word}" type="text" placeholder="Įvesk žodį">
<span class="correct hide">Yay</span>
<span class="wrong hide">NOO</span>
</div>
</div>
<div class="content">
Content
</div>
</div>
</div>
</div>`).join("");
mainColumns.addEventListener("change",function(e) {
const correct = [...mainColumns.querySelectorAll("[data-word]")].map(input => {
if (input.value) {
const correct = input.value === input.dataset.word;
parent = input.closest("div");
parent.querySelector(".correct").classList.toggle("hide",!correct)
parent.querySelector(".wrong").classList.toggle("hide",correct);
return correct ? 1 : 0;
}
else return 0;
}).reduce((a,b)=>a+b);
document.getElementById("correct").innerText = correct;
})
#mainColumns { display:flex; }
.hide { display: none; }
<div id="mainColumns"></div>
Correct: <span id="correct"></span>
What you can do is to filter the word array with word from the input value. Then check if the length is equal zero, No match, if the length is greater than one, then there is a match.
const status = wordBox.filter(item => item.word === inputWord)
I'd move towards keeping the objects and the HTML separate, binding the HTML to the object and vice versa. This means including a couple more properties to your array elements.
let info = [{
image: 'flower.png',
word: 'flower',
content: '',
guess: ''
}];
function bindWords() {
info.forEach((words) => {
mainColumns.innerHTML = `
<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${words.image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" data-word="${words.word}" type="text" placeholder="Įvesk žodį" value="${words.guess}">
</div>
</div>
<div class="content">
${words.content}
</div>
</div>
</div>
</div>`;
});
}
bindWords();
check.addEventListener('click', () => {
info = Array.from(document.querySelectorAll('.card')).map(el => ({
image: el.querySelector('img').src,
word: el.querySelector('.input').dataset.word,
guess: el.querySelector('.input').value,
content: el.querySelector('.input').value === el.querySelector('.input').dataset.word ?
'Correct' : 'Incorrect'
}));
bindWords();
});
<div id="mainColumns"></div>
<button id="check">Check Answers</button>
I am trying to make a slideshow in a webpage.
I created the next and previous button for changing images in different way. The next button is working but the previous button in not working. The display property of the images is set to none by default.
var nextbutton = document.querySelector(".next");
var prevbutton = document.querySelector(".prev");
var slide = document.querySelectorAll('.slideshow');
var slideindex = 1 ;
var show = function(n){
var i;
if (n > slide.length) { slideindex = 1};
if (n < 1) {slideindex = slide.length};
for (i = 0; i < slide.length; i++) {
slide[i].style.display = "none";
};
slide[slideindex-1].style.display = "block";
};
var cl = function(p) {
show(slideindex += p);
};
/* next button is working */
nextbutton.addEventListener("click", function(){
show(slideindex += 1 );
} );
/* previous button is not working */
prevbutton.addEventListener("click" , cl(-1));
.slideshow {
width:100%;
height: 500px !important ;
border-radius: 7px;
display: none;
}
<section class="content-head">
<div class="container">
<div class="img">
<img class="img-fluid my-5 mx-auto slideshow" id="" src="https://www.w3schools.com/howto/img_woods_wide.jpg">
</div>
<div class="img">
<img class="img-fluid my-5 mx-auto slideshow" id="" src="https://www.w3schools.com/howto/img_5terre.jpg">
</div>
<div class="img">
<img class="img-fluid my-5 mx-auto slideshow" id="" src="https://www.w3schools.com/howto/img_mountains.jpg">
</div>
<div class="img">
<img class="img-fluid my-5 mx-auto slideshow" id="" src="https://www.w3schools.com/howto/img_lights.jpg">
</div>
<div class="img">
<img class="img-fluid my-5 mx-auto slideshow" id="" src="https://www.w3schools.com/howto/img_nature.jpg">
</div>
<div class="img">
<img class="img-fluid my-5 mx-auto slideshow" id="" src="https://www.w3schools.com/howto/img_snow.jpg">
</div>
</div>
<div class="button container">
<a class="prev">❮</a>
<a class="next">❯</a>
</div>
</section>
prevbutton.addEventListener("click" , cl(-1));
This calls the function immediately, when you bind the event, not when the event fires. You avoid this mistake when binding the next button event.
Change to:
prevbutton.addEventListener("click", evt => cl(-1));
or
prevbutton.addEventListener("click", function(evt) { cl(-1); });
You could also do:
prevbutton.addEventListener("click", cl.bind(null, -1));
Why didn't your one work?
prevbutton.addEventListener("click", cl(-1));
is equivalent to:
let theReturnValue = cl(-1);
prevbutton.addEventListener("click", theReturnValue);
JavaScript calls cl(-1) and passes the return value to addEventListener
Why does this solution work
The solutuon used Function.prototype.bind which you can look up but it is equivalent to:
prevbutton.addEventListener("click", function(...args) {
cl.call(null, -1, ...args);
});
Bind in detail
Arguments: fn.bind(thisArg[, ...args])
fn
The function.
thisArg
What the value of this will be in the function fn (or cl in this case)
...args
Optional. Predefined arguments for the function. All other arguments given in invocation will be put after these arguments.
Im trying to hide and show a few cards in bootstrap, but I can't figure it out.
All cards have the class card (of course) and im trying to hide all those cards when a button is clicked. Here is what I have now:
function myFunction() {
jQuery(document).ready(function($) {
$(".card").hide();
});
var game = document.getElementById("game").value;
var resolution = document.getElementById("resolution").value;
var graphic = document.getElementById("graphic").value;
if (game == "Black" && graphic == "high" && resolution == "1080") {
alert("Hello " + game + "! You will now be redirected to www.w3Schools.com");
} else if (book == "Red") {
} else if (book == "Green") {
} else {
}
}
The call for the function is correct cause the alert does work properly.
For some reason the
jQuery(document).ready(function($) {
$(".card").hide();
});
part does work when outside the js function (when it's not connected to the button).
No idea if it helps but here is also a snipped of my bootstrap doc:
<button type="submit" class="btn btn-primary" id="btn" onclick="myFunction()">Submit</button>
</form>
</div>
<!-- Results -->
<div class="card" id="p2" style="width:200px; margin:30px">
<img class="card-img-top" src="https://image" alt="Card image" style="width:100%">
<div class="card-body">
<h5 class="card-title">Processor</h5>
<p>Newegg</p>
<p>Newegg</p>
<p>Newegg</p>
</div>
</div>
<div class="card" id="p3" style="width:200px; margin:30px">
<img class="card-img-top" src="https://image" alt="Card image" style="width:100%">
<div class="card-body">
<h5 class="card-title">Graphic card</h5>
<p>Newegg</p>
<p>Newegg</p>
<p>Newegg</p>
</div>
</div>
Here the things I've tried already:
The toggle How to hide and show bootstrap 4 cards by hovering over navigation menu through css?
Standard js document.getElementById(".card").style.display = "none";
I've looked at the react stuff, but I don't understand that.
I think what you have to do is this if you want to make a show and hide toggle of all the elements that have the card class in your DOM.
var myFunction = function() {
var divsToHide = document.getElementsByClassName("card");
if(divsToHide.length>0){
for(var i = 0; i < divsToHide.length; i++){
if( divsToHide[i].style.display== "none"){
divsToHide[i].style.display = "block";
}else{
divsToHide[i].style.display = "none"; // depending on what you're doing
}
}} }
I hope it helps you
I have a website with multiple image galleries on different parts of the website. When you click on the image of specific gallery it changes to next one of that gallery and so on.
What I am trying to achieve is to reset the previous gallery to image 1 when you start clicking on a different gallery. So when the user goes back to the previous gallery, it would start from the first image.
Code used for the galleries:
let projectIndexes = {
project1: 1,
project2: 1,
}
showDivs("project1", projectIndexes.project1);
showDivs("project2", projectIndexes.project2);
function plusDivs(project, n) {
showDivs(project, projectIndexes[project] += n);
}
function showDivs(project, index) {
let i;
let x = document.getElementById(project).getElementsByClassName("slidess");
if (index > x.length) { index = 1 }
if (index < 1) { index = x.length }
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[index - 1].style.display = "block";
projectIndexes[project] = index;
let elements = document.getElementById(project).querySelector('.imgslide').children;
let imgNames = [];
for (let i = 0; i < elements.length; i++) {
imgNames.push(elements[i].children[0].children[0].alt);
}
}
<div class="slide">
<div class="slide-content">
<div class="nextt" onclick="plusDivs('project1', 1)"></div>
</div>
<div class="image-container container prjct">
<div class="projects" id="project1">
<div class="imgslide noselect">
<div class="content-container slidess">
<div class="style-3 style-3-left">
<img class="imageName" alt="Img" src="">
</div>
<div class="style-3 style-3-middle">
<img class="imageName" alt="Img" src="">
</div>
<div class="style-3 style-3-right">
<img class="imageName" alt="Img" src="">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="slide">
<div class="slide-content">
<div class="nextt" onclick="plusDivs('project2', 1)"></div>
</div>
<div class="image-container container prjct">
<div class="projects" id="project2">
<div class="imgslide noselect">
<div class="content-container slidess">
<div class="style-3 style-3-left">
<img class="imageName" alt="Img" src="">
</div>
<div class="style-3 style-3-middle">
<img class="imageName" alt="Img" src="">
</div>
<div class="style-3 style-3-right">
<img class="imageName" alt="Img" src="">
</div>
</div>
<!-- <div class="img-name"></div> -->
</div>
</div>
</div>
</div>
I know a way to force show the first element, but it turns out it does that for all projects.
What I was not able to find is a way to recognise when clicking on a new project, that the previous and only previous project needs to reset to first image.
I have been struggling with this for a while now and cannot make it work, so any help would be highly appreciated. And if something is not clear, let me know and I will clarify things.
If I'm following you correctly, the following should do it.
function resetPriorGalleries(currentProject) {
var projectDivs = document.getElementsByClassName("projects");
for (let i = 0; i < projectDivs.length; i++) {
if (projectDivs[i].id === currentProject)
return;
showDivs(projectDivs[1].id, 1);
}
}
The best place to call it would probably be in the onclicks.
onclick="plusDivs('project2', 1); resetPriorGalleries('project2');"
I have the following html:
<div id="prog" class="downloads clearfix">
<div class="item">
<div class="image_container">
<img src="/img/downloads/company.png" width="168" height="238" alt="">
</div>
<div class="title">
pricelist: <label id="pr1"></label>
</div>
<div class="type">
pdf document
</div>
<div class="link">
<a id="pdfdocument" class="button" target="_blank" href="#">start Download </a>
</div>
</div>
</div>
I want build HTML which is inside the <div id="prog"> with Javascript:
<div id="prog" class="downloads clearfix"></div>
I'm trying to use this Javascript, but without success:
var tmpDocument, tmpAnchorTagPdf, tmpAnchorTagXls, parentContainer, i;
parentContainer = document.getElementById('prog');
for (i = 0; i < documents.length; i++) {
tmpDocument = documents[i];
tmpAnchorTagPdf = document.createElement('a id="pdfdocument" ');
tmpAnchorTagPdf.href = '/role?element=' + contentElement.id + '&handle=' + ope.handle;
tmpAnchorTagPdf.innerHTML = 'start Download';
tmpAnchorTagXls = document.createElement('a');
tmpAnchorTagXls.href = '/role?element=' + contentElement.id + '&handle=' + ope.handle;
tmpAnchorTagXls.innerHTML = 'start Download';
parentContainer.appendChild(tmpAnchorTagPdf);
parentContainer.appendChild(tmpAnchorTagXls);
}
If this is a section of code that you will be using more than once, you could take the following approach.
Here is the original div without the code you want to create:
<div id="prog" class="downloads clearfix">
</div>
Create a template in a hidden div like:
<div id="itemtemplate" style="display: none;">
<div class="item">
<div class="image_container">
<img src="/img/downloads/company.png" width="168" height="238" alt="">
</div>
<div class="title">
pricelist: <label></label>
</div>
<div class="type">
pdf document
</div>
<div class="link">
<a class="button" target="_blank" href="#">start Download </a>
</div>
</div>
</div>
Then duplicate it with jquery (OP originally had a jquery tag; see below for JS), update some HTML in the duplicated div, then add it to the document
function addItem() {
var item = $("#itemtemplate div.item").clone();
//then you can search inside the item
//let's set the id of the "a" back to what it was in your example
item.find("div.link a").attr("id", "pdfdocument");
//...the id of the label
item.find("div.title label").attr("id", "pr1");
//then add the objects to the #prog div
$("#prog").append(item);
}
update
Here is the same addItem() function for this example using pure Javascript:
function JSaddItem() {
//get the template
var template = document.getElementById("itemtemplate");
//get the starting item
var tempitem = template.firstChild;
while(tempitem != null && tempitem.nodeName != "DIV") {
tempitem = tempitem.nextSibling;
}
if (tempitem == null) return;
//clone the item
var item = tempitem.cloneNode(true);
//update the id of the link
var a = item.querySelector(".link > a");
a.id = "pdfdocument";
//update the id of the label
var l = item.querySelector(".title > label");
l.id = "pr1";
//get the prog div
var prog = document.getElementById("prog");
//append the new div
prog.appendChild(item);
}
I put together a JSFiddle with both approaches here.