Multiple Auto-scrolling list of items - javascript

This is what I have right now
$(document).ready(function () {
var waitingTimeBottom = 2500;
var waitingTimeTop = 5000;
var animFactor = 20;
autoScroll('.qbox1');
autoScroll('.qbox2');
autoScroll('.qbox3');
autoScroll('.qbox4');
function autoScroll(qbx){
$q = $(qbx);
$m = $(qbx + ' .marq');
var mh = $m.height();
var qh = $q.height();
var xpx = mh - qh;
var animationTime = xpx * animFactor;
function scroll() {
$m.animate({'top': -xpx + "px"}, animationTime, "linear", function () {
$m.delay(waitingTimeBottom).animate({'top': '0px'}, animationTime, "linear", function () {
setTimeout(function () {
scroll();
}, waitingTimeTop);
});
});
}
if (mh > qh) {
scroll();
} else {
console.log("too few items");
}
}
});
.qbox1, .qbox2, .qbox3, .qbox4 {
height: 60vh;
width: auto;
box-sizing: border-box;
overflow: hidden;
float:left;
margin-left: 2px;
}
.marq {
position: relative;
box-sizing: border-box;
}
.item {
color: #39739d;
background-color: #E1ECF4;
border-color: #96bdd9;
box-shadow: inset 0 1px 0 #f4f8fb;
box-sizing: border-box;
padding: 5px;
margin-bottom: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="qbox1">
<div class="marq">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
<div class="item">Item 13</div>
<div class="item">Item 14</div>
<div class="item">Item 15</div>
</div>
</div>
<div class="qbox2">
<div class="marq">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
<div class="item">Item 13</div>
<div class="item">Item 14</div>
<div class="item">Item 15</div>
</div>
</div>
<div class="qbox3">
<div class="marq">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
<div class="item">Item 13</div>
<div class="item">Item 14</div>
<div class="item">Item 15</div>
</div>
</div>
<div class="qbox4">
<div class="marq">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
<div class="item">Item 13</div>
<div class="item">Item 14</div>
<div class="item">Item 15</div>
</div>
</div>
Out of four, a single qbox is supposed to work like
$(document).ready(function() {
var waitingTimeBottom = 2500;
var waitingTimeTop = 5000;
var animFactor = 20;
autoScroll('.qbox1');
function autoScroll(qbx) {
$q = $(qbx);
$m = $(qbx + ' .marq');
var mh = $m.height();
var qh = $q.height();
var xpx = mh - qh;
var animationTime = xpx * animFactor;
function scroll() {
$m.animate({
'top': -xpx + "px"
}, animationTime, "linear", function() {
$m.delay(waitingTimeBottom).animate({
'top': '0px'
}, animationTime, "linear", function() {
setTimeout(function() {
scroll();
}, waitingTimeTop);
});
});
}
if (mh > qh) {
scroll();
} else {
console.log("too few items");
}
}
});
.qbox1,
.qbox2,
.qbox3,
.qbox4 {
height: 60vh;
width: auto;
box-sizing: border-box;
overflow: hidden;
float: left;
margin-left: 2px;
}
.marq {
position: relative;
box-sizing: border-box;
}
.item {
color: #39739d;
background-color: #E1ECF4;
border-color: #96bdd9;
box-shadow: inset 0 1px 0 #f4f8fb;
box-sizing: border-box;
padding: 5px;
margin-bottom: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="qbox1">
<div class="marq">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
<div class="item">Item 13</div>
<div class="item">Item 14</div>
<div class="item">Item 15</div>
</div>
</div>
Why there is a conflict when multiple qbox are inserted?

Try this...
Change
$q = $(qbx); $m = $(qbx + ' .marq'); to var $q = $(qbx); var $m = $(qbx + ' .marq');
$(document).ready(function () {
var waitingTimeBottom = 2500;
var waitingTimeTop = 5000;
var animFactor = 20;
autoScroll('.qbox1');
autoScroll('.qbox2');
autoScroll('.qbox3');
autoScroll('.qbox4');
function autoScroll(qbx){
var $q = $(qbx);
var $m = $(qbx + ' .marq');
var mh = $m.height();
var qh = $q.height();
var xpx = mh - qh;
var animationTime = xpx * animFactor;
function scroll() {
$m.animate({'top': -xpx + "px"}, animationTime, "linear", function () {
$m.delay(waitingTimeBottom).animate({'top': '0px'}, animationTime, "linear", function () {
setTimeout(function () {
scroll();
}, waitingTimeTop);
});
});
}
if (mh > qh) {
scroll();
} else {
console.log("too few items");
}
}
});
.qbox1, .qbox2, .qbox3, .qbox4 {
height: 60vh;
width: auto;
box-sizing: border-box;
overflow: hidden;
float:left;
margin-left: 2px;
}
.marq {
position: relative;
box-sizing: border-box;
}
.item {
color: #39739d;
background-color: #E1ECF4;
border-color: #96bdd9;
box-shadow: inset 0 1px 0 #f4f8fb;
box-sizing: border-box;
padding: 5px;
margin-bottom: 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="qbox1">
<div class="marq">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
<div class="item">Item 13</div>
<div class="item">Item 14</div>
<div class="item">Item 15</div>
</div>
</div>
<div class="qbox2">
<div class="marq">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
<div class="item">Item 13</div>
<div class="item">Item 14</div>
<div class="item">Item 15</div>
</div>
</div>
<div class="qbox3">
<div class="marq">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
<div class="item">Item 13</div>
<div class="item">Item 14</div>
<div class="item">Item 15</div>
</div>
</div>
<div class="qbox4">
<div class="marq">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
<div class="item">Item 13</div>
<div class="item">Item 14</div>
<div class="item">Item 15</div>
</div>
</div>

Related

Dynamically add incrementing class between multiple nth-children(n+)

I am looking to add an incrementing class between every 4 children.
So, "Item 1 to Item 4" should have the class ".summary-item-1" and then "Item 5 to Item 7" should have the class ".summary-item-2" and so on without stopping.
$(document).ready((function() {
$(".carousel-slides-view-4").each((function() {
$(this).find(".summary-item:nth-child(4n+1)").each((function(n) {
$(this).addClass("summary-item-" + (n + 1))
}))
}))
}));
.summary-item-1 {
color: red;
}
.summary-item-2 {
color: blue;
}
.summary-item-3 {
color: green;
}
.summary-item-4 {
color: yellow;
}
.summary-item-5 {
color: orange;
}
.summary-item-6 {
color: violet;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="carousel-slides-view-4">
<div class="summary-item">Item 1</div>
<div class="summary-item">Item 2</div>
<div class="summary-item">Item 3</div>
<div class="summary-item">Item 4</div>
<div class="summary-item">Item 5</div>
<div class="summary-item">Item 6</div>
<div class="summary-item">Item 7</div>
<div class="summary-item">Item 8</div>
<div class="summary-item">Item 9</div>
<div class="summary-item">Item 10</div>
<div class="summary-item">Item 11</div>
<div class="summary-item">Item 12</div>
<div class="summary-item">Item 13</div>
<div class="summary-item">Item 14</div>
<div class="summary-item">Item 15</div>
<div class="summary-item">Item 16</div>
<div class="summary-item">Item 17</div>
</div>
Please try to use this code
document.querySelectorAll('.summary-item').forEach((element,index) => {
const itemIndex = parseInt(index / 4) + 1;
element.classList.add(`summary-item-${itemIndex}`);
});
.summary-item-1 {
color: red;
}
.summary-item-2 {
color: blue;
}
.summary-item-3 {
color: green;
}
.summary-item-4 {
color: yellow;
}
.summary-item-5 {
color: orange;
}
.summary-item-6 {
color: violet;
}
<div class="carousel-slides-view-4">
<div class="summary-item">Item 1</div>
<div class="summary-item">Item 2</div>
<div class="summary-item">Item 3</div>
<div class="summary-item">Item 4</div>
<div class="summary-item">Item 5</div>
<div class="summary-item">Item 6</div>
<div class="summary-item">Item 7</div>
<div class="summary-item">Item 8</div>
<div class="summary-item">Item 9</div>
<div class="summary-item">Item 10</div>
<div class="summary-item">Item 11</div>
<div class="summary-item">Item 12</div>
<div class="summary-item">Item 13</div>
<div class="summary-item">Item 14</div>
<div class="summary-item">Item 15</div>
<div class="summary-item">Item 16</div>
<div class="summary-item">Item 17</div>
</div>

How to select every first items of multiple blocks (html, javascript)

I'm trying to select every first item of a serie of multiple blocks but I can't figure out how to do this :(
Here is an exemple of what I've tried :
let everyItems = Array.from(document.querySelectorAll('.block .item'));
let firstItems = Array.from(everyItems[0]);
document.getElementById('every1stItem').innerText = firstItems.innerText;
<div calss="block"><b>First block</b>
<div class="item">Item 1.1</div>
<div class="item">Item 1.2</div>
<div class="item">Item 1.3</div>
<div class="item">Item 1.4</div>
</div>
<div calss="block"><b>Second block</b>
<div class="item">Item 2.1</div>
<div class="item">Item 2.2</div>
<div class="item">Item 2.3</div>
<div class="item">Item 2.4</div>
</div>
<div calss="block"><b>Third block</b>
<div class="item">Item 3.1</div>
<div class="item">Item 3.2</div>
<sdivan class="item">Item 3.3</div>
<div class="item">Item 3.4</div>
</div>
<div>
<b>The first item of every block is :</b>
<div id="every1stItem"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Thank you for helping me out !
You can do something like this
let everyItems = Array.from(document.querySelectorAll('.block'));
let firstItems = everyItems.map(i => i.children[1].innerText).join(', ')
document.getElementById('every1stItem').innerText = firstItems;
<div class="block"><b>First block</b>
<div class="item">Item 1.1</div>
<div class="item">Item 1.2</div>
<div class="item">Item 1.3</div>
<div class="item">Item 1.4</div>
</div>
<div class="block"><b>Second block</b>
<div class="item">Item 2.1</div>
<div class="item">Item 2.2</div>
<div class="item">Item 2.3</div>
<div class="item">Item 2.4</div>
</div>
<div class="block"><b>Third block</b>
<div class="item">Item 3.1</div>
<div class="item">Item 3.2</div>
<div class="item">Item 3.3</div>
<div class="item">Item 3.4</div>
</div>
<div>
<b>The first item of every block is :</b>
<div id="every1stItem"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
using :nth-child(n) selector
let everyItems = $('.item:nth-child(2)');
$('#every1stItem').html(everyItems)
<div>
<b>The first item of every block is :</b>
<div id="every1stItem"></div>
</div>
<hr>
<div class="block"><b>First block</b>
<div class="item">Item 1.1</div>
<div class="item">Item 1.2</div>
<div class="item">Item 1.3</div>
<div class="item">Item 1.4</div>
</div>
<div class="block"><b>Second block</b>
<div class="item">Item 2.1</div>
<div class="item">Item 2.2</div>
<div class="item">Item 2.3</div>
<div class="item">Item 2.4</div>
</div>
<div class="block"><b>Third block</b>
<div class="item">Item 3.1</div>
<div class="item">Item 3.2</div>
<div class="item">Item 3.3</div>
<div class="item">Item 3.4</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
document.queryselector(".className") returns the first element with the class className

How to target a part of CSS class name?

Example 1 works:
HTML:
<div class="items">
<div class="item">item 1</div>
<div class="prefix-item-suffix">item 2</div>
<div class="item">item 3</div>
</div>
CSS:
div[class^="prefix"][class$="suffix"] {
color: red;
}
Example 2 doesn't:
HTML:
<div class="items">
<div class="item">item 1</div>
<div class="multiple prefix-item-suffix classes">item 2</div>
<div class="item">item 3</div>
</div>
CSS:
div[class^="prefix"][class$="suffix"] {
color: red;
}
Example 2 has multiple classes so CSS approach stops working. In real time project the multiple classes will be random except the one targeted in between them, the value between prefix-the_dynamic_value-suffix will also be random, how to target that with other classes inside same element? Because example 1 approach doesn't work.
Try [class*=…]
div[class*="prefix-"][class*="-suffix"] {
color: red;
}
<div class="items">
<div class="item">item 1</div>
<div class="multiple prefix-item-suffix classes">item 2</div>
<div class="item">item 3</div>
</div>
You could do this with js by checking if some class on the element starts with prefix and ends with suffix. If the check returns true then you run your code.
document.querySelectorAll('.items > div').forEach(el => {
const check = [...el.classList].some(cls => {
return cls.startsWith('prefix') && cls.endsWith('suffix')
})
if (check) {
el.style.color = 'red'
}
})
<div class="items">
<div class="item">item 1</div>
<div class="multiple prefix-item-suffix classes">item 2</div>
<div class="item prefix-item-suffix-not-this">item 3</div>
</div>

open and close menus

I have 4 menus and with this piece of code, i can show menus and hide them with specific btns .my question is how can i when i open a menu and i don't close it and then I open another one close previous menus? i tried to store the open menu in a variable and check it when i open another one but it didn't work.
<body>
<div class="container"> ‌
<div class="menu">
<button class="btn">open</button>
<div class="items">
<div class="items-container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item">item 3</div>
<div class="item">item 4</div>
<div class="item">item 6</div>
</div>
</div>
</div>
<div class="container"> ‌
<div class="menu">
<button class="btn">open</button>
<div class="items">
<div class="items-container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item">item 3</div>
<div class="item">item 4</div>
<div class="item">item 6</div>
</div>
</div>
</div>
<div class="container"> ‌
<div class="menu">
<button class="btn">open</button>
<div class="items">
<div class="items-container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item">item 3</div>
<div class="item">item 4</div>
<div class="item">item 6</div>
</div>
</div>
</div>
<div class="container"> ‌
<div class="menu">
<button class="btn">open</button>
<div class="items">
<div class="items-container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item">item 3</div>
<div class="item">item 4</div>
<div class="item">item 6</div>
</div>
</div>
</div>
</div>
</body>
const btns = document.querySelectorAll(".btn");
btns.forEach(btn => {
const menu = btn.parentElement;
const items = menu.querySelector(".items");
const itemsContainer = items.querySelector(".items-container");
const itemsContainerHeight = itemsContainer.getBoundingClientRect().height;
let previousActivebtn = "";
btn.addEventListener("click", (e) => {
// change btn text
if (e.currentTarget.innerHTML == "open") {
e.currentTarget.innerHTML = "close";
} else {
e.currentTarget.innerHTML = "open";
}
//show and hid the menus
if (!items.classList.contains("item-active")) {
items.classList.add("item-active");
items.style.height = itemsContainerHeight + 32 + "px";
} else {
items.classList.remove("item-active");
items.removeAttribute("style");
}
});
});
You overcomplicate it. You could create a CSS rule which would ensure that .items is hidden, unless .menu is opened:
.menu .items:not(.open) {
display: none
}
And you could create a function like this:
function open(item) {
if (!item.classList.contains("open")) {
//Hide whatever was opened
for (let it of document.querySelectorAll(.menu .items.open)) {
it.classList.remove("open")
}
item.classList.add("open");
} else {
item.classList.remove("open");
}
}
Just pass to this function the item having the class of items.

Make content scroll behind sticky header

I have a scroll area in which there are different headings which I want to be sticky, have a look at this fiddle.
.item{
height: 60px;
width: 100%;
background-color:red;
margin:3px 0;
}
.heading{
position:sticky;
top:0;
height:40px;
}
<div style="overflow-y:auto;height:300px;">
<h3 class="heading">Heading 1</h3>
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<h3 class="heading">Heading 2</h3>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<h3 class="heading">Heading 3</h3>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<h3 class="heading">Heading 4</h3>
<div class="item">Item 19</div>
<div class="item">Item 11</div>
<div class="item">Item 12</div>
</div>
As you can see every item is visible behind the headings. As in the fiddle, in my real application these heading elements are also transparent. So I need a way to make the items overflow right under each heading.
Place background:inherit to heading and every wrapping element up to the element which has the image as backgrund. Plunkr Credits

Categories

Resources