jQuery - prev/next navigation between non-siblings - javascript

I have a bunch of elements of the same type that have different parents, but I would like to be able to seamlessly navigate/cycle through all of them as if they were together.
<div>
<a href="#" class="open></a>
</div>
<div>
</div>
<div>
</div>
‹
›
I've managed to get this far: https://jsfiddle.net/pj0ecxge/
Currently it doesn't function as intended, as prev() and next() are only meant to target sibling elements, so the arrows don't work if the previous or next element is in another parent.
A single element will always be open by default, but it won't always be the same element as shown in the example. Also, only one element can be open at the same time.
If it makes a difference, I can add a single class to all children elements, but I can't change the HTML structure i.e put them all inside the same parent.
It would be nice if the navigation is infinite - i.e clicking next while the last element is open will show the first element and vice versa, but this is not required if it's too complex to do.
Thanks in advance and any help will be very appreciated!

You can check whether there are next/previous elements, if not then you can move a layer up/down like
$('.prev').click(function(e) {
e.preventDefault();
var current = $('.open');
var prev = current.prev();
if (!prev.length) {
prev = current.parent().prev('div').children('a:last-child')
}
if (prev.length) {
current.removeClass('open');
prev.addClass('open');
}
});
$('.next').click(function(e) {
e.preventDefault();
var current = $('.open');
var next = current.next();
if (!next.length) {
next = current.parent().next('div').children('a:first-child')
}
if (next.length) {
current.removeClass('open');
next.addClass('open');
}
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
text-align: center;
}
div {
font-size: 0;
}
div a {
width: 150px;
height: 150px;
border: 2px solid black;
}
a {
display: inline-block;
}
.open {
background: red;
}
.prev,
.next {
font-size: 100px;
text-decoration: none;
margin: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
</div>
<div>
</div>
<div>
</div>
‹
›

Find the next set when the current set has reached either end. And the if the set is the last one then go back to the first one (and vice-versa).
$('.prev').click(function(e) {
e.preventDefault();
var current = $('.open');
var prev = current.prev();
if (!prev.length) {
prev = current.parent().prev('div').children('a:last-of-type');
if (!prev.length) {
prev = $('div:last-of-type').children('a:last-of-type');
}
}
current.removeClass('open');
prev.addClass('open');
});
$('.next').click(function(e) {
e.preventDefault();
var current = $('.open');
var next = current.next();
if (!next.length) {
next = current.parent().next('div').children('a:first-of-type');
if (!next.length) {
next = $('div:first-of-type').children('a:first-of-type');
}
}
current.removeClass('open');
next.addClass('open');
});

Related

Use html <a> tag with same z-index?

I have slider and when i mouseover on slider play button is displaying, but slider images are inside a tag and when play button is not hidden i can't click on images inside a tag. i tried set same z-index for both (slider images and play button) but still not working
i need to click on play button when it shown and go to link placed bottom of this play button
if it is possible please help, and sorry for my bad english.
Main question: how can i click on play button with and redirect to link placed inside a tag?
Here is image how slider looks like onmouseover and image when mouse is out of slider
here is my html code:
<style type="text/css">
#slider-play-button-container{
position: absolute;
z-index: 2;
left: 0;
right: 0;
text-align: center;
cursor: pointer;
}
#slider-play-button{
position: relative;
top: 25vh;
width: 2vw;
opacity: 0;
}
.slide-img{
width: 100%;
height: 55vh;
object-fit: cover;
border-radius: .7vw;
overflow:hidden;
}
</style>
<main class=content>
<span id="slider-play-button-container"><img src="https://i.imgur.com/md7vyI8.png" id="slider-play-button"></span>
<div id="slider">
<a href="Link to go after play button click" target="_Blank">
<h3 class="slider-movie-name">ჯონ ვიკი: III თავი - პარაბელუმი</h3>
<img src="https://i.imgur.com/OP3AITl.jpg" class="slide-img">
</a>
<a href="Another link to go after play button click" target="_Blank">
<h3 class="slider-movie-name">შურისმაძიებლები: დასასრული</h3>
<img src="https://i.imgur.com/3vDzVHa.jpg" class="slide-img">
</a>
</div>
</main>
<script>
function bid(n){return document.getElementById(n)}
function qs(n){return document.querySelector(n)}
function qsa(n){return document.querySelectorAll(n)}
let slider = bid('slider');
let arrowTop = bid('slide_arrow_top');
let arrowBottom = bid('slide_arrow_bottom');
let sliderImage = qsa('.slide-img');
let sliderPlayButtonContainer = bid('slider-play-button-container');
let sliderPlayButton = bid('slider-play-button');
let count = 0;
let imageOffset = 0;
let imgOffset = 0;
var slideInterval;
let sliderImageOffset;
/* autoscroll */
window.addEventListener('load',winLoadForSlide);
function winLoadForSlide(){
/* slider */
slider.addEventListener('wheel',slideMouseScroll);
arrowBottom.addEventListener('click',scrollBottom);
arrowTop.addEventListener('click',scrollTop);
function bottomSlide(){
if (count < 4) {
count++;
}
imageOffset = sliderImage[count].offsetTop;
slider.scrollTo(0,imageOffset);
}
function topSlide(){
if (count > 0) {
count--;
}
imageOffset = sliderImage[count].offsetTop;
slider.scrollTo(0,imageOffset-5);
}
function slideMouseScroll(){
if (event.deltaY < 0){
topSlide();
}else if (event.deltaY > 0){
bottomSlide();
}
}
function scrollBottom(){
bottomSlide();
}
function scrollTop(){
topSlide();
}
slideInterval = setInterval(repeatScroll,100 * 20);
function showSliderPlayButton(){
sliderPlayButton.style.transform = "scale(5)";
sliderPlayButton.style.opacity = "1";
sliderPlayButton.style.transition = "250ms";
}
function hideSliderPlayButton(){
sliderPlayButton.style.transform = "scale(1)";
sliderPlayButton.style.opacity = "0";
sliderPlayButton.style.transition = "250ms";
}
[slider,arrowBottom,arrowTop,sliderPlayButtonContainer,sliderPlayButton].forEach(slideElements => {
slideElements.addEventListener('mouseover',()=>{
clearInterval(slideInterval);
});
slideElements.ondragstart = function(){ return false; }
});
[slider,sliderPlayButtonContainer,sliderPlayButton].forEach(slideElementsWithoutButtons => {
slideElementsWithoutButtons.addEventListener('mouseover',()=>{
showSliderPlayButton();
});
});
slider.addEventListener('mouseleave',()=>{
slideInterval = setInterval(repeatScroll,100 * 20);
hideSliderPlayButton();
});
function repeatScroll(){
if( (slider.scrollHeight - slider.scrollTop - slider.clientHeight) !== 4 ){
if (imgOffset < 4) {
imgOffset++;
}
sliderImageOffset = sliderImage[imgOffset].offsetTop;
slider.scrollTo(0,sliderImageOffset);
}else{
imgOffset = 0;
slider.scrollTo(0,0);
}
}
/* END slider */
}
/* END autoscroll */
</script>
There are a few ways to get around this problem.
One would involve getting rid of the anchor tags altogether, grouping each image inside a single container and assigning a click event listener to each one to ultimately open the link. If you then add another click listener to the arrow button which executes event.preventDefault(); the click event will be passed through to the object below - the <div> including your image.
If you want to keep the anchor tags, things are a little tricky. Luckily there are some helpful JavaScript functions, foremost document.elementsFromPoint(x,y).
If you feed the current mouse coordinates to this function - e.g. by clicking on the arrow button - it will return an array of objects below this point.
This array contains the anchor element in the background, so it's just a matter of picking it out of the array, get the link assigned to it and open it using the window.open() command.
Here's an example:
function bid(n) {
return document.getElementById(n)
}
let sliderPlayButtonContainer = bid('slider-play-button-container');
let sliderPlayButton = bid('slider-play-button');
sliderPlayButtonContainer.addEventListener('click', (event) => {
var list = document.elementsFromPoint(event.clientX, event.clientY)
var anchorElement = list.find(element => element instanceof HTMLImageElement && element.className == 'slide-img').parentElement;
window.open(anchorElement.href, anchorElement.target);
});
function showSliderPlayButton() {
sliderPlayButton.style.transform = "scale(5)";
sliderPlayButton.style.opacity = "1";
sliderPlayButton.style.transition = "250ms";
}
sliderPlayButtonContainer.addEventListener('mouseover', () => {
showSliderPlayButton();
});
#slider-play-button-container {
position: absolute;
z-index: 2;
left: 0;
right: 0;
text-align: center;
cursor: pointer;
}
#slider-play-button {
position: relative;
top: 25vh;
width: 2vw;
opacity: 1;
}
.slide-img {
width: 100%;
height: 55vh;
object-fit: cover;
border-radius: .7vw;
overflow: hidden;
}
<span id="slider-play-button-container"><img src="https://i.imgur.com/md7vyI8.png" id="slider-play-button"></span>
<div id="slider">
<a href="https://www.startpage.com" target="_blank">
<h3 class="slider-movie-name">ჯონ ვიკი: III თავი - პარაბელუმი</h3>
<img src="https://i.imgur.com/OP3AITl.jpg" class="slide-img">
</a>
</div>
parentElement property helped a lot to solve my problem
playButtonATagHref = sliderImage[imgOffset].parentElement.href;
sliderPlayButton.addEventListener('click',()=>{
window.location.href = playButtonATagHref;
});

Giving a div a style on click

applying a class to an element only when clicked
You could make 2 different click functions. One for trap and one for the rest.
For that you need to know which ones are the other ( safe ones ). See otherDivsIds in the below code. You find the other id's using the filter function in the idArray and then loop through them ( with forEach or something else ) and add event listeners to each of them.
I would also suggest to ' swap ' the naming of the variables trapBox and trapId. Vice versa would be better
See code below
var idArray = ['one','two','three','four'];
var trapBox = idArray[Math.floor(Math.random() * idArray.length)];
var trapId= document.getElementById(trapBox);
trapId.addEventListener('click', boomClickFunction, false);
var otherDivsIds = idArray.filter(id => id !== trapBox);
otherDivsIds.forEach(id => {
safeBox = document.getElementById(id);
safeBox.addEventListener('click', safeClickFunction, false)
})
var timeoutId = window.setTimeout(ticker, 5000);
function ticker() {
document.getElementById('timesUp').innerHTML = "Time's up!";
document.body.style.backgroundColor = "black";
}
function boomClickFunction() {
this.classList.add('boom')
}
function safeClickFunction() {
this.classList.add('safe')
}
div {
width: 20px;
height: 20px;
background-color: green;
margin: 20px;
float: left;
}
.boom {
background-color: red;
}
.safe {
background-color: lightblue;
}
#timesUp {
color: white;
}
<div id='one'>
</div>
<div id='two'>
</div>
<div id='three'>
</div>
<div id='four'>
</div>
<span id="timesUp">
</span>
You can add a class to an element by using classList.add('classToBeAdded').
In your case, you could put it in your clickFunction:
trapId.classList.add('boom');

My next and prev button for the list isn't working

The problem: I am not able to get the value of the HTML list from javascript. Each time user click next button, the program will count how many times the user clicks the next button. In javascript, I called the HTML list and iterate it. inside for loop, I called user click on next button number and add 1, The result of the sum will go inside the array and display that array line data. I don't know because of some reason I can't able to get data. Let me know if you get confused
Here is the HTML code
<div id="Border" class="">
<div id="Topic_List" class="creature">
<ul id="ListName" class="">
<li> Google </li>
<li>Facebook</li>
<li> Google </li>
</ul>
</div>
</div>
<div id="" class="" style="clear:both;"></div>
<div id="InputInsideFullCover" class="">
<textarea id="File_Name" name="File_Name"></textarea>
</div>
<button id="clickme" onclick="Next()"> Next </button>
<button onclick="Prev()"> Prev </button>
Here is the JavaScript code
<script>
function Next(){
var button = document.getElementById("clickme"),
count = 0;
button.onclick = function() {
count += 1;
var ul = document.getElementById("ListName");
var items = ul.getElementsByTagName("li");
for (var i = 0; i < items.length; ++i) {
var GetButtonClickValue = count;
var AddOne = GetButtonClickValue + 1;
var file_name = document.getElementById("ListName").innnerHTML=items[AddOne];
document.getElementById("File_Name").href = file_name;
var url_to_file = "http://www.example.com/"+file_name;
$.ajax({
url: url_to_file,
type:'HEAD',
error: function()
{
alert('data not found.');
},
success: function()
{
}
});
}
if(count > 9){
count = " ";
count = 1;
button.innerHTML = "Click me: " + count;
}
};
}
</script>
here is the CSS code
<style>
#Border{margin:5px auto;padding:0;width:50px;height:auto;border:1px solid #666;background-color:#f1f1f1}
#InputInsideFullCover{margin:5px;padding:0;width:700px;height:auto;}
#File_Name{margin:0;padding:0;width:638px;height:25px;resize:none;}
#Topic_List{margin:5px;padding:0;width:640px;height:auto;}
#Topic_List ul{margin:0px;padding:0;height:auto;width:12px;}
#Topic_List li{margin:0px;padding:0;list-style-type:none;float:left}
#button{
background-color: #4CAF50; /* Green background */
border: 1px solid green; /* Green border */
color: white; /* White text */
padding: 10px 24px; /* Some padding */
cursor: pointer; /* Pointer/hand icon */
width: 50%; /* Set a width if needed */
display: block; /* Make the buttons appear below each other */
}
.btn-group button:not(:last-child) {
border-bottom: none; /* Prevent double borders */
}
/* Add a background color on hover */
.btn-group button:hover {
background-color: #3e8e41;
}
</style>
You are declaring count to 0 at the beginning of the function. So every time the button is clicked count equals 0 and then one is added. (It will always be 1) You need to pull the count var outside of the function. This will also be useful for your Prev function. I bet that your Next and prev functions will be similar enough to make only one function. Call your function with true or false to add or subtract the count.
Just Add this
<script src="jquery-3.4.0.min.js"></script>
in your head tag before the external script tag
beacuse you are using ajax you need jquery

Creating Drop down page

I am after creating a drop down page like on my examples below:
This is how I would like it to show when the arrow on the side is cliked.
How would I make something like this and is there any examples any where for me to study to help me make this ?
If you can use jquery you can play with hasClass, addClass and removeClass to change the height of the submenu
Working Demo.
$(".btn").click(function() {
if ($(".menu").hasClass("dropped")) {
$(".menu").removeClass("dropped");
} else {
$(".menu").addClass("dropped");
}
});
.menu {
height: 0;
overflow: hidden;
transition: all 0.5s ease 0s;
}
.dropped {
height: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button class="btn">
Dropdown
</button>
<div class="menu">
<p>Stufss...</p>
<p>Stufss...</p>
<p>Stufss...</p>
<p>Stufss...</p>
<p>Stufss...</p>
<p>Stufss...</p>
</div>
With 3 div elements you can get a result like the one pictured. From the picture it looks like one div is wrapping around two other div elements, a div element that already has some information and a div element that will grow/shrink in size through appending/removing elements when the user presses the dropdown button.
Here is a working example:
var extraInformation = document.getElementById('infoLong');
var dropdown = document.getElementById('dropdown');
// The extra info that will be appended into the infoLong div
var someHeading = document.createElement('h4');
someHeading.innerHTML = 'Detailed Game Information';
someHeading.style.background = '#C58AC5';
var teamOneInfo = document.createElement('p');
teamOneInfo.innerHTML = 'Team 1: Lost';
teamOneInfo.style.background = '#FF516B';
var teamTwoInfo = document.createElement('p');
teamTwoInfo.innerHTML = 'Team 2: Won';
teamTwoInfo.style.background = '#3FBFBF';
// Should add more detailed information when the dropdown button
// is pressed only if the infoLong div is empty
dropdown.addEventListener('click', function(){
if(extraInformation.children.length === 0){
extraInformation.appendChild(someHeading);
extraInformation.appendChild(teamOneInfo);
extraInformation.appendChild(teamTwoInfo);
}else{
while(extraInformation.firstChild){
extraInformation.removeChild(extraInformation.firstChild);
}
}
});
#infoShort {
background: #3FBFBF;
}
p {
margin: 0;
}
h4 {
margin: 0;
}
<div id='gameInfoContainer'>
<div id='infoShort'>
<h3>Game Summary</h3>
<button id='dropdown'>Dropdown</button>
</div>
<div id='infoLong'></div>
</div>

jQuery, multiple content sliders in single page

I want to make a lot of slides in a one-page scrolling site. A neat way to do this was with a code from Stano. My problem is that this code was only meant to occur once per page. In order to make it fit my needs I made it into this fiddle. I realized that this would accumulate very fast into some rather messy coding if I had 20+ of these:
$(document).ready(function() {
var divs = $('.divs>div');
var now = 0; // currently shown div
divs.hide().first().show(); // hide all divs except first
$(".next").click(function() {
divs.eq(now).hide();
now = (now + 1 < divs.length) ? now + 1 : 0;
divs.eq(now).show(); // show next
});
$(".prev").click(function() {
divs.eq(now).hide();
now = (now > 0) ? now - 1 : divs.length - 1;
divs.eq(now).show(); // show previous
});
});
Is there any way to create a common ID/class for the divs and clickers (previous, next) or a container that ensures that the slider functions by itself without interrupting other sliders?
For example creating a variable with the ID of the container
var test = $('.container').attr('id') )
Implementing the ID in the divs
var divs = $(test).attr( 'id',$(test).attr('id') );
Implementing the ID in the next (and prev), so that when they are being clicked they will only affect the divs with the same ID
$(".next",test).click(function () {...
Maybe have a wrapper with a specific ID where the 3 divs (divs, prev and next) are includes and tell the script that they need to be in the same wrapper in order to affect each other.
<div ID="wrap1">
<div class="prev"></div>
<div class="next"></div>
<div class="divs"></div>
</div>
I do not know how the script will change. Maybe including .child() or .parent()?
I am very new at java scripting and hope that my question is understood properly. Please let me know if there is anything that needs to be clarified.
Check my code, each slider has now a function at document ready, not mixing thing around, and a jquery higher version was used.
$(document).ready(function () {
function FirstSlider(){
var divs = $('.div1>div');
var now = 0; // currently shown div
console.log(divs);
divs.hide().first().show(); // hide all divs except first
$(".nex1").click(function () {
divs.eq(now).hide();
now = (now + 1 < divs.length) ? now + 1 : 0;
divs.eq(now).show(); // show next
});
$(".pre1").click(function () {
divs.eq(now).hide();
now = (now > 0) ? now - 1 : divs.length - 1;
divs.eq(now).show(); // show previous
});
}
function SecondSlider(){
var divs = $('.div2>div');
var now = 0; // currently shown div
divs.hide().first().show(); // hide all divs except first
$(".nex2").click(function () {
divs.eq(now).hide();
now = (now + 1 < divs.length) ? now + 1 : 0;
divs.eq(now).show(); // show next
});
$(".pre2").click(function () {
divs.eq(now).hide();
now = (now > 0) ? now - 1 : divs.length - 1;
divs.eq(now).show(); // show previous
});
}
FirstSlider();
SecondSlider();
});
.body {
margin: 0 0;
}
.prenex {
position: fixed;
top:15vh;
display: block;
background-color: #aaa;
cursor: pointer;
width: auto;
height: auto;
font-size: 10vh;
padding: 2vh 4vh;
text-align: center;
opacity: .5;
-webkit-user-select: none;
/* Chrome/Safari */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* IE10+ */
}
.prev, .pre1, .pre2 {
left:5vh;
float:left;
}
.next, .nex1, .nex2 {
right: 5vh;
float:right;
}
.pre1, .nex1 {
top:20vh;
}
.pre2, .nex2 {
top:70vh;
}
.divs, .div1, .div2 {
width:70vw;
height:40vh;
margin: 0 auto;
display:block;
background-color:#aaa;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="prenex nex1">></div>
<div class="prenex pre1">
<</div>
<div class="div1">
<div>Hello World,</div>
<div>I</div>
<div>Am</div>
<div>The</div>
<div>Test</div>
</div>
<br>
<hr>
<br>
<div class="prenex nex2">></div>
<div class="prenex pre2">
<</div>
<div class="div2">
<div>Hello World,</div>
<div>why do I</div>
<div>follow</div>
<div>the steps of</div>
<div>my evil twin?</div>
</div>

Categories