I'm working on a Drupal website and I'm working on revising a component. I would like the first accordion menu item open by default, I have been kind of stuck on this for a little while.
I can not add to html because content is dynamic so has to be done with JS. Here is the script so far.
Any help would be great.
Bellow is the JS and HTML
jQuery(document).ready(() => {
const buttons = document.querySelectorAll('[data-accordion-button]');
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', (e) => {
const toggle = (e.target.getAttribute('aria-expanded') === 'true') ? false : true;
const root = buttons[i].closest('[data-accordion-container]');
const panel = buttons[i].closest('[data-accordion-panel]');
const panelSiblings = getSiblings(panel);
const firstChild = getFirstChild();
const window = panel.querySelector('[data-accordion-window]');
const content = panel.querySelector('[data-accordion-content]');
buttons[i].setAttribute('aria-expanded', toggle);
buttons[i].setAttribute('tabindex', '0');
toggle ?
window.setAttribute('style', `height: ${content.offsetHeight}px; visibility: visible;`) :
window.setAttribute('style', 'height: 0; visibility: hidden;');
if (root.getAttribute('data-accordion-config-single') === 'true') {
panelSiblings.forEach((sibling) => {
const siblingButton = sibling.querySelector('[data-accordion-button]');
const siblingWindow = sibling.querySelector('[data-accordion-window]');
siblingButton.setAttribute('aria-expanded', 'false');
siblingWindow.setAttribute('style', 'height: 0; visibility: hidden;');
});
}
});
// Arrow key controls
buttons[i].addEventListener('keydown', (e) => {
if (e.keyCode === 38) {
if (i === 0) {
buttons[buttons.length - 1].focus();
} else {
buttons[i - 1].focus();
}
}
if (e.keyCode === 40) {
if (i === buttons.length - 1) {
buttons[0].focus();
} else {
buttons[i + 1].focus();
}
}
});
}
function getSiblings(element) {
let siblings = [];
let sibling = element.parentNode.firstChild;
while (sibling) {
if (sibling.nodeType === 1 && sibling !== element) {
siblings.push(sibling);
}
sibling = sibling.nextSibling
}
return siblings;
};
});
```
<div class="accordion" data-accordion-container data-accordion-config-single="false">
<article class="accordion__panel-container" data-accordion-panel>
<h3 class="accordion__header">
<button class="h4 accordion__button" data-accordion-button aria-expanded="false" tabindex="0">
Taxation & Regulation in a Token Economy
</button>
</h3>
<div class="accordion__window" data-accordion-window>
<div class="accordion__content wysiwyg" data-accordion-content>
<p>
This text is for placement only. Vestibulum id ligula porta felis euismod semper.
</p>
</div>
</div>
</article>
<article class="accordion__panel-container" data-accordion-panel>
<h3 class="accordion__header">
<button class="h4 accordion__button" data-accordion-button aria-expanded="false">
Regulatory Content Aggregation
</button>
</h3>
<div class="accordion__window" data-accordion-window>
<div class="accordion__content wysiwyg" data-accordion-content>
<p>We demonstrate our commitment to Total Rewards through:</p>
</div>
</div>
</article>
</div>
Related
I'm using the scrollspy of Bootstrap-5.2 to update the displayed text whithin the scrollBox, when reaching the top or bottom part (pre-reload-item/post-reload-item).
The funktion for the bottom shiftContentDown works fine, but for shiftContentUp it works the first time only. After that the scrollspy doesn't activate the reload-top element anymore unless I scroll down to the post-reload-item (->reload-bottom activates -> shiftContentDown fires) and then up again.
I suspect it has something to do with the line document.getElementById('scrollBox').scrollBy(0, count * 24). Without it the new content of the pre-reload-item would be in fokus and the reload-top element stays active. With it the previous content of the pre-reload-item now part of the mid-reload-item stays visible and the reload-top element is no longer active. I'd expect it to activate again if I scroll up now, but for some reason it doesn't.
let nextIndex = 0;
let allContent = [];
let displayed = [0, 0]
let eof = false;
let pre = document.getElementById('pre-reload-item');
let mid = document.getElementById('mid-reload-item');
let post = document.getElementById('post-reload-item');
document.getElementById('scrollBox').addEventListener('activate.bs.scrollspy', () => {
let current = document.querySelector('#indexBox > a.active');
if (current === document.getElementById('reload-bottom')) {
shiftContentDown()
} else if (current === document.getElementById('reload-top')) {
shiftContentUp()
}
});
function shiftContentDown(count = 100, buffer = 0.5) {
let shift = allContent.length - displayed[1];
if (!eof && shift < count) {
getMoreContent(nextIndex);
} else {
let addition = allContent.slice(displayed[1], displayed[1] + count);
addition.forEach(l => {
if (pre.childElementCount >= (count * buffer)) {
pre.removeChild(pre.childNodes[0]);
displayed[0]++;
}
if (mid.childElementCount >= (count * (1 + 2*buffer)))
pre.appendChild(mid.childNodes[0]);
if (post.childElementCount >= (count * buffer) || post.childNodes.length > mid.childNodes.length)
mid.appendChild(post.childNodes[0]);
post.appendChild(l);
displayed[1]++;
});
}
}
function shiftContentUp(count = 100) {
let addition = allContent.slice(Math.max(displayed[0] - count, 0), displayed[0]);
addition.reverse().forEach(l => {
pre.insertBefore(l, pre.childNodes[0]);
displayed[0]--;
mid.insertBefore(pre.childNodes[pre.childElementCount - 1], mid.childNodes[0]);
post.insertBefore(mid.childNodes[mid.childElementCount - 1], post.childNodes[0]);
post.removeChild(post.childNodes[post.childElementCount - 1]);
displayed[1]--;
});
document.getElementById('scrollBox').scrollBy(0, count * 24);
}
function getMoreContent(index, chunkSize=100, last=1000) {
for (let i=0; i < chunkSize; i++) {
if (nextIndex < last) {
let newLineNode = document.createElement('div');
newLineNode.innerHTML = '----- ' + (nextIndex++) + ' -----';
allContent.push(newLineNode);
} else {
eof = true;
}
}
shiftContentDown();
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<div id="indexBox" class="list-group" style="display: none">
<a id="reload-bottom" class="list-group-item list-group-item-action" href="#post-reload-item">reload bottom</a>
<a id="reload-top" class="list-group-item list-group-item-action" href="#pre-reload-item">reload top</a>
</div>
<div id="scrollBox" data-bs-spy="scroll" data-bs-target="#indexBox" data-bs-smooth-scroll="true" data-bs-offset="0" class="scrollspy-example" tabindex="0" style="height: 300px; overflow-y: scroll">
<div id="pre-reload-item" class="text-bg-danger" style="white-space: pre-line"></div>
<div id="mid-reload-item" class="text-bg-info" style="white-space: pre-line"></div>
<div id="post-reload-item" class="text-bg-danger" style="white-space: pre-line"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
I have such an issue : I need to make smooth sub menu items fading with delay on mouseenter/leave, and i made a code
HTML + tailwind
<nav class="hidden shrink-0 xl:flex justify-center gap-x-8 items-center hover:[&>div>a]:opacity-100 [&>div>a]:opacity-50 [&>div>a]:transition-all">
<div>
Nav Hover
<div class="sub-nav absolute pt-12 pb-3 flex flex-col gap-y-2 [&>a]:text-gray-500 hover:[&>a]:text-black [&>a]:transition [&>a]:ease-in-out [&>a]:duration-300">
Item1
Item2
Item3
Item4
Item5
</div>
</div>
<div>Nav 2</div>
<div>Nav 3</div>
<div>Nav 4</div>
</nav>
JS
document.querySelector('#header nav div').addEventListener('mouseenter', function () {
if (this.querySelector('div') != null) {
this.querySelector('div').classList.remove('hidden')
let subNav = Array.from(this.querySelectorAll('div.sub-nav > a'))
console.log(subNav.length)
for (let i = 0; i < subNav.length; i++) {
console.log(subNav[i]);
setTimeout(function () {
subNav[i].style.opacity = 1
}, 100 * i);
}
}
})
document.querySelector('#header nav div').addEventListener('mouseleave', function () {
if (this.querySelector('div') != null) {
if (!this.querySelector('div').classList.contains('hidden')) {
let subNav = Array.from(this.querySelectorAll('div.sub-nav > a'))
console.log(subNav.length)
for (let i = subNav.length-1, d = 0; i >= 0, d < subNav.length; i--, d++) {
console.log(subNav[i]);
setTimeout(function () {
subNav[i].style.opacity = 0
if(i == 0){
this.querySelector('div').classList.add('hidden')
}
}, 100 * d);
}
}
}
})
it has two main problems :
If I enter area and then quickly leave it - the last items keeps visible and fadeOut animation breaks. I tried to check if opacity > 0 and then set it to 0^ but it doesnt work
This gives me error "Uncaught TypeError: this.querySelector is not a function"
if(i == 0){
this.querySelector('div').classList.add('hidden')
}
What the solution and best practices to the code? Thanks!
I tried opacity checking
I have a component that should be reusable within a page. And it should be called only when in view.
I've added an extra class function outside class Tabs which is called class Pagination.
this class is not within class Tabs which is breaking the component if reused within the page (multiple times).
Would anyone help me to move the class Pagination inside Tabs? My goal is having a unique class, so I can reuse the component multiple times and only when is in view. I really hope it makes sense,
here you have a Pen demo, as you can see the pagination is not in the right constuctor. I brake the function everytime I try to move it.
class Pagination {
constructor(tabComponent, prevBtnId, nextBtnId) {
this.arrayUtils = new ArrayUtils();
this.tabComponent = tabComponent;
this.prevBtn = document.querySelector(prevBtnId);
this.nextBtn = document.querySelector(nextBtnId);
// listen to tabComponents newly created Toggle event
// in which we wanna make sure to disable Btns or something..
this.tabComponent.onTabsToggle((tabs, tabIndex) => {
this.applyPaginationRules(tabs, tabIndex);
});
}
setDisabled(btn, value) {
if (value) {
btn.setAttribute("disabled", "true");
} else {
btn.removeAttribute("disabled");
}
}
applyPaginationRules(tabs, newActiveIndex) {
const nextBtnDisabled = newActiveIndex === tabs.length - 1;
const prevBtnDisabled = newActiveIndex === 0;
this.setDisabled(this.nextBtn, nextBtnDisabled);
this.setDisabled(this.prevBtn, prevBtnDisabled);
}
paginate(btn, action) {
const block = btn.closest(".tabs-block");
const panels = block.querySelectorAll(".panel");
const tabs = block.querySelectorAll(".tab-wrapper > li > button");
const activeIndex = Array.from(tabs).findIndex(
(t) => t.getAttribute("data-open") === "true"
);
if (tabs.length < 2) {
console.log("0 OR 1 tabs to toggle so no action.");
return;
}
var newActiveIndex;
if (action === "next") {
newActiveIndex = this.arrayUtils.nextIndex(activeIndex, tabs);
} else if (action === "prev") {
newActiveIndex = this.arrayUtils.previousIndex(activeIndex, tabs);
} else {
throw "Invalid toggle action " + action;
}
// enable / disable next and previous btns..
this.applyPaginationRules(tabs, newActiveIndex);
this.tabComponent.toggleTabs(tabs[newActiveIndex], panels);
}
addPaginationListener(btn, action) {
btn.addEventListener("click", (e) => {
this.paginate(btn, action);
});
}
init() {
this.addPaginationListener(this.prevBtn, "prev");
this.addPaginationListener(this.nextBtn, "next");
// disable prev button on beggining since we start at 0..
this.setDisabled(this.prevBtn, true);
}
}
class ArrayUtils {
// getting next index in array
nextIndex(currentIndex, array) {
// if 0 OR 1 elements, index stays the same..
if (array.length < 2) return currentIndex;
// if possible increment.
if (currentIndex < array.length - 1) {
return currentIndex + 1;
}
// if index would exceed array size go to start.
return 0;
}
// getting previous INdex in array:
previousIndex(currentIndex, array) {
// if 0 OR 1 elements, index stays the same..
if (array.length < 2) return currentIndex;
// if possible decrement!
if (currentIndex > 0) {
return currentIndex - 1;
}
// start at the end of array when end is reached ofc.
return array.length - 1;
}
}
class Tabs {
constructor() {
this.tabsBlocks = document.querySelectorAll(".tabs-block");
this.onToggleHandlers = [];
}
onTabsToggle(fn) {
this.onToggleHandlers.push(fn);
}
emitTabsToggle(tabs, tabIndex) {
this.onToggleHandlers.forEach((fn) => fn(tabs, tabIndex));
}
init() {
if (this.tabsBlocks.length > 0) {
Array.prototype.forEach.call(this.tabsBlocks, (tabBlock, index) => {
const tabContainer = tabBlock.querySelector(".tab-wrapper");
const tabs = tabBlock.querySelectorAll(".tab-wrapper li button");
const panels = tabBlock.querySelectorAll(".panel");
tabContainer.setAttribute("role", "tablist");
Array.prototype.forEach.call(tabs, (tab, tabIndex) => {
if (tab.dataset.open === "true") this.toggleTabs(tab, panels);
tab.setAttribute("role", "tab");
tab.setAttribute(
"aria-controls",
`panel-${tab.dataset.target}-block-${index + 1}`
);
const associatedPanel = tabBlock.querySelector(
`[data-panel="${tab.dataset.target}"]`
);
if (associatedPanel !== null) {
associatedPanel.id = `panel-${tab.dataset.target}-block-${
index + 1
}`;
tab.id = `tab-${tab.dataset.target}-block-${index + 1}`;
}
tab.addEventListener("click", () => {
this.toggleTabs(tab, panels);
this.emitTabsToggle(tabs, tabIndex);
});
});
Array.prototype.forEach.call(panels, (panel) => {
const associatedTab = tabBlock.querySelector(
`[data-target="${panel.dataset.panel}"]`
);
panel.setAttribute("role", "tabpanel");
panel.setAttribute("aria-labelledby", `${associatedTab.id}`);
});
});
}
}
toggleTabs = (currentTab, panels) => {
const tabs = currentTab.closest(".tabs-block").querySelectorAll("button");
const target = currentTab.dataset.target;
Array.prototype.forEach.call(tabs, (tab) => {
if (tab.dataset.target !== target) {
tab.classList.remove("is-active");
tab.setAttribute("data-open", "false");
tab.setAttribute("aria-selected", "false");
}
});
Array.prototype.forEach.call(panels, (panel) => {
if (panel.dataset.panel !== target) {
panel.classList.remove("is-active");
} else {
panel.classList.add("is-active");
}
});
/// activate tab..
currentTab.classList.add("is-active");
currentTab.setAttribute("data-open", "true");
currentTab.setAttribute("aria-selected", "true");
};
}
const components = {
Tabs: new Tabs()
};
components.Tabs.init();
// have the pagination more decoupled from tabs!
// it uses tabs component but you can remove it OR apply it to other
// classes like so more easily..
const prevBtnId = ".pagination-prev";
const nextBtnId = ".pagination-next";
const pagination = new Pagination(components.Tabs, prevBtnId, nextBtnId);
pagination.init();
.tabs-block {
border: 1px solid red;
}
.tabs-block .tab-wrapper li {
flex: 1 1 0%;
text-align: center;
}
.tabs-block .tab-wrapper li button {
font-weight: lighter;
font-size: rem(20px);
}
.tabs-block .tab-wrapper li button.is-active {
font-weight: normal;
}
.tabs-block .panel {
display: none;
}
.tabs-block .panel.is-active {
display: block;
}
.is-active {
color: red;
}
<section class="tabs-block">
<ul class="tab-wrapper">
<li><button data-target="1" data-open="true">Tab title 1</button></li>
<li><button data-target="2">Tab title 2</button></li>
<li><button data-target="3">Tab title 3</button></li>
</ul>
<div class="panel-wrapper">
<div data-panel="1" class="panel">
<p>Panel 1 content</p>
</div>
<div data-panel="2" class="panel">
<p>Panel 2 content</p>
</div>
<div data-panel="3" class="panel">
<p>Panel 3 content</p>
</div>
</div>
<button class="buttonPrev pagination-prev">
<< Prev</button>
<button class="buttonNext pagination-next">Next >></button>
</section>
I have some simple vanilla accordion and I'm not really sure why the CSS transition is not applying here? The divs have correct height, what is going on here?
(Cannot post because apparently my issue is mostly code, so this text is a dirty fix, sorry).
HTML (simplified version)
<div class="container">
<ul>
<li class="accordion-item">
<button class="accordion-item__title">
Title
</button>
<div class="accordion-item__body not-active">
Body
</div>
</li>
</ul>
</div>
JS
document.addEventListener('DOMContentLoaded', function () {
const accordions = document.querySelectorAll('.block-accordion');
if (typeof (accordions) !== 'undefined' && accordions != null) {
//loop thorugh all acordions
for (let a = 0; a < accordions.length; a++) {
const accordion = accordions[a];
const accordionItems = accordion.querySelectorAll('.accordion-item');
//loop through all accordiond's items
for (let i = 0; i < accordionItems.length; i++) {
const accordionItem = accordionItems[i];
//show first by default
accordionItems[0].querySelector('.accordion-item__body').classList.remove('not-active');
accordionItems[0].querySelector('.accordion-item__body').parentElement.classList.add('active');
accordionItems[0].querySelector('.accordion-item__title').setAttribute("aria-expanded", true);
//hide each accordion on click
const accordionItemTitle = accordionItem.firstElementChild;
accordionItemTitle.addEventListener('click', function toggleAccordion(e) {
const accordionContent = accordionItem.querySelector('.accordion-item__body');
accordionContent.style.height = "auto";
if (accordionContent.previousElementSibling === e.target) {
accordionContent.classList.toggle('not-active');
accordionContent.parentElement.classList.toggle('active');
if (accordionContent.classList.contains('not-active')) {
accordionContent.style.height = '0px';
accordionContent.previousElementSibling.setAttribute("aria-expanded", false);
} else {
accordionContent.style.height = accordionContent.clientHeight + 'px';
accordionContent.previousElementSibling.setAttribute("aria-expanded", true);
}
}
});
}
}
}
});
SASS
.block-accordion {
.active {
display: block;
}
.not-active {
display: none;
transition: height 0.35s ease-in-out;
overflow: hidden;
}
}
How can I stop this carousel from bubbling the animation? If you click right faster, it will start to mix up things. I need to stop the event handler function if the animation is running, inside that timeOut, the handlers should go offline.
Please see snippet below:
var Carousel = function(element, options) {
this.carousel = document.querySelector(element);
this.slides = Array.prototype.slice.call(this.carousel.querySelectorAll('.item'), null);
this.prev = this.carousel.querySelector("[data-slide='prev']");
this.next = this.carousel.querySelector("[data-slide='next']");
this.indicators = this.carousel.querySelectorAll(".carousel-indicators li");
this.interval = options && options.interval ? options.interval : 5000;
this.duration = 600; // bootstrap carousel default transition duration
this.paused = null;
this.direction = null;
this.index = 0;
this.total = this.slides.length;
this.init();
};
Carousel.prototype = {
init: function() {
this.cycle();
this.actions();
},
_slideTo: function(next, e) {
var self = this;
//determine type
var active = self._getActiveIndex(); // the current active
var direction = self.direction;
var type = direction === 'left' ? 'next' : 'prev';
if (!this.slides[next].classList.contains(type)) {
//e.preventDefault();
//e.defaultPrevented = false;
this.slides[next].classList.add(type);
this.slides[next].offsetWidth;
this.slides[active].classList.add(direction);
this.slides[next].classList.add(direction);
setTimeout(function() {
console.log('inside timeout prevented? ' + e.defaultPrevented);
self.slides[next].classList.remove(type, direction);
self.slides[next].classList.add('active');
self.slides[active].classList.remove('active', direction);
self._curentPage(self.indicators[next]);
//e.defaultPrevented = false;
}, self.duration + 200);
}
},
_getActiveIndex: function() {
return this._getItemIndex('.item.active')
},
_getItemIndex: function(itm) {
return this.slides.indexOf(this.carousel.querySelector(itm))
},
_curentPage: function(p) {
for (var i = 0; i < this.indicators.length; ++i) {
var a = this.indicators[i];
a.className = "";
}
p.className = "active";
},
cycle: function() {
var self = this;
//deleted some shit
},
actions: function() {
var self = this;
self.next.addEventListener("click", function(e) {
e.preventDefault();
self.index++;
self.direction = 'left'; //set direction first
if (self.index == self.total - 1) {
self.index = self.total - 1;
} else if (self.index == self.total) {
self.index = 0
}
self._slideTo(self.index, e);
}, false);
self.prev.addEventListener("click", function(e) {
e.preventDefault();
self.index--;
self.direction = 'right'; //set direction first
if (self.index == 0) {
self.index = 0;
} else if (self.index < 0) {
self.index = self.total - 1
}
self._slideTo(self.index, e);
}, false);
for (var i = 0; i < self.indicators.length; ++i) {
var a = self.indicators[i];
a.addEventListener("click", function(e) {
e.preventDefault();
var n = parseInt(this.getAttribute("data-slide-to"), 10);
self.index = n;
if (self.index == 0) {
self.index = 0;
}
if (self.index > 0) {}
if (self.index == self.total - 1) {
self.index = self.total - 1;
} else {}
//determine direction first
var active = self._getActiveIndex(); // the current active
if ((active < self.index) || (active === self.total - 1 && self.index === 0)) {
self.direction = 'left'; // next
} else if ((active > self.index) || (active === 0 && self.index === self.total - 1)) {
self.direction = 'right'; // prev
}
self._slideTo(self.index, e);
}, false);
}
window.addEventListener('keydown', function(e) {
if (/input|textarea/i.test(e.target.tagName)) return;
switch (e.which) {
case 39:
self.index++;
self.direction = 'left';
if (self.index == self.total - 1) {
self.index = self.total - 1;
} else
if (self.index == self.total) {
self.index = 0
}
break;
case 37:
self.index--;
self.direction = 'right';
if (self.index == 0) {
self.index = 0;
} else
if (self.index < 0) {
self.index = self.total - 1
}
break;
default:
return;
}
// e.preventDefault();
self._slideTo(self.index, e);
}, false)
}
}
var slider = new Carousel("#myCarousel1");
#myCarousel1 {
height: 300px;
max-width: 100%
}
.item {
height: 300px;
background: url(http://placehold.it/100x100/069/069.png) repeat center center;
background-size: cover
}
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" />
<div id="myCarousel1" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#myCarousel1" data-slide-to="0" class="active"></li>
<li data-target="#myCarousel1" data-slide-to="1"></li>
<li data-target="#myCarousel1" data-slide-to="2"></li>
</ol>
<div class="carousel-inner">
<div class="item active">
<div class="container">
<div class="carousel-caption">
<h1>Example headline.</h1>
<p>Note: If you're viewing this page via a <code>file://</code> URL, the "next" and "previous" Glyphicon buttons on the left and right might not load/display properly due to web browser security rules.</p>
<p><a class="btn btn-lg btn-primary" href="#" role="button">Sign up today</a>
</p>
</div>
</div>
</div>
<div class="item">
<div class="container">
<div class="carousel-caption">
<h1>Another example headline.</h1>
<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
<p><a class="btn btn-lg btn-primary" href="#" role="button">Learn more</a>
</p>
</div>
</div>
</div>
<div class="item">
<div class="container">
<div class="carousel-caption">
<h1>One more for good measure.</h1>
<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
<p><a class="btn btn-lg btn-primary" href="#" role="button">Browse gallery</a>
</p>
</div>
</div>
</div>
</div>
<span class="glyphicon glyphicon-chevron-left"></span>
<span class="glyphicon glyphicon-chevron-right"></span>
</div>
Perhaps checking the time interval between the clicks and returning false from the function that slides the carousel can solve this problem:
var oldTs = 0;
element.removeEventListener("click", slideClickHandler);
function slideClickHandler(e) {
var ts = e.timeStamp;
if ((oldTs !== 0) && (ts - oldTs < 500)) return false; //If time between clicks is 500 miliseconds and its not the first click cancel slide
else {
oldTs = ts; //Update timestamp buffer
slide(); //Do the sliding stuff
}
}
element.addEventListener('click', slideClickHandler);
Edit: You should put this code in a function and refresh the click handler after every slide for it to work.