JavaScript array skipping values - javascript

I have this function that loops through all of the <img> tags and adds their sourcesrc into an array. When the user clicks on the main parent div, Bootstrap's modal fades in showing the rest of the gallery.
My problem is, whenever I press the right chevron on a specific div it shows the gallery and slides them perfectly but when I click on another div, the array skips two values and displays the third one instead.
To explain my problem more briefly, lets say I have this array:
arr = [1,2,3,4,5]
When I click the next button the first time it works perfectly
1 => 2 => 3 => 4 => 5
But when I click on another div and press next:
1 => 2 => 5
Here's a working demo of what I have done till now.
HTML:
<div class="col-md-4 col-sm-4 col-lg-4 padBtm10">
<a data-toggle="modal" data-target="#exampleModal" href="#" class="modal-trigger deco-none" onclick="return false;">
<div class="card that_img radius10">
<img data-caption-title="First caption" class="card-img-top img-responsive caption" src="http://dummyimage.com/500x300/000/fff" alt="Card image cap" />
<span class="fa fa-search search fa-3x blue"></span>
<div class="redbg radiusBtm10 white card-block">
<h4 class="card-title">Lorem Ipsum</h4>
</div>
<div class="imgs-album">
<img src="http://dummyimage.com/500x300/000/fff" class="img-responsive full" data-caption-title="First caption for slider 1" />
<img src="http://dummyimage.com/500x300/ddd/fff" class="img-responsive full" data-caption-title="First caption for slider 2" />
<img src="http://dummyimage.com/500x300/aaa/fff" class="img-responsive full" data-caption-title="First caption for slider 3" />
<img src="http://dummyimage.com/500x300/ccc/000" class="img-responsive full" data-caption-title="First caption for slider 4" />
</div>
</div>
</a>
</div>
update (HTML structure for the modal)
<div class="modal breaker fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body noPad">
<button type="button" class="close-pop close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<div class="">
<a href="#" onclick="return false;">
<span class="fa fa-chevron-right fa-2x right white"></span>
</a>
<a href="#" onclick="return false;">
<span class="fa fa-chevron-left fa-2x left white"></span>
</a>
</div>
<div class="pop-image">
<img src="" class="img-responsive full">
</div>
<h4 class="modal_caption"></h4>
</div>
</div>
</div>
</div>
JavaScript:
(function() {
var ready = function() {
$(".that_img").hover(function() {
$(this).find("span.search").css("display", "block");
}, function() {
$(this).find("span.search").css("display", "none");
});
$(".that_img").on({
click: function() {
var img_src_arr = $(this).find(".imgs-album")
.children("img").map(function() {
return $(this).attr("src");
}).get();
var img_data_cap = $(this).find(".imgs-album")
.children("img").map(function() {
return $(this).data("caption-title");
}).get();
$(".pop-image").find("img").attr("src", img_src_arr[0]);
$(".modal_caption").html(img_data_cap[0]);
var counter = 0;
counter >= 0 ? $(".left").hide() : $(".left").show();
$(".right").on({
click: function() {
counter += 1;
if (counter == 1) {
$(".left").show()
}
var next = $(".pop-image").find("img")
.attr("src", img_src_arr[counter]);
var next_cap = $(".modal_caption")
.html(img_data_cap[counter]);
if (counter > (img_src_arr.length - 2)) {
$(".right").hide();
$(".left").show();
}
}
});
$(".left").on({
click: function() {
counter -= 1;
$(".right").show();
if (counter === 0) {
$(".right").show();
$(".left").hide();
}
$(".pop-image").find("img")
.attr("src", img_src_arr[counter]);
var prev = $(".modal_caption").html(img_data_cap[counter]);
}
});
}
});
}
$(document).ready(ready);
}).call(this);

The problem occurs because every time an image is clicked, click-handlers are added. With the first image everything seems fine because .left and .right have, at that point, a single click handler. Upon clicking another image, new click-handlers are added and now when you click a chevron, the 2 handlers are being executed resulting in your counter going up, or down, by 2 instead of 1. To prevent this from happening you will have to unbind the handlers from the object.
Change these lines, (explanation here)
$(".right").on({
$(".left").on({
to,
$(".right").off().on({
$(".left").off().on({
And change this line,
counter >= 0 ? $(".left").hide() : $(".left").show();
to,
$(".right").show()
$(".left").hide()
Edit : as mentioned by juhana unbind() is deprecated, so use off() instead.

Related

Javascript - Carousel managed automatically and with keyboard

I'm developing an automatic and keyboard managed carousel slider but it doesn't respond when I hit the previous or back buttons in the keyboard. It works when I click the previous and next buttons, and changes automatically.
Here is my HTML and Js code:
let currentSlide = 0;
const slides = document.querySelectorAll(".picture")
//carousel
const init = (n) => {
slides.forEach((picture, index) => {
picture.style.display = "none"
})
slides[n].style.display = "block"
}
//left and right buttons
document.addEventListener("DOMContentLoaded", init(currentSlide))
const next = () => {
currentSlide >= slides.length - 1 ? currentSlide = 0 : currentSlide++
init(currentSlide)
}
const prev = () => {
currentSlide <= 0 ? currentSlide = slides.length - 1 : currentSlide--
init(currentSlide)
}
document.querySelector(".buttonleft").addEventListener('click', prev)
document.querySelector(".buttonright").addEventListener('click', next)
//each 3 seconds change picture
setInterval(() => {
next()
}, 3000);
// NAVIGATE WITH KEYS
document.keydown(function(e) {
if (e.keyCode === 37) {
// Previous
$(".buttonleft").click();
return false;
}
if (e.keyCode === 39) {
// Next
$(".buttonright").click();
return false;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="carousel-container">
<!-- next and prev buttons -->
<div class="navigation">
<div class="btn buttonleft">
<img src="assets/img/left.png">
</div>
<div class="btn buttonright">
<img src="assets/img/right.png">
</div>
<!-- carousel -->
<div class="carousel">
<div class="logo">
<img src="assets/img/mmlogo.png" alt="Yahoo" class="image">
</div>
<div class="picture fade">
<a href="http://www.yahoo.com" target="_blank">
<img src="assets/img/image1.png" alt="Cloudy with a Chance of Meatballs" class="image">
</a>
</div>
<div class="picture fade">
<a href="http://www.google.com" target="_blank">
<img src="assets/img/image2.png" alt="Cloudy with a Chance of Meatballs" class="image">
</a>
</div>
<div class="picture fade">
<a href="http://www.youtube.com" target="_blank">
<img src="assets/img/image3.png" alt="Cloudy with a Chance of Meatballs" class="image">
</a>
</div>
<div class="picture fade">
<a href="http://www.gmail.com" target="_blank">
<img src="assets/img/image4.png" alt="Cloudy with a Chance of Meatballs" class="image">
</a>
</div>
<div class="picture fade">
<a href="http://www.outlook.com" target="_blank">
<img src="assets/img/image5.png" alt="Cloudy with a Chance of Meatballs" class="image">
</a>
</div>
</div>
</div>
</div>
Any ideas? I don't want to use Bootstrap.
Thanks!
Looks like you're using vanilla javascript, until the last event listener. Looks like jquery.
Make it vanilla js like you did above. It works fine.
Keeping your console tools open will give you a good idea of what's wrong.
document.addEventListener('keydown', (function(e) {
if (e.keyCode === 37) {
// Previous
console.log("prev");
}
if (e.keyCode === 39) {
// Next
console.log("next");
}
}));

Using JavaScript Show and Hide Div but styling disappear when showing the div again

I'm working image gallery page Sitecore MVC platform.
The razor page I'm working on have should display first 8 image only on default. When user click the load more button. It'll display all images.
The first 8 image would be stack and it should be in columns of 4. The rest of the images should be 4 across and expand downwards when the Load More button is clicked
I decided to use 2 Divs and JavaScript to achieve the Load More function. E.g One div is show 8 and the other to show all.
The first 8 is showing with the correct styling but when I hide and show the other div with exact same style its not being render correctly. Instead of 4 columns they are all stack into 1.
Please help.....
#{
//to handle id must start with letter compatibility. HTML5 removed this restriction tho
var minimisedDivId = ENU.SitecoreHelper.Resources.HTMLHelpers.EnsureGuidStartsWithLetter(Guid.NewGuid());
var loadMoreDivId = ENU.SitecoreHelper.Resources.HTMLHelpers.EnsureGuidStartsWithLetter(Guid.NewGuid());
}
<head>
<script>
function toggleDiv() {
var minimised = document.getElementById("#minimisedDivId");
var loadMore = document.getElementById("#loadMoreDivId");
if (minimised.style.display === "none") {
minimised.style.display = "block";
loadMore.style.display = "none";
} else {
minimised.style.display = "none";
loadMore.style.display = "block";
}
}
</script>
<style>
.imagegallery-container {
margin: 0px;
padding: 0px;
position: relative;
text-align: center;
}
.imagegallery-area {
margin: 0px;
padding: 0px;
}
.imagegallery {
margin: 0px;
padding: 0px;
}
.image-area {
/* margin: 0px;
padding: 0px;*/
}
.thumbnail {
margin: 0px;
padding: 0px;
}
.imageText {
position: relative;
bottom: 10%;
left: 50%;
transform: translate(-50%, -50%);
}
.loadMore {
margin: 0 auto; /*center*/
}
</style>
</head>
<div class="row imagegallery-container">
<div class="col"> </div>
<!-- TODO: Load first 8 -->
<div class="imagegallery-area row col-8" id="#minimisedDivId">
#if (Model.IsInEditMode)
{
foreach (var item in Model.Children.ToList().Select((value, index) => new { value, index }))
{
<span class="col-3 editor">
#Html.Glass().Editable(item.value, x => x.Thumbnail)
</span>
}
}
#if (Model.Children.Any())
{
<!-- TODO: I need to take the first 8 of and display them-->
foreach (var item in Model.Children.ToList().Take(8).Select((value, index) => new { value, index }))
{
<a class="col-3 thumbnail" data-toggle="modal" data-target="#carouselModal" style="border:2px red">
#*<img src="#item.value.ThumbnailUrl" />*#
#Html.Glass().RenderImage(item.value, x => x.Thumbnail, new { w = 200, h = 200, mw = 200, mh = 200 }, isEditable: true)
<div class="imageText">#Html.Glass().Editable(item.value, x => x.Text)</div>
</a>
}
}
<div class="loadMore">
<button onclick="toggleDiv()">LOAD MORE</button>
</div>
</div>
<!-- TODO: Load all -->
<div class="imagegallery-area row col-8" id="#loadMoreDivId" style="display:none;">
#if (Model.IsInEditMode)
{
foreach (var item in Model.Children.ToList().Select((value, index) => new { value, index }))
{
<span class="col-3 editor">
#Html.Glass().Editable(item.value, x => x.Thumbnail)
</span>
}
}
#if (Model.Children.Any())
{
// Display max of 8 items, 4 across and stacking to 2
foreach (var item in Model.Children.ToList().Select((value, index) => new { value, index }))
{
//Carousel should have a closed button,top right. Image number buttom right e.g 1 of 8
<a class="col-3 thumbnail" data-toggle="modal" data-target="#carouselModal" style="border:2px red">
<img src="#item.value.ThumbnailUrl" />
#Html.Glass().RenderImage(item.value, x => x.Thumbnail, new { w = 200, h = 200, mw = 200, mh = 200 }, isEditable: true)
<div class="imageText">#Html.Glass().Editable(item.value, x => x.Text)</div>
</a>
}
}
<div class="loadMore">
<button >Collapsed</button>
</div>
</div>
<!-- TODO: I would then display all the elements if LOAD MORE is clicked -->
<!-- LOAD MORE-->
<!-- This would show all the rows-->
<!-- Modal -->
<div class="modal fade" id="carouselModal" tabindex="-1" role="dialog" aria-labelledby="carouselModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalTitle"></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="carouselControls" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carouselControls" data-slide-to="0" class="active"></li>
<li data-target="#carouselControls" data-slide-to="1"></li>
<li data-target="#carouselControls" data-slide-to="2"></li>
</ol>
<div class="carousel-inner">
#if (Model.Children.Any())
{
//get the first imageItem for "active" class
<div class="carousel-item active">
<img class="d-block w-100" src="#Model.Children.ToList().First().ImageUrl" alt="#Model.Children.ToList().First().Title" />
<div class="imageText">#Model.Children.ToList().First().Text)</div>
</div>
Model.Children.ToList().Skip(1);
//The carry on the rest in the look with no active
foreach (var item in Model.Children.ToList().Select((value, index) => new { value, index }))
{
<div class="carousel-item">
<img class="d-block w-100" src="#item.value.ImageUrl" alt="#item.value.Title" />
<div class="imageText">#Html.Glass().Editable(item.value, x => x.Text)</div>
</div>
}
}
</div>
<a class="carousel-control-prev" href="#carouselControls" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselControls" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div>
<div class="modal-footer">
x of x
</div>
</div>
</div>
</div>
<div class="clearfix"></div>
<div class="col"> </div>
</div>
Try editing this row (in both locations):
div class="imagegallery-area row col-8"
And move row into its own div:
div class="imagegallery-area col-8"
div class="row">
A div should be a row or a col, not both.

Angular ngFor - restriction to show on every item

I have got following code in my component.html. ( I am new to angular )
<div class="card" *ngFor="let item of galleries;"
(mouseenter)=" setBackground(item?.image?.fullpath)"
(mouseover)="showCount = true; getImagesCount(item.path);" (mouseleave)="showCount = false">
<img class="card-img-top" [routerLink]="['/'+item.path]"
[src]="item?.image?.fullpath ? path + '0x156/' + item?.image?.fullpath : defaultImage"
alt="Card image cap">
<div class="card-block">
<h4 class="card-title imagesCount"></h4>
<h4 class="card-title title">{{item.name}}</h4>
<img class="closeIcon" src="../../../assets/images/close.png" alt="" (click)="removeGallery(item);">
<span class="animated fadeInUp" *ngIf="showCount">{{imagesCount}}</span>
</div>
</div>
Down in the code i have *ngIf="showCount where i am trying to show how many images gallery have. But issue is that it is shown on every card, but i want it to show only on current card that i enter my mouse with.
You should specify your *ngIf in:
<span class="animated fadeInUp" *ngIf="showCount">{{imagesCount}}</span>
because actually you will get for every item in your galleries list.
Here is an idea, how you can specify that:
Step 1: Add new variable to your component.ts
currentItem: number;
Step 2: add index to your ngFor
*ngFor="let item of galleries; let index = index;"
Step 3: Extend your (mouseover) and (mouseleave) events
Add currentItem and fill with data.
(mouseover)="showCount = true; currentItem = index; getImagesCount(item.path);"
(mouseleave)="showCount = false; currentItem = null;"
Step 4: Change you *ngIf in span with itemsCount
<span class="animated fadeInUp" *ngIf="showCount && currentItem == index">{{imagesCount}}</span>
Now you have a spicified solution.
I would suggest you to create an extra key i.e. showCount inside item object.
item = {
...,
showCount: false
}
than use that key for showing and hiding showCount in the HTML.
<div class="card" *ngFor="let item of galleries;"
(mouseenter)=" setBackground(item?.image?.fullpath)"
(mouseover)="item[showCount] = true; getImagesCount(item.path);"
(mouseleave)="item[showCount] = false">
<img class="card-img-top" [routerLink]="['/'+item.path]"
[src]="item?.image?.fullpath ? path + '0x156/' + item?.image?.fullpath : defaultImage"
alt="Card image cap">
<div class="card-block">
<h4 class="card-title imagesCount"></h4>
<h4 class="card-title title">{{item.name}}</h4>
<img class="closeIcon" src="../../../assets/images/close.png" alt="" (click)="removeGallery(item);">
<span class="animated fadeInUp" [hidden]="item[showCount]">{{imagesCount}}</span>
</div>
</div>
I would approach this by making your 'showCount' variable into an array, and comparing *ngIf to the array value:
Some small tweaks:
<div class="card" *ngFor="let item of galleries; let idx=index">
....
(mouseover)="showCount[idx]=true
(mouseleave)="showCount[idx]=false
</div>
...
<span class="animated fadeInUp" *ngIf="showCount[idx]">

How to create a URL that links directly to open a Bootstrap Modal

I have an issue where I'm attempting to use a URL to open a Modal in window B, by clicking on an image link in window A. The image itself is setup inside an anchor tag, such that <a href="myserver.mydestinationB.com#myModal><img src='myImage'></a> is in window A.
How can I get to window B AND open the modal only using the URL, if possible.
Code :
Page A
<a href="http://www.x.com/#DesiredModalID">
<img typeof="foaf:Image" src="http://google.com/image.png" width="1920" height="1080" alt="">
</a>
Page B
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog"><!-- Modal content-->
<div class="modal-content">
<div class="modal-header"><button id="modalclose" class="close" data- dismiss="modal" type="button">×</button>
<h4 class="modal-title" id="header-data">Modal Header</h4>
</div>
<div class="modal-body">
<p id="modal-text">Some text in the modal.</p>
<div id="modal-body" style="text-align: center;"> </div>
</div>
<div class="modal-footer">
<h5 id="footer-data" style="font-weight:bold;font-style:italic;float:left;">Test Data</h5>
<button class="btn btn-default" data-dismiss="modal" id="closetwo" type="button">Close</button></div>
</div>
</div>
<img id="myimage" src='myImage'>
<script>
$(document).ready(function(){
$("#myimage").click(function() {
$("#myModal").modal();
})
})
</script>
<a href="myserver.mydestinationB.com?mymodal=open>
--- On Page B you add script ---
<script>
$(document).ready(function(){
var mymodal = $_GET('mymodal');
if(mymodal != null){
$("#myModal").modal();
}
})
function $_GET(param) {
var vars = {};
window.location.href.replace( location.hash, '' ).replace(
/[?&]+([^=&]+)=?([^&]*)?/gi, // regexp
function( m, key, value ) { // callback
vars[key] = value !== undefined ? value : '';
}
);
if ( param ) {
return vars[param] ? vars[param] : null;
}
return vars;
}
</script>

Moving DIV disable button 0px left-margin

I have a little problem. Im trying to create my own slider using jQuery and some css/javascript.
I got my slider to work moving a Div 660px to the left and right by clicking a button.
But, I would like to have the right button disabled when the left margin is 0. And I would like the whole div to rewind back to 0px after some clicks.
Is this possible?
Here is my code:
<script language="javascript">
function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
}
</script>
<div class="container">
<div class="row">
<div class="contr-left">
<a type="button" value="Move Left" onclick="example_animate('-=600px')"><i class="fa fa-chevron-circle-left fa-2x" aria-hidden="true" ></i></a>
</div>
<div id="carreview" class="carousel" data-ride="carousel" style="opacity: 1; display: block;">
<div class="wrapper-outer">
<div class="wrapper-inner" id="slide">
<?php get_template_part('loop-reviews');?>
</div>
</div>
<div class="contr-right">
<a type="button" value="Move Right" onclick="example_animate('+=600px')"><i class="fa fa-chevron-circle-right fa-2x" aria-hidden="true" ></i></a>
</div>
</div>
</div>
</div>
The code im using is from this page: Page
Well, with the code from Rayn i got the button to hide, but now it won't show when left-margin is 1px or something. So I'm trying this now: (doesn't work btw)
Im trying this now: (doesn't work btw)`function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
var slidemarginleft = $('#slide').css('margin-left'); //this gets the value of margin-left
if(slidemarginleft == '0px'){
$('.contr-right').hide();
} else (slidemarginleft == '1px') {
$('.contr-right').show();
}
}`
Also I'm seeing that the margin-left isn't set in the style sheet but in the
<div style="margin-left:0px">content</div>
You can do an if statement after each click to check if the element has 0px
function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
var slidemarginleft = $('#slide').css('margin-left'); //this gets the value of margin-left
if(slidemarginleft == '0px'){
$('.contr-right').hide();
}
}
Use this
function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
if($('.xman').css("marginLeft")=='0px'){
$('.contr-left').attr('disabled',true);
}
}
Disable Button when margin-left: 0px
You can use jquery's .prop() method to disable a button if a condition is met. Here is an example (in pseudo code):
function disableButton() {
$(element).prop('disabled', true);
}
function checkMargin() {
if ($(element).css("margin") === 0) {
disableButton()
}
}
checkMargin()
Rewind to 0px after some clicks
Here, I'd just set a count for clicks and trigger a function when it meets the threshold you want. Pseudo code:
var threshold = 5
var clicks = 0
$(element).click(function(){
clicks++
if (clicks === 5) {
rewind();
}
clicks - 5
})
function rewind() {
$(element).css( "margin", "0" );
checkMargin()
}
Here is my working code, thanks for all the help:
<script>
function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
var slidemarginleft = $('#slide').css('margin-left'); //this gets the value of margin-left
if(slidemarginleft < '-3000px'){
$('#slide').animate({marginLeft: '0px'}, 400);
}
var hide = $('#slide').css('margin-left'); //this gets the value of margin-left
if(hide >= '-50px'){
$('.contr-left').addClass('showMe');
}
var hideMe = $('#slide').css('margin-left'); //this gets the value of margin-left
if(hideMe <= '-50px'){
$('.contr-left').removeClass('showMe');
}
}
</script>
<!-- /Review script -->
<section id="reviews">
<div class="container">
<div class="row">
<div class="container">
<div class="row">
<h4>Reviews</h4>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-sm-1" style="width:40px;">
<div class="row">
<div class="contr-left">
<a type="button" value="Move Left" onclick="example_animate('+=510px')"><i class="fa fa-chevron-circle-left fa-2x" aria-hidden="true" ></i></a>
</div>
</div>
</div>
<div class="col-sm-10">
<div class="row">
<div id="carreview" class="carousel" data-ride="carousel" style="opacity: 1; display: block;">
<div class="wrapper-outer">
<div class="wrapper-inner" id="slide" style="margin-left:0px;">
<?php get_template_part('loop-reviews');?>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-1" style="width:40px;">
<div class="row">
<div class="contr-right">
<a type="button" value="Move Right" onclick="example_animate('-=510px')"><i class="fa fa-chevron-circle-right fa-2x" aria-hidden="true" ></i></a>
</div>
</div>
</div>
</div>
<div class="btn btn-06">Bekijk alle reviews</div>
</div>
</section>

Categories