How to display Image caption with Image in slider - javascript

I want to display image caption under each images in image slider.
But right now my problem is all the image captions are displaying for each image like this
View :
<div class="grid-11 left">
#if (Model.Photos.Count > 0)
{
<div style="padding:10px">
<div class="slide-content" style="max-width:800px">
#foreach (var photos in Model.Photos)
{
<div>
<img class="mySlides" src="#Url.Content(photos.photo_url)"/>
</div>
<span>#photos.photo_caption</span>
}
<div class="w3-center">
<div class="w3-section">
<button class="w3-button w3-light-grey" onclick="plusDivs(-1)">❮ </button>
<button class="w3-button w3-light-grey" onclick="plusDivs(1)"> ❯</button>
</div>
</div>
</div>
</div>
}
</div>
Script :
var slideIndex = 1;
showDivs(slideIndex);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function currentDiv(n) {
showDivs(slideIndex = n);
}
function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
if (n > x.length) {
slideIndex = 1
}
if (n < 1) {
slideIndex = x.length
}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex - 1].style.display = "block";
}
How do is display caption for each image by passing image_id?

The problem is you're targeting the image only for display block/none via class="mySlides". You need to wrap the image and caption in some sort of container and target that instead.
#foreach (var photos in Model.Photos)
{
<div class="mySlides">
<div>
<img src="#Url.Content(photos.photo_url)"/>
</div>
<span>#photos.photo_caption</span>
</div>
}

Related

How to run just one Function inside UseEffect?

Does anybody know how to solve this code. I have a carousel, and there is previous and next icon. When clicked, I have to run a specific function inside useEffect().
I want to run the plusSlides() function, which simply calculates the new main carousel picture.
The code is:
function Carousel({ children }) {
useEffect(() => {
var slideIndex = 1;
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("mySlides");
if (n > slides.length) {slideIndex = 1}
if (n < 1) {slideIndex = slides.length}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slides[slideIndex-1].style.display = "block";
}
});
return (
<CarouselStyled visible={visible}>
<div className="slideshow-container">
<div className="container">
<Link href={`/${router.locale == "bs" ? "" : "en"}`}>
<a className="mylogo">
<img src="/logo.svg" alt="Doxat" />
</a>
</Link>
</div>
<div className="mySlides fade">
<img src="/images/doxat-2.jpg" />
</div>
<div className="mySlides fade">
<img src="/images/doxat-1.jpg" />
</div>
<div className="mySlides fade">
<img src="/images/doxat-3.jpg" />
</div>
<a className="prev" onClick={() => plusSlides(-1)}>
/* When clicked here, the plusSlides function has to be run*/
<MdChevronLeft />
</a>
<a className="next">
<MdChevronRight />
</a>
</div>
</CarouselStyled>
);
}
your function need definition on useEffect() outside,then because you use function component,just call plusSlides can work
function Carousel({ children }) {
const plusSlides = ()=>{
// do somthing
}
useEffect(()=>{
},[])
return(
<div>
<a className="prev" onClick={() => plusSlides(-1)}></a>
</div>
)
}

image lightbox with reactjs using jsx

i am trying to use this image lightbox in reactjs https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_slideshow_gallery . But it seems to be not working for me in reactjs.I am having problem with onclick function declarations.Here is my code so far:
render() {
var slideIndex = 1;
showSlides(slideIndex);
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("demo");
var captionText = document.getElementById("caption");
if (n > slides.length) {slideIndex = 1}
if (n < 1) {slideIndex = slides.length}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
captionText.innerHTML = dots[slideIndex-1].alt;
}
return (
<div>
<div className="container">
<div className="mySlides">
<div className="numbertext">1 / 6</div>
<img src="img_woods_wide.jpg" style="width:100%"/>
</div>
<div className="mySlides">
<div className="numbertext">2 / 6</div>
<img src="img_5terre_wide.jpg" style="width:100%"/>
</div>
<a className="prev" onClick="plusSlides(-1)">❮</a>
<a className="next" onClick="plusSlides(1)">❯</a>
<div className="caption-container">
<p id="caption"></p>
</div>
<div className="row">
<div className="column">
<img className="demo cursor" src="img_woods.jpg" style="width:100%"
onClick="currentSlide(1)" alt="The Woods"/>
</div>
<div className="column">
<img className="demo cursor" src="img_5terre.jpg" style="width:100%"
onClick="currentSlide(2)" alt="Cinque Terre"/>
</div>
</div>
</div>
</div>
);
}
I have also tried declaring the script into the componentDidMount.But it seems to be not working.How can i fix this?
You should not access DOM in React.
But you should create model of your component in state and map it to view in render() function
UPD:
The code could looks like this
const useSlider = (items) => {
const [pointer, setPointer] = useState(0)
useEffect(() => {
setPointer(0) // reset pointer if items list changes
}, [items])
// Move pointer forvard
const next = () => setPointer((pointer) =>
pointer < items.length - 1 ? pointer + 1 : 0
);
// Move Pointer back
const prev = () => setPointer((pointer) =>
pointer > 0 ? pointer - 1 : items.length - 1
);
// Focused item
const item = useState (() => items[pointer], [items, pointer])
return {
pointer,
next,
prev,
setPointer,
item,
}
}
const Slider = ({ items }) => {
const { next, prev, pointer, setPointer, item } = useSlider(items);
return (
<div>
<div className="container">
<div className="mySlides">
<div className="numbertext">{`${pointer + 1} / ${items.length}`}</div>
<img src={item.src} style="width:100%" />
</div>
<a className="prev" onClick={prev}>❮</a>
<a className="next" onClick={next}>❯</a>
<div className="caption-container">
<p id="caption">{item.caption}</p>
</div>
<div className="row">
{
items.map((item, pointer) => (
<div key={pointer} className="column">
<img
className="demo cursor"
src={item.src}
style="width:100%"
onClick={() => setPointer(pointer)}
alt={item.caption}
/>
</div>
))
}
</div>
</div>
</div>
);
}
const items = [{
src: 'img_woods.jpg',
caption: 'The Woods'
}, {
src: 'img_5terre.jpg',
caption: 'Cinque Terre'
}];
// <Slider items={items}/>

Multiple line image slider with buttons

I am working on a website that should have image sliders with clickable buttons that flip to the next image.
I was able to make a single slider / page, but as I have no experience in coding yet, I ran into difficulties when I was trying make multiple sliders following each other directly. The buttons of a certain slider started to mix up, and target other sliders too, or only the first one, but not the way I wanted..
So I started copying and repeating the same lines of code and applying them to groups of images separately.
I also want some text to flip together with the images, so I grouped the text and images together with the buttons, and finally I ended up having a lot of repetition, and way too long codes. :-)
Right now it works, but I assume that there is a much easier, solution, that would make my code a lot shorter.
Can someone help me with:
Having one good java script, that doesn't mix up the targets, when having multiple sliders?
Having only one "buttons"/slider instead of copying them to all the "containergrid"s groups, but still flipping the text together with the image?
Thanks, and sorry for the long code. :)
<div class="content">
<!---THE FIRST SLIDER--->
<div class="slider_1">
<div class="slides_1">
<div class="containergrid">
<div class="description">
<p class="maindescription">Description</p>
<p class="year">2017</p>
</div>
<div class="imgbutton">
<img class="img_1_1">
<div class="button">
<button class="prev"
onclick="plusDivs1(-1)"></button>
<button class="next"
onclick="plusDivs1(1)"></button>
</div>
</div>
</div>
</div>
<div class="slides_1">
<div class="containergrid">
<div class="description">
<p class="maindescription">Description</p>
<p class="year">2017</p>
</div>
<div class="imgbutton">
<img class="img_1_2">
<div class="button">
<button class="prev"
onclick="plusDivs1(-1)"></button>
<button class="next"
onclick="plusDivs1(1)"></button>
</div>
</div>
</div>
</div>
</div>
<!---THE SECOND SLIDER--->
<div class="slider_2">
<div class="slides_2">
<div class="containergrid">
<div class="description">
<p class="maindescription">Description</p>
<p class="year">2017</p>
</div>
<div class="imgbutton">
<img class="img_2_1">
<div class="button">
<button class="prev"
onclick="plusDivs1(-1)"></button>
<button class="next"
onclick="plusDivs1(1)"></button>
</div>
</div>
</div>
</div>
<div class="slides_2">
<div class="containergrid">
<div class="description">
<p class="maindescription">Description</p>
<p class="year">2017</p>
</div>
<div class="imgbutton">
<img class="img_2_2">
<div class="button">
<button class="prev"
onclick="plusDivs1(-1)"></button>
<button class="next"
onclick="plusDivs1(1)"></button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var slideIndex = 1;
showDivs1(slideIndex);
function plusDivs1(n) {
showDivs1(slideIndex += n);
}
function showDivs1(n) {
var i;
var x = document.getElementsByClassName("slides_1");
if (n > x.length) { slideIndex = 1 }
if (n < 1) { slideIndex = x.length }
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex - 1].style.display = "flex";
}
</script>
<script>
var slideIndex = 1;
showDivs2(slideIndex);
function plusDivs2(n) {
showDivs2(slideIndex += n);
}
function showDivs2(n) {
var i;
var x = document.getElementsByClassName("slides_2");
if (n > x.length) { slideIndex = 1 }
if (n < 1) { slideIndex = x.length }
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex - 1].style.display = "flex";
}
</script>
So you would just have to pass a reference to your slides into the showDivs function, so you can keep the clicks independent of one another. You'd still have to initialize each slider separately.
function plusDivs(slider, n) {
showDivs(slider, slideIndex += n);
}
function showDivs(slider, index) {
var i;
var x = document.getElementsByClassName(slider);
if (index > x.length) {
slideIndex = 1
}
if (index < 1) {
slideIndex = x.length
}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex - 1].style.display = "flex";
}
// Initialize the sliders
var slideIndex = 1;
showDivs('slides_1', slideIndex);
showDivs('slides_2', slideIndex);
In your HTML you just need to pass the reference to the plusDivs function:
onclick="plusDivs('slides_1', 1)"
Here is a fiddle showing a working example

Vanilla JS - slider - Active dots

Please, can you help me assign .active class to slider Dots, which are generated by JS, they are not part of HTML. When slide 1 is active, I need dot 1 to have class .active, but no luck.. all solutions I have foud are for dots hardcoded in HTML.
My HTML:
<div class="w3-content w3-display-container">
<div class="w3-display-container mySlides">
<div class="w3-display-bottomleft w3-large w3-container w3-padding-16 w3-black">
<h3>Slide 1</h3>
<p>1. Lorem Ipsum.</p>
</div>
</div>
<div class="w3-display-container mySlides">
<div class="w3-display-bottomright w3-large w3-container w3-padding-16 w3-black">
<h3>Slide 2</h3>
<p>2.Lorem Ipsum.</p>
</div>
</div>
<div class="w3-display-container mySlides">
<div class="w3-display-topleft w3-large w3-container w3-padding-16 w3-black">
<h3>Slide 3</h3>
<p>3. Lorem Ipsum.</p>
</div>
</div>
<button class="w3-button w3-display-left w3-black" onclick="plusDivs(-1)">❮</button>
<div id="js-slider-dots"></div>
<button class="w3-button w3-display-right w3-black" onclick="plusDivs(1)">❯</button>
</div>
My JS (which switch the slides and generate dots):
var slideIndex = 1;
showDivs(slideIndex);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function goToDiv(n) {
showDivs(slideIndex = n);
}
function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
if (n > x.length) { slideIndex = 1 }
if (n < 1) { slideIndex = x.length }
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex - 1].style.display = "block";
}
function generateDots() {
var i;
var x = document.getElementsByClassName("mySlides");
for (i = 0; i < x.length; i++) {
var dotNumber = i + 1;
var dot = document.createElement('span');
dot.innerHTML =
'<button class="js-dot" onclick="goToDiv(' + dotNumber + ')">' + dotNumber + '</button>';
document.getElementById('js-slider-dots').appendChild(dot);
}
}
generateDots();
It is also all live on JS Bin: https://jsbin.com/ketohatane/edit?html,js,output
You can easily do it by .classList.add() and .remove().
Just select the dots, and activate the dot that belongs to the active slide at showDivs:
function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
//get the list of dots
var y = document.getElementById("js-slider-dots").children;
if (n > x.length) { slideIndex = 1 }
if (n < 1) { slideIndex = x.length }
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
//remove .active from all dots
y[i].classList.remove("active")
}
x[slideIndex - 1].style.display = "block";
//add .active to the selected dot
y[slideIndex - 1].classList.add("active")
}
See this snippet:
var slideIndex = 1;
function plusDivs(n) {
showDivs(slideIndex += n);
}
function goToDiv(n) {
showDivs(slideIndex = n);
}
function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
//get the list of dots
var y = document.getElementById("js-slider-dots").children;
if (n > x.length) { slideIndex = 1 }
if (n < 1) { slideIndex = x.length }
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
//remove .active from all dots
y[i].classList.remove("active")
}
x[slideIndex - 1].style.display = "block";
//add .active to the selected dot
y[slideIndex - 1].classList.add("active")
}
function generateDots() {
var i;
var x = document.getElementsByClassName("mySlides");
for (i = 0; i < x.length; i++) {
var dotNumber = i + 1;
var dot = document.createElement('span');
dot.innerHTML =
'<button class="js-dot" onclick="goToDiv(' + dotNumber + ')">' + dotNumber + '</button>';
document.getElementById('js-slider-dots').appendChild(dot);
}
}
generateDots();
//placed AFTER generateDots()
showDivs(slideIndex);
/* Just for illustration */
.active{outline:solid 1px red;}
<div class="w3-content w3-display-container">
<div class="w3-display-container mySlides">
<div class="w3-display-bottomleft w3-large w3-container w3-padding-16 w3-black">
<h3>Slide 1</h3>
<p>1. Lorem Ipsum.</p>
</div>
</div>
<div class="w3-display-container mySlides">
<div class="w3-display-bottomright w3-large w3-container w3-padding-16 w3-black">
<h3>Slide 2</h3>
<p>2.Lorem Ipsum.</p>
</div>
</div>
<div class="w3-display-container mySlides">
<div class="w3-display-topleft w3-large w3-container w3-padding-16 w3-black">
<h3>Slide 3</h3>
<p>3. Lorem Ipsum.</p>
</div>
</div>
<button class="w3-button w3-display-left w3-black" onclick="plusDivs(-1)">❮</button>
<div id="js-slider-dots"></div>
<button class="w3-button w3-display-right w3-black" onclick="plusDivs(1)">❯</button>
</div>
If you access the DOM from your goToDiv function, you can be sure that you are accessing the DOM after it has been updated with your class="js-dot" elements.
Something like this will give you the functionality you want.
function goToDiv(n) {
showDivs(slideIndex = n);
var dots = document.getElementsByClassName('js-dot');
for(var i = 0; i < dots.length; i++) {
if (i == n - 1) {
dots[i].classList.add('active');
} else {
dots[i].classList.remove('active');
}
}
}
Here it is in action:
https://jsbin.com/tekukebeye/1/edit?html,js,output

how to code for multiple modals where some of them are carousels with different number of slides

I have a page with several buttons, when each button is clicked a different modal pops up. Some of the modals are carousels, the code I have works but for only one of the carousels, when I have more than one I get extra empty slides on all the carousels. So I'm guessing my code is counting all the slides from all the carousels together. Im trying to have write something where it says if this modal is clicked then get the slides from the clicked modal only but Im struggling with that.
These are the bits of relevant code:
<script>
//Carousel
var slideIndex = 1;
showDivs(slideIndex);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function currentDiv(n) {
showDivs(slideIndex = n);
}
function showDivs(n) {
var i;
var x = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("demo");
if (n > x.length) {slideIndex = 1}
if (n < 1) {slideIndex = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
/*dots[i].className = dots[i].className.replace(" w3-white", "");*/
}
x[slideIndex-1].style.display = "block";
/*dots[slideIndex-1].className += " w3-white";*/
}
</script>
<script>
//Display corresponding modal of letter that is clicked
$(".button").on("click", function() {
var modal = $(this).data("modal");
$(modal).show();
document.body.classList.add("modal-open");
});
//Close modal when "x" is clicked or when area outside modal is clicked
$(".modal").on("click", function(e) {
var className = e.target.className;
if(className === "modal" || className === "close"){
$(this).closest(".modal").hide();
document.body.classList.remove("modal-open");
}
});
</script>
<button class="button" data-modal="#modalOne"><img id="myImg" src=""></button>
<button class="button" data-modal="#modalB"><img id="myImg" src=""></button>
<button class="button" data-modal="#modalC"><img id="myImg" src=""></button>
<!-- The Modal -->
<div id="modalA" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<div class= "mySlides">
<img class="gif" src="" width="100" height="100" >
<h4>Title</h4>
<p> content </p>
</div>
<div class="mySlides">
<h4 Title</h4>
<p> content </p>
</div>
<div class="w3-left w3-hover-text-khaki" onclick="plusDivs(-1)">❮</div>
<div class="w3-right w3-hover-text-khaki" onclick="plusDivs(1)">❯</div>
</div>
</div>
<!-- The Modal B -->
<div id="modalB" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<div class="mySlides">
<img class="gif" src="" width="100" height="100" >
<h4></h4>
<p></p>
</div>
</div>
</div>
<!-- The Modal C -->
<div id="modalC" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<div class="mySlides">
<img class="gif" src="" width="100" height="100" >
<h4></h4>
<p></p>
<div class="mySlides">
<h4></h4>
<p></p>
</div>
<div class="w3-left w3-hover-text-khaki" onclick="plusDivs(-1)">❮</div>
<div class="w3-right w3-hover-text-khaki" onclick="plusDivs(1)">❯</div>
</div>
</div>
When you do this line
var x = document.getElementsByClassName("mySlides");
You count all the elements with class name of "mySlides", which is ALL of the slides in the HTML document.
Add code in your button click routine to count the number of slides in the corresponding modal:
Add this at the top of the javascript:
var modal = "modalA";
showDivs(slideIndex, modal);
Change the button click to:
$(".button").on("click", function() {
modal = $(this).data("modal").text();
$("#" + modal).show();
document.body.classList.add("modal-open");
});
Modify your showDivs function to include the new variable:
function showDivs(n, modal) {
var i;
var x = document.getElementById(modal).getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("demo");
if (n > x.length) {slideIndex = 1}
if (n < 1) {slideIndex = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
/*dots[i].className = dots[i].className.replace(" w3-white", "");*/
}
x[slideIndex-1].style.display = "block";
/*dots[slideIndex-1].className += " w3-white";*/
}
Finally, change the data-modal attributes of your buttons to read:
<button class="button" data-modal="modalA">
<button class="button" data-modal="modalB">
<button class="button" data-modal="modalC">
You will also need to update the lines:
function plusDivs(n) {
showDivs(slideIndex += n, modal);
}
function currentDiv(n) {
showDivs(slideIndex = n, modal);
}

Categories