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.
Related
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>
I have a slider(source code here) that currently has it's height set to 100%. However, I want the slider to have a height of 550px so it does not look too big, but am not managing to get that right for some reason.
Below is the full code and running snippet:
(function(factory){
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports !== 'undefined') {
module.exports = factory(require('jquery'));
} else {
factory(jQuery);
}
})(function($){
var Zippy = (function(element, settings){
var instanceUid = 0;
function _Zippy(element, settings){
this.defaults = {
slideDuration: '3000',
speed: 500,
arrowRight: '.arrow-right',
arrowLeft: '.arrow-left'
};
this.settings = $.extend({},this,this.defaults,settings);
this.initials = {
currSlide : 0,
$currSlide: null,
totalSlides : false,
csstransitions: false
};
$.extend(this,this.initials);
this.$el = $(element);
this.changeSlide = $.proxy(this.changeSlide,this);
this.init();
this.instanceUid = instanceUid++;
}
return _Zippy;
})();
Zippy.prototype.init = function(){
this.csstransitionsTest();
this.$el.addClass('zippy-carousel');
this.build();
this.events();
this.activate();
this.initTimer();
};
Zippy.prototype.csstransitionsTest = function(){
var elem = document.createElement('modernizr');
var props = ["transition","WebkitTransition","MozTransition","OTransition","msTransition"];
for ( var i in props ) {
var prop = props[i];
var result = elem.style[prop] !== undefined ? prop : false;
if (result){
this.csstransitions = result;
break;
}
}
};
Zippy.prototype.addCSSDuration = function(){
var _ = this;
this.$el.find('.slide').each(function(){
this.style[_.csstransitions+'Duration'] = _.settings.speed+'ms';
});
}
Zippy.prototype.removeCSSDuration = function(){
var _ = this;
this.$el.find('.slide').each(function(){
this.style[_.csstransitions+'Duration'] = '';
});
}
Zippy.prototype.build = function(){
var $indicators = this.$el.append('<ul class="indicators" >').find('.indicators');
this.totalSlides = this.$el.find('.slide').length;
for(var i = 0; i < this.totalSlides; i++) $indicators.append('<li data-index='+i+'>');
};
Zippy.prototype.activate = function(){
this.$currSlide = this.$el.find('.slide').eq(0);
this.$el.find('.indicators li').eq(0).addClass('active');
};
Zippy.prototype.events = function(){
$('body')
.on('click',this.settings.arrowRight,{direction:'right'},this.changeSlide)
.on('click',this.settings.arrowLeft,{direction:'left'},this.changeSlide)
.on('click','.indicators li',this.changeSlide);
};
Zippy.prototype.clearTimer = function(){
if (this.timer) clearInterval(this.timer);
};
Zippy.prototype.initTimer = function(){
this.timer = setInterval(this.changeSlide, this.settings.slideDuration);
};
Zippy.prototype.startTimer = function(){
this.initTimer();
this.throttle = false;
};
Zippy.prototype.changeSlide = function(e){e
if (this.throttle) return;
this.throttle = true;
this.clearTimer();
var direction = this._direction(e);
var animate = this._next(e,direction);
if (!animate) return;
var $nextSlide = this.$el.find('.slide').eq(this.currSlide).addClass(direction + ' active');
if (!this.csstransitions){
this._jsAnimation($nextSlide,direction);
} else {
this._cssAnimation($nextSlide,direction);
}
};
Zippy.prototype._direction = function(e){
var direction;
// Default to forward movement
if (typeof e !== 'undefined'){
direction = (typeof e.data === 'undefined' ? 'right' : e.data.direction);
} else {
direction = 'right';
}
return direction;
};
Zippy.prototype._next = function(e,direction){
var index = (typeof e !== 'undefined' ? $(e.currentTarget).data('index') : undefined);
switch(true){
case( typeof index !== 'undefined'):
if (this.currSlide == index){
this.startTimer();
return false;
}
this.currSlide = index;
break;
case(direction == 'right' && this.currSlide < (this.totalSlides - 1)):
this.currSlide++;
break;
case(direction == 'right'):
this.currSlide = 0;
break;
case(direction == 'left' && this.currSlide === 0):
this.currSlide = (this.totalSlides - 1);
break;
case(direction == 'left'):
this.currSlide--;
break;
}
return true;
};
Zippy.prototype._cssAnimation = function($nextSlide,direction){
setTimeout(function(){
this.$el.addClass('transition');
this.addCSSDuration();
this.$currSlide.addClass('shift-'+direction);
}.bind(this),100);
setTimeout(function(){
this.$el.removeClass('transition');
this.removeCSSDuration();
this.$currSlide.removeClass('active shift-left shift-right');
this.$currSlide = $nextSlide.removeClass(direction);
this._updateIndicators();
this.startTimer();
}.bind(this),100 + this.settings.speed);
};
Zippy.prototype._jsAnimation = function($nextSlide,direction){
var _ = this;
if(direction == 'right') _.$currSlide.addClass('js-reset-left');
var animation = {};
animation[direction] = '0%';
var animationPrev = {};
animationPrev[direction] = '100%';
this.$currSlide.animate(animationPrev,this.settings.speed);
$nextSlide.animate(animation,this.settings.speed,'swing',function(){
_.$currSlide.removeClass('active js-reset-left').attr('style','');
_.$currSlide = $nextSlide.removeClass(direction).attr('style','');
_._updateIndicators();
_.startTimer();
});
};
Zippy.prototype._updateIndicators = function(){
this.$el.find('.indicators li').removeClass('active').eq(this.currSlide).addClass('active');
};
$.fn.Zippy = function(options){
return this.each(function(index,el){
el.Zippy = new Zippy(el,options);
});
};
});
var args = {
arrowRight : '.arrow-right',
arrowLeft : '.arrow-left',
speed : 1000,
slideDuration : 4000
};
$('.carousel').Zippy(args);
(function(factory){
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports !== 'undefined') {
module.exports = factory(require('jquery'));
} else {
factory(jQuery);
}
})(function($){
var Zippy = (function(element, settings){
var instanceUid = 0;
function _Zippy(element, settings){
this.defaults = {
slideDuration: '3000',
speed: 500,
arrowRight: '.arrow-right',
arrowLeft: '.arrow-left'
};
this.settings = $.extend({},this,this.defaults,settings);
this.initials = {
currSlide : 0,
$currSlide: null,
totalSlides : false,
csstransitions: false
};
$.extend(this,this.initials);
this.$el = $(element);
this.changeSlide = $.proxy(this.changeSlide,this);
this.init();
this.instanceUid = instanceUid++;
}
return _Zippy;
})();
Zippy.prototype.init = function(){
this.csstransitionsTest();
this.$el.addClass('zippy-carousel');
this.build();
this.events();
this.activate();
this.initTimer();
};
Zippy.prototype.csstransitionsTest = function(){
var elem = document.createElement('modernizr');
var props = ["transition","WebkitTransition","MozTransition","OTransition","msTransition"];
for ( var i in props ) {
var prop = props[i];
var result = elem.style[prop] !== undefined ? prop : false;
if (result){
this.csstransitions = result;
break;
}
}
};
Zippy.prototype.addCSSDuration = function(){
var _ = this;
this.$el.find('.slide').each(function(){
this.style[_.csstransitions+'Duration'] = _.settings.speed+'ms';
});
}
Zippy.prototype.removeCSSDuration = function(){
var _ = this;
this.$el.find('.slide').each(function(){
this.style[_.csstransitions+'Duration'] = '';
});
}
Zippy.prototype.build = function(){
var $indicators = this.$el.append('<ul class="indicators" >').find('.indicators');
this.totalSlides = this.$el.find('.slide').length;
for(var i = 0; i < this.totalSlides; i++) $indicators.append('<li data-index='+i+'>');
};
Zippy.prototype.activate = function(){
this.$currSlide = this.$el.find('.slide').eq(0);
this.$el.find('.indicators li').eq(0).addClass('active');
};
Zippy.prototype.events = function(){
$('body')
.on('click',this.settings.arrowRight,{direction:'right'},this.changeSlide)
.on('click',this.settings.arrowLeft,{direction:'left'},this.changeSlide)
.on('click','.indicators li',this.changeSlide);
};
Zippy.prototype.clearTimer = function(){
if (this.timer) clearInterval(this.timer);
};
Zippy.prototype.initTimer = function(){
this.timer = setInterval(this.changeSlide, this.settings.slideDuration);
};
Zippy.prototype.startTimer = function(){
this.initTimer();
this.throttle = false;
};
Zippy.prototype.changeSlide = function(e){e
if (this.throttle) return;
this.throttle = true;
this.clearTimer();
var direction = this._direction(e);
var animate = this._next(e,direction);
if (!animate) return;
var $nextSlide = this.$el.find('.slide').eq(this.currSlide).addClass(direction + ' active');
if (!this.csstransitions){
this._jsAnimation($nextSlide,direction);
} else {
this._cssAnimation($nextSlide,direction);
}
};
Zippy.prototype._direction = function(e){
var direction;
// Default to forward movement
if (typeof e !== 'undefined'){
direction = (typeof e.data === 'undefined' ? 'right' : e.data.direction);
} else {
direction = 'right';
}
return direction;
};
Zippy.prototype._next = function(e,direction){
var index = (typeof e !== 'undefined' ? $(e.currentTarget).data('index') : undefined);
switch(true){
case( typeof index !== 'undefined'):
if (this.currSlide == index){
this.startTimer();
return false;
}
this.currSlide = index;
break;
case(direction == 'right' && this.currSlide < (this.totalSlides - 1)):
this.currSlide++;
break;
case(direction == 'right'):
this.currSlide = 0;
break;
case(direction == 'left' && this.currSlide === 0):
this.currSlide = (this.totalSlides - 1);
break;
case(direction == 'left'):
this.currSlide--;
break;
}
return true;
};
Zippy.prototype._cssAnimation = function($nextSlide,direction){
setTimeout(function(){
this.$el.addClass('transition');
this.addCSSDuration();
this.$currSlide.addClass('shift-'+direction);
}.bind(this),100);
setTimeout(function(){
this.$el.removeClass('transition');
this.removeCSSDuration();
this.$currSlide.removeClass('active shift-left shift-right');
this.$currSlide = $nextSlide.removeClass(direction);
this._updateIndicators();
this.startTimer();
}.bind(this),100 + this.settings.speed);
};
Zippy.prototype._jsAnimation = function($nextSlide,direction){
var _ = this;
if(direction == 'right') _.$currSlide.addClass('js-reset-left');
var animation = {};
animation[direction] = '0%';
var animationPrev = {};
animationPrev[direction] = '100%';
this.$currSlide.animate(animationPrev,this.settings.speed);
$nextSlide.animate(animation,this.settings.speed,'swing',function(){
_.$currSlide.removeClass('active js-reset-left').attr('style','');
_.$currSlide = $nextSlide.removeClass(direction).attr('style','');
_._updateIndicators();
_.startTimer();
});
};
Zippy.prototype._updateIndicators = function(){
this.$el.find('.indicators li').removeClass('active').eq(this.currSlide).addClass('active');
};
$.fn.Zippy = function(options){
return this.each(function(index,el){
el.Zippy = new Zippy(el,options);
});
};
});
var args = {
arrowRight : '.arrow-right',
arrowLeft : '.arrow-left',
speed : 1000,
slideDuration : 4000
};
$('.carousel').Zippy(args);
<div class="wrapper">
<div class="carousel">
<div class="inner">
<div class="slide active">
<div class="slide-box">
<h1>1</h1>
<h2>Heading 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.</p>
</div>
</div>
<div class="slide">
<div class="slide-box">
<h1>2</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.</p>
</div>
</div>
<div class="slide">
<div class="slide-box">
<h1>3</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.</p>
</div>
</div>
</div>
<div class="arrow arrow-left"></div>
<div class="arrow arrow-right"></div>
</div>
</div>
I tried giving a height of 500px to the wrapper class but it does not seem to be the best way.
How can I adjust the height of the slider and also keep the content in the middle of the box when I resize the page?
Here mycodepen if needed
Thank you in advance
The padding in the slide style give problems with height:
.slide {
text-align: center;
padding-top: 25%;
background-size: cover;
}
This is my fix to your style to get the right height, I also centered horizontally and vertically the slide-box and the text:
/********For better see the text********/
p{
color:white;
}
h2{
color:white;
}
/**************************************/
.wrapper{
width:100%;
position:relative;
height: 50px;
}
.slide-box {
max-width: 1300px;
margin: 0 auto;
padding: 54px;
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
/**
* Padding is set relative to the width
* of the element, so here padding-top:60% is
* a percentage of the width. This allows us
* to set the height as a ratio of the width
*
*/
.carousel{
width: 100%;
height: 500px;
position: relative;
/* padding-top: 50%; */
overflow: hidden;
}
.inner{
width: 100%;
height: 100%;
position: absolute;
top:0;
left: 0;
}
/**
* ==========================
* Animation styles
*
* Notes:
* 1. We use z-index to position active slides in-front
* of non-active slides
* 2. We set right:0 and left:0 on .slide to provide us with
* a default positioning on both sides of the slide. This allows
* us to trigger JS and CSS3 animations easily
*
*/
.slide{
width: 100%;
height: 500px;
position: absolute;
top:0;
right:0;
left:0;
z-index: 1;
opacity: 0;
}
.slide.active,
.slide.left,
.slide.right{
z-index: 2;
opacity: 1;
}
/**
* ==========================
* JS animation styles
*
* We use jQuery.animate to control the sliding animations
* when CSS3 animations are not available. In order for
* the next slide to slide in from the right, we need
* to change the left:0 property of the slide to left:auto
*
*/
.js-reset-left{left:auto}
/**
* ==========================
* CSS animation styles
*
* .slide.left and .slide.right set-up
* the to-be-animated slide so that it can slide
* into view. For example, a slide that is about
* to slide in from the right will:
* 1. Be positioned to the right of the viewport (right:-100%)
* 2. Slide in when the style is superseded with a more specific style (right:0%)
*
*/
.slide.left{
left:-100%;
right:0;
}
.slide.right{
right:-100%;
left: auto;
}
.transition .slide.left{left:0%}
.transition .slide.right{right:0%}
/**
* The following classes slide the previously active
* slide out of view before positioning behind the
* currently active slide
*
*/
.transition .slide.shift-right{right: 100%;left:auto}
.transition .slide.shift-left{left: 100%;right:auto}
/**
* This sets the CSS properties that will animate. We set the
* transition-duration property dynamically via JS.
* We use the browser's default transition-timing-function
* for simplicity's sake
*
* It is important to note that we are using CodePen's inbuilt
* CSS3 property prefixer. For your own projects, you will need
* to prefix the transition and transform properties here to ensure
* reliable support across browsers
*
*/
.transition .slide{
transition-property: right, left, margin;
}
/**
* ==========================
* Indicators
*
*/
.indicators{
width:100%;
position: absolute;
bottom:0;
z-index: 4;
padding:0;
text-align: center;
}
.indicators li{
width: 13px;
height: 13px;
display: inline-block;
margin: 5px;
background: #fff;
list-style-type: none;
border-radius: 50%;
cursor:pointer;
transition:background 0.3s ease-out;
}
.indicators li.active{background:#93278f}
.indicators li:hover{background-color:#2b2b2b}
/**
* ==========================
* Arrows
*
*/
.arrow{
width: 20px;
height: 20px;
position:absolute;
top:50%;
z-index:5;
border-top:3px solid #fff;
border-right:3px solid #fff;
cursor:pointer;
transition:border-color 0.3s ease-out;
}
.arrow:hover{border-color:#93278f}
.arrow-left{
left:20px;
transform:rotate(225deg);
}
.arrow-right{
right:20px;
transform:rotate(45deg);
}
/**
* ==========================
* For demo purposes only
*
* Please note that the styles below are used
* for the purposes of this demo only. There is no need
* to use these in any of your own projects
*
*/
.slide{
text-align:left;
background-size:cover;
display: table-cell;
vertical-align: middle;
}
h1{
width:100px;
height:100px;
background-color:rgba(146, 45, 141,0.7);
margin:auto;
line-height:100px;
color:#fff;
font-size:2.4em;
border-radius:50%;
text-align: center;
}
.slide:nth-child(1){
background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/163697/slide-1.jpg);
}
.slide:nth-child(2){
background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/163697/slide-2.jpg);
}
.slide:nth-child(3){
background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/163697/slide-3.jpg);
}
Building a Bootstrap template for a responsive site. It needs to show a simple horizontal navbar on desktop and tablet, then go to offcanvas slide-in on phones. Found an example by Phil Hughes (iamphill) on Github. As I adapted this, the dropdown menu items stopped working. When I click on either of the two dropdowns nothing happens. No errors in Chrome Inspector. Validating HTML, CSS and JS does not reveal anything. The bug is either too obvious or too subtle.
! function(t) {
"use strict";
"function" == typeof define && define.amd ? define(["jquery"], t) : "object" == typeof exports ? module.exports = t(require("jquery")) : t(jQuery)
}(function(t) {
"use strict";
function e(e) {
var o = e.attr("data-target");
o || (o = e.attr("href"), o = o && /#[A-Za-z]/.test(o) && o.replace(/.*(?=#[^\s]*$)/, ""));
var n = o && t(o);
return n && n.length ? n : e.parent()
}
function o(o) {
o && 3 === o.which || (t(r).remove(), t(a).each(function() {
var n = t(this),
r = e(n),
a = {
relatedTarget: this
};
r.hasClass("open") && (o && "click" == o.type && /input|textarea/i.test(o.target.tagName) && t.contains(r[0], o.target) || (r.trigger(o = t.Event("hide.bs.dropdown", a)), o.isDefaultPrevented() || (n.attr("aria-expanded", "false"), r.removeClass("open").trigger(t.Event("hidden.bs.dropdown", a)))))
}))
}
function n(e) {
return this.each(function() {
var o = t(this),
n = o.data("bs.dropdown");
n || o.data("bs.dropdown", n = new i(this)), "string" == typeof e && n[e].call(o)
})
}
var r = ".dropdown-backdrop",
a = '[data-toggle="dropdown"]',
d = ".drawer-nav",
i = function(e) {
t(e).on("click.bs.dropdown", this.toggle)
};
i.VERSION = "3.3.5", i.prototype.toggle = function(n) {
var r = t(this);
if (!r.is(".disabled, :disabled")) {
var a = e(r),
i = a.hasClass("open");
if (o(), !i) {
"ontouchstart" in document.documentElement && !a.closest(d).length && t(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(t(this)).on("click", o);
var s = {
relatedTarget: this
};
if (a.trigger(n = t.Event("show.bs.dropdown", s)), n.isDefaultPrevented()) return;
r.trigger("focus").attr("aria-expanded", "true"), a.toggleClass("open").trigger(t.Event("shown.bs.dropdown", s))
}
return !1
}
}, i.prototype.keydown = function(o) {
if (/(38|40|27|32)/.test(o.which) && !/input|textarea/i.test(o.target.tagName)) {
var n = t(this);
if (o.preventDefault(), o.stopPropagation(), !n.is(".disabled, :disabled")) {
var r = e(n),
d = r.hasClass("open");
if (!d && 27 != o.which || d && 27 == o.which) return 27 == o.which && r.find(a).trigger("focus"), n.trigger("click");
var i = " li:not(.disabled):visible a",
s = r.find(".dropdown-menu" + i);
if (s.length) {
var p = s.index(o.target);
38 == o.which && p > 0 && p--, 40 == o.which && p < s.length - 1 && p++, ~p || (p = 0), s.eq(p).trigger("focus")
}
}
}
};
var s = t.fn.dropdown;
t.fn.dropdown = n, t.fn.dropdown.Constructor = i, t.fn.dropdown.noConflict = function() {
return t.fn.dropdown = s, this
}, t(document).on("click.bs.dropdown.data-api", o).on("click.bs.dropdown.data-api", ".dropdown form", function(t) {
t.stopPropagation()
}).on("click.bs.dropdown.data-api", a, i.prototype.toggle).on("keydown.bs.dropdown.data-api", a, i.prototype.keydown).on("keydown.bs.dropdown.data-api", ".dropdown-menu", i.prototype.keydown)
});
// and now js for offcanvas
(function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
(function($, window) {
var Offcanvas, OffcanvasDropdown, OffcanvasTouch, transformCheck;
OffcanvasDropdown = (function() {
function OffcanvasDropdown(element) {
this.element = element;
this._clickEvent = bind(this._clickEvent, this);
this.element = $(this.element);
this.nav = this.element.closest(".nav");
this.dropdown = this.element.parent().find(".dropdown-menu");
this.element.on('click', this._clickEvent);
this.nav.closest('.navbar-offcanvas').on('click', (function(_this) {
return function() {
if (_this.dropdown.is('.shown')) {
return _this.dropdown.removeClass('shown').closest('.active').removeClass('active');
}
};
})(this));
}
OffcanvasDropdown.prototype._clickEvent = function(e) {
if (!this.dropdown.hasClass('shown')) {
e.preventDefault();
}
e.stopPropagation();
$('.dropdown-toggle').not(this.element).closest('.active').removeClass('active').find('.dropdown-menu').removeClass('shown');
this.dropdown.toggleClass("shown");
return this.element.parent().toggleClass('active');
};
return OffcanvasDropdown;
})();
OffcanvasTouch = (function() {
function OffcanvasTouch(button, element, location, offcanvas) {
this.button = button;
this.element = element;
this.location = location;
this.offcanvas = offcanvas;
this._getFade = bind(this._getFade, this);
this._getCss = bind(this._getCss, this);
this._touchEnd = bind(this._touchEnd, this);
this._touchMove = bind(this._touchMove, this);
this._touchStart = bind(this._touchStart, this);
this.endThreshold = 130;
this.startThreshold = this.element.hasClass('navbar-offcanvas-right') ? $("body").outerWidth() - 60 : 20;
this.maxStartThreshold = this.element.hasClass('navbar-offcanvas-right') ? $("body").outerWidth() - 20 : 60;
this.currentX = 0;
this.fade = this.element.hasClass('navbar-offcanvas-fade') ? true : false;
$(document).on("touchstart", this._touchStart);
$(document).on("touchmove", this._touchMove);
$(document).on("touchend", this._touchEnd);
}
OffcanvasTouch.prototype._touchStart = function(e) {
this.startX = e.originalEvent.touches[0].pageX;
if (this.element.is('.in')) {
return this.element.height($(window).outerHeight());
}
};
OffcanvasTouch.prototype._touchMove = function(e) {
var x;
if ($(e.target).parents('.navbar-offcanvas').length > 0) {
return true;
}
if (this.startX > this.startThreshold && this.startX < this.maxStartThreshold) {
e.preventDefault();
x = e.originalEvent.touches[0].pageX - this.startX;
x = this.element.hasClass('navbar-offcanvas-right') ? -x : x;
if (Math.abs(x) < this.element.outerWidth()) {
this.element.css(this._getCss(x));
return this.element.css(this._getFade(x));
}
} else if (this.element.hasClass('in')) {
e.preventDefault();
x = e.originalEvent.touches[0].pageX + (this.currentX - this.startX);
x = this.element.hasClass('navbar-offcanvas-right') ? -x : x;
if (Math.abs(x) < this.element.outerWidth()) {
this.element.css(this._getCss(x));
return this.element.css(this._getFade(x));
}
}
};
OffcanvasTouch.prototype._touchEnd = function(e) {
var end, sendEvents, x;
if ($(e.target).parents('.navbar-offcanvas').length > 0) {
return true;
}
sendEvents = false;
x = e.originalEvent.changedTouches[0].pageX;
if (Math.abs(x) === this.startX) {
return;
}
end = this.element.hasClass('navbar-offcanvas-right') ? Math.abs(x) > (this.endThreshold + 50) : x < (this.endThreshold + 50);
if (this.element.hasClass('in') && end) {
this.currentX = 0;
this.element.removeClass('in').css(this._clearCss());
this.button.removeClass('is-open');
sendEvents = true;
} else if (Math.abs(x - this.startX) > this.endThreshold && this.startX > this.startThreshold && this.startX < this.maxStartThreshold) {
this.currentX = this.element.hasClass('navbar-offcanvas-right') ? -this.element.outerWidth() : this.element.outerWidth();
this.element.toggleClass('in').css(this._clearCss());
this.button.toggleClass('is-open');
sendEvents = true;
} else {
this.element.css(this._clearCss());
}
return this.offcanvas.bodyOverflow(sendEvents);
};
OffcanvasTouch.prototype._getCss = function(x) {
x = this.element.hasClass('navbar-offcanvas-right') ? -x : x;
return {
"-webkit-transform": "translate3d(" + x + "px, 0px, 0px)",
"-webkit-transition-duration": "0s",
"-moz-transform": "translate3d(" + x + "px, 0px, 0px)",
"-moz-transition": "0s",
"-o-transform": "translate3d(" + x + "px, 0px, 0px)",
"-o-transition": "0s",
"transform": "translate3d(" + x + "px, 0px, 0px)",
"transition": "0s"
};
};
OffcanvasTouch.prototype._getFade = function(x) {
if (this.fade) {
return {
"opacity": x / this.element.outerWidth()
};
} else {
return {};
}
};
OffcanvasTouch.prototype._clearCss = function() {
return {
"-webkit-transform": "",
"-webkit-transition-duration": "",
"-moz-transform": "",
"-moz-transition": "",
"-o-transform": "",
"-o-transition": "",
"transform": "",
"transition": "",
"opacity": ""
};
};
return OffcanvasTouch;
})();
window.Offcanvas = Offcanvas = (function() {
function Offcanvas(element) {
var t, target;
this.element = element;
this.bodyOverflow = bind(this.bodyOverflow, this);
this._sendEventsAfter = bind(this._sendEventsAfter, this);
this._sendEventsBefore = bind(this._sendEventsBefore, this);
this._documentClicked = bind(this._documentClicked, this);
this._close = bind(this._close, this);
this._open = bind(this._open, this);
this._clicked = bind(this._clicked, this);
this._navbarHeight = bind(this._navbarHeight, this);
target = this.element.attr('data-target') ? this.element.attr('data-target') : false;
if (target) {
this.target = $(target);
if (this.target.length && !this.target.hasClass('js-offcanvas-done')) {
this.element.addClass('js-offcanvas-has-events');
this.location = this.target.hasClass("navbar-offcanvas-right") ? "right" : "left";
this.target.addClass(transform ? "offcanvas-transform js-offcanvas-done" : "offcanvas-position js-offcanvas-done");
this.target.data('offcanvas', this);
this.element.on("click", this._clicked);
this.target.on('transitionend', (function(_this) {
return function() {
if (_this.target.is(':not(.in)')) {
return _this.target.height('');
}
};
})(this));
$(document).on("click", this._documentClicked);
if (this.target.hasClass('navbar-offcanvas-touch')) {
t = new OffcanvasTouch(this.element, this.target, this.location, this);
}
this.target.find(".dropdown-toggle").each(function() {
var d;
return d = new OffcanvasDropdown(this);
});
this.target.on('offcanvas.toggle', (function(_this) {
return function(e) {
return _this._clicked(e);
};
})(this));
this.target.on('offcanvas.close', (function(_this) {
return function(e) {
return _this._close(e);
};
})(this));
this.target.on('offcanvas.open', (function(_this) {
return function(e) {
return _this._open(e);
};
})(this));
}
} else {
console.warn('Offcanvas: `data-target` attribute must be present.');
}
}
Offcanvas.prototype._navbarHeight = function() {
if (this.target.is('.in')) {
return this.target.height($(window).outerHeight());
}
};
Offcanvas.prototype._clicked = function(e) {
e.preventDefault();
this._sendEventsBefore();
$(".navbar-offcanvas").not(this.target).trigger('offcanvas.close');
this.target.toggleClass('in');
this.element.toggleClass('is-open');
this._navbarHeight();
return this.bodyOverflow();
};
Offcanvas.prototype._open = function(e) {
e.preventDefault();
if (this.target.is('.in')) {
return;
}
this._sendEventsBefore();
this.target.addClass('in');
this.element.addClass('is-open');
this._navbarHeight();
return this.bodyOverflow();
};
Offcanvas.prototype._close = function(e) {
e.preventDefault();
if (this.target.is(':not(.in)')) {
return;
}
this._sendEventsBefore();
this.target.removeClass('in');
this.element.removeClass('is-open');
this._navbarHeight();
return this.bodyOverflow();
};
Offcanvas.prototype._documentClicked = function(e) {
var clickedEl;
clickedEl = $(e.target);
if (!clickedEl.hasClass('offcanvas-toggle') && clickedEl.parents('.offcanvas-toggle').length === 0 && clickedEl.parents('.navbar-offcanvas').length === 0 && !clickedEl.hasClass('navbar-offcanvas')) {
if (this.target.hasClass('in')) {
e.preventDefault();
this._sendEventsBefore();
this.target.removeClass('in');
this.element.removeClass('is-open');
this._navbarHeight();
return this.bodyOverflow();
}
}
};
Offcanvas.prototype._sendEventsBefore = function() {
if (this.target.hasClass('in')) {
return this.target.trigger('hide.bs.offcanvas');
} else {
return this.target.trigger('show.bs.offcanvas');
}
};
Offcanvas.prototype._sendEventsAfter = function() {
if (this.target.hasClass('in')) {
return this.target.trigger('shown.bs.offcanvas');
} else {
return this.target.trigger('hidden.bs.offcanvas');
}
};
Offcanvas.prototype.bodyOverflow = function(events) {
if (events === null) {
events = true;
}
if (this.target.is('.in')) {
$('body').addClass('offcanvas-stop-scrolling');
} else {
$('body').removeClass('offcanvas-stop-scrolling');
}
if (events) {
return this._sendEventsAfter();
}
};
return Offcanvas;
})();
transformCheck = (function(_this) {
return function() {
var asSupport, el, regex, translate3D;
el = document.createElement('div');
translate3D = "translate3d(0px, 0px, 0px)";
regex = /translate3d\(0px, 0px, 0px\)/g;
el.style.cssText = "-webkit-transform: " + translate3D + "; -moz-transform: " + translate3D + "; -o-transform: " + translate3D + "; transform: " + translate3D;
asSupport = el.style.cssText.match(regex);
return _this.transform = asSupport.length !== null;
};
})(this);
return $(function() {
transformCheck();
$('[data-toggle="offcanvas"]').each(function() {
var oc;
return oc = new Offcanvas($(this));
});
$(window).on('resize', function() {
$('.navbar-offcanvas.in').each(function() {
return $(this).height('').removeClass('in');
});
return $('.offcanvas-toggle').removeClass('is-open');
});
return $('.offcanvas-toggle').each(function() {
return $(this).on('click', function(e) {
var el, selector;
if (!$(this).hasClass('js-offcanvas-has-events')) {
selector = $(this).attr('data-target');
el = $(selector);
if (el) {
el.height('');
el.removeClass('in');
return $('body').css({
overflow: '',
position: ''
});
}
}
});
});
});
})(window.jQuery, window);
}).call(this);
/* CSS used here will be applied after bootstrap.css */
#media (max-width: 767px) {
.offcanvas-stop-scrolling {
height: 100%;
overflow: hidden; }
.navbar-default .navbar-offcanvas {
background-color: #f8f8f8; }
.navbar-inverse .navbar-offcanvas {
background-color: #222; }
.navbar-offcanvas {
position: fixed;
width: 100%;
max-width: 250px;
left: -250px;
top: 0;
padding-left: 15px;
padding-right: 15px;
z-index: 999;
overflow: scroll;
-webkit-overflow-scrolling: touch;
-webkit-transition: all 0.15s ease-in;
transition: all 0.15s ease-in; }
.navbar-offcanvas.in {
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); }
.navbar-offcanvas.navbar-offcanvas-fade {
opacity: 0; }
.navbar-offcanvas.navbar-offcanvas-fade.in {
opacity: 1; }
.navbar-offcanvas.offcanvas-transform.in {
-webkit-transform: translateX(250px);
transform: translateX(250px); }
.navbar-offcanvas.offcanvas-position.in {
left: 0; }
.navbar-offcanvas.navbar-offcanvas-right {
left: auto;
right: -250px; }
.navbar-offcanvas.navbar-offcanvas-right.offcanvas-transform.in {
-webkit-transform: translateX(-250px);
transform: translateX(-250px); }
.navbar-offcanvas.navbar-offcanvas-right.offcanvas-position.in {
left: auto;
right: 0; }
.navbar-offcanvas .dropdown.active .caret {
border-top: 0;
border-bottom: 4px solid; }
.navbar-offcanvas .dropdown-menu {
position: relative;
width: 100%;
border: inherit;
box-shadow: none;
-webkit-transition: height 0.15s ease-in;
transition: height 0.15s ease-in; }
.navbar-offcanvas .dropdown-menu.shown {
display: block;
margin-bottom: 10px; } }
.offcanvas-toggle .icon-bar {
background: #000;
-webkit-transition: all .25s ease-in-out;
transition: all .25s ease-in-out; }
.offcanvas-toggle.is-open .icon-bar:nth-child(1) {
-webkit-transform: rotate(45deg) translate(5px, 4px);
transform: rotate(45deg) translate(5px, 4px); }
.offcanvas-toggle.is-open .icon-bar:nth-child(2) {
opacity: 0; }
.offcanvas-toggle.is-open .icon-bar:nth-child(3) {
-webkit-transform: rotate(-45deg) translate(4px, -4px);
transform: rotate(-45deg) translate(4px, -4px); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<body class="body-offcanvas">
<header class="clearfix">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle offcanvas-toggle" data-toggle="offcanvas" data-target="#js-bootstrap-offcanvas">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brandhere</a>
</div>
<div class="navbar-offcanvas navbar-offcanvas-touch" id="js-bootstrap-offcanvas">
<ul class="nav navbar-nav">
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">NUMBERS<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>One</li>
<li>Two</li>
<li>Thirty-six</li>
<li>-7</li>
<li>Eighteen</li>
</ul>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">MUSIC<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>BJ Cole</li>
<li>C. Debussy</li>
<li>Brian Eno</li>
<li>Robert Fripp</li>
<li>Skip James</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<div class="row">
<div>
<h1>Page Title</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin feugiat hendrerit feugiat. In cursus nisl id arcu ullamcorper, eget euismod ante tincidunt. Aliquam tincidunt felis eget quam euismod cursus. Nam aliquet a tellus ut pretium. Pellentesque fermentum nulla tempus mauris sagittis, eget imperdiet quam tristique. Pellentesque quis mauris mauris. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sodales turpis fringilla ligula rutrum, eget mattis justo bibendum. Integer imperdiet mi non cursus bibendum. Nullam vitae cursus justo. Integer quis elit sit amet arcu pellentesque sit amet a sapien. Aliquam tincidunt felis eget quam euismod cursus. Suspendisse lobortis ut elit vitae rhoncus. Ut tincidunt, ante eu egestas sodales, dui nulla aliquet mi, a eleifend lacus risus sit amet lacus.</p>
</div>
</div>
</div>
</body>
Here it is on Bootply http://www.bootply.com/ONyk2E5GWv
There are 2 things here:
1) You're using same class for dropdown-toggle for both Numbers as well as Music. Try to keep it unique like below -
<li class="dropdown numbers">
<a class="dropdown-toggle" data-toggle="numbers" href="#">NUMBERS<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>One</li>
</ul>
</li>
<li class="dropdown music">
<a class="dropdown-toggle" data-toggle="music" href="#">MUSIC<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>BJ Cole</li>
</ul>
</li>
2) You're using CSS Media Query max-width: 767px which means that this styling is applied only for screens whose width are less than 767 pixels, ideally Tablets and Mobile devices. Upon click of dropdown, on the dropdown-menu, 'shown' class is being added which will have the styling of displaying the list by changing the CSS attribute display from 'none' to 'block'
.navbar-offcanvas .dropdown-menu.shown {
display: block;
margin-bottom: 10px;
}
Objective
I'm looking at the .length of each of these positions:
.player--forward, .player--defenseman and .player--goalie to see how many of these players have the class is-selected
A player is selected when a user clicks the btn--add button to add that player to their team.
Once a position reaches the maximum number that can be chosen: two
forwards (pickedF === 2) or three defensemen (pickedD === 3) or
one goalie (pickedG === 1), I'm looking to make it so any players that have do not have a class is-selected unable to be clicked on with "pointer-events:none"
Update #1
Right now, it appears to be counting correctly, but it does not change "pointer-events" to none until after btn-add is clicked because of the nesting of the if-statements and I think that some parts are in the btn-add click function when they don't need to be
scripts.js
function countPlayers(){
$(".player").click(function(){
// Select the current player
var player = $(this);
// Count number of players of each position that have been clicked
var pickedF = $(".player--forward.is-selected").length;
var pickedD = $(".player--defenseman.is-selected").length;
var pickedG = $(".player--goalie.is-selected").length;
// Grab the name of the player last clicked
playerName = player.find(".player__name").text();
// Literally magic.
$(".btn--add").unbind("click");
$(".btn--add").click(function(){
// Ensures names don't match
var spanText = $(".player__pick").eq(0).text();
// Changes the opacity of a picked player to 0.5
player.addClass("is-selected");
if (player.hasClass("player--forward")) {
if (spanText !== playerName) {
$(".player__pick--forward.is-empty").eq(0).html(playerName);
$(".player__pick--forward.is-empty").eq(0).removeClass("is-empty");
if (pickedF < 2) {
pickedF++;
} else if (pickedF === 2) {
$(".player--forward").not(":has(.is-selected)").css("pointer-events", "none");
console.log("Locked forwards");
} else {
$(".player--forward").css("pointer-events", "auto");
}
}
}
if (player.hasClass("player--defenseman")) {
if (spanText !== playerName) {
$(".player__pick--defenseman.is-empty").eq(0).html(playerName);
$(".player__pick--defenseman.is-empty").eq(0).removeClass("is-empty");
// Issue here
if (pickedD < 3) {
pickedD++;
} else if (pickedD === 3) {
$(".player--defenseman").not(":has(.is-selected)").css("pointer-events", "none");
console.log("Locked defensemen");
} else {
$(".player--defenseman").css("pointer-events", "auto");
}
}
}
if (player.hasClass("player--goalie")) {
if (spanText !== playerName) {
$(".player__pick--goalie.is-empty").eq(0).html(playerName);
$(".player__pick--goalie.is-empty").eq(0).removeClass("is-empty");
// Issue here
if (pickedD < 1){
pickedG++;
} else if (pickedG === 1) {
$(".player--goalie").not(":has(.is-selected)").css("pointer-events", "none");
console.log("Locked goalie");
} else {
$(".player--goalie").css("pointer-events", "auto");
}
}
}
console.log(pickedF, pickedD, pickedG);
});
$(".btn--remove").click(function(){
player.removeClass("is-selected");
if (player.hasClass("player--forward")) {
$(".player__pick--forward").eq(0).html("Pick a Forward");
$(".player__pick--forward").eq(0).addClass("is-empty");
}
if (player.hasClass("player--defenseman")) {
$(".player__pick--defenseman").eq(0).html("Pick a Defenseman");
$(".player__pick--defenseman").eq(0).addClass("is-empty");
}
if (player.hasClass("player--goalie")) {
$(".player__pick--goalie").eq(0).html("Pick a Goalie");
$(".player__pick--goalie").eq(0).addClass("is-empty");
}
console.log(pickedF, pickedD, pickedG);
});
});
}
index.html
<div class="popup__text">
<p class="popup__position">tk-position</p>
<p class="popup__name">tk-name</p>
<p class="popup__years">tk-years</p>
<p class="popup__description">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sequi ad dicta sunt unde, sed quae nihil inventore voluptates nulla voluptate laudantium nesciunt quo, aspernatur deleniti quod harum, nisi error doloribus.</p>
<div class="popup__stats">
<p>tk-stats</p>
</div>
<div class="buttons">
<button class="btn--add">Add to team</button>
<button class="btn--remove">Remove from team</button>
</div>
</div>
<div class="player player--bobplager player--defenseman" data-id="11">
<div class="player__info animated">
<p class="player__name">Bob Plager</p>
<p class="player__position">Defenseman</p>
</div>
</div>
<div class="player player--shanahan player--forward" data-id="12">
<div class="player__info animated">
<p class="player__name">Brendan Shanahan</p>
<p class="player__position">Forward</p>
</div>
</div>
<div class="player player--hull player--forward" data-id="13">
<div class="player__info animated">
<p class="player__name">Brett Hull</p>
<p class="player__position ">Forward</p>
</div>
</div>
<div class="player player--elliott player--goalie" data-id="14">
<div class="player__info animated">
<p class="player__name">Brian Elliott</p>
<p class="player__position ">Goalie</p>
</div>
</div>
function countPlayers(){
$(".player").click(function(){
// Select the current player
var player = $(this);
// Count number of players of each position that have been clicked
var pickedF = $(".player--forward.is-selected").length;
var pickedD = $(".player--defenseman.is-selected").length;
var pickedG = $(".player--goalie.is-selected").length;
// Grab the name of the player last clicked
playerName = player.find(".player__name").text();
// Literally magic.
$(".btn--add").unbind("click");
$(".btn--add").click(function(){
// Ensures names don't match
var spanText = $(".player__pick").eq(0).text();
// Changes the opacity of a picked player to 0.5
player.addClass("is-selected");
if (player.hasClass("player--forward")) {
if (spanText !== playerName) {
$(".player__pick--forward.is-empty").eq(0).html(playerName);
$(".player__pick--forward.is-empty").eq(0).removeClass("is-empty");
if (pickedF < 2) {
pickedF++;
}
if (pickedF === 2) {
$(".player--forward").not(":has(.is-selected)").css("pointer-events", "none");
console.log("Locked forwards");
} else {
$(".player--forward").css("pointer-events", "auto");
}
}
}
if (player.hasClass("player--defenseman")) {
if (spanText !== playerName) {
$(".player__pick--defenseman.is-empty").eq(0).html(playerName);
$(".player__pick--defenseman.is-empty").eq(0).removeClass("is-empty");
if (pickedD < 3) {
pickedD++;
}
if (pickedD === 3) {
$(".player--defenseman").not(":has(.is-selected)").css("pointer-events", "none");
console.log("Locked defensemen");
} else {
$(".player--defenseman").css("pointer-events", "auto");
}
}
}
if (player.hasClass("player--goalie")) {
if (spanText !== playerName) {
$(".player__pick--goalie.is-empty").eq(0).html(playerName);
$(".player__pick--goalie.is-empty").eq(0).removeClass("is-empty");
if (pickedG < 1){
pickedG++;
}
if (pickedG === 1) {
$(".player--goalie").not(":has(.is-selected)").css("pointer-events", "none");
console.log("Locked goalie");
} else {
$(".player--goalie").css("pointer-events", "auto");
}
}
}
console.log(pickedF, pickedD, pickedG);
});
$(".btn--remove").click(function(){
player.removeClass("is-selected");
if (player.hasClass("player--forward")) {
$(".player__pick--forward").eq(0).html("Pick a Forward");
$(".player__pick--forward").eq(0).addClass("is-empty");
}
if (player.hasClass("player--defenseman")) {
$(".player__pick--defenseman").eq(0).html("Pick a Defenseman");
$(".player__pick--defenseman").eq(0).addClass("is-empty");
}
if (player.hasClass("player--goalie")) {
$(".player__pick--goalie").eq(0).html("Pick a Goalie");
$(".player__pick--goalie").eq(0).addClass("is-empty");
}
console.log(pickedF, pickedD, pickedG);
});
});
}
I need to set the caret position after DOM element with #id in contenteditable div. In such way that I will be able to continue typing text.
General problem is
get the caret position of specified DOM element (ie. span or div with #id)
set the caret at this position (ie. after this DOM element + be able to write text becouse of focus)
example html structure:
<div id="container" contenteditable="true">
dasidjsaid<div id="el1">sdsad</div>fdfhsdhdsf<div id="el2">sdsad</div>afasf
<div id="el3">test</div><div id="el4">jsj</div> <div id="el5">32</div>sadsa
</div>
Give this a try:
function setToStart(element) {
if(!element) {
return;
}
element.focus();
var range = document.createRange();
range.setStart(element, 0);
range.setEnd(element, 0);
range.collapse(true);
var sel = window.getSelection();
sel.removeAllRanges();
try {
sel.addRange(range);
} catch (e) { }
}
function setToEnd(element) {
element.focus();
var nodeStack = [element];
var node = null;
var lastNode = element;
var charIndex = 0;
while ((node = nodeStack.pop())) {
if (node.nodeType === 3) {
lastNode = node;
charIndex = node.length;
} else {
var i = node.childNodes.length;
while (i--) {
nodeStack.push(node.childNodes[i]);
}
}
}
var range = document.createRange();
range.setStart(lastNode, charIndex);
range.setEnd(lastNode, charIndex);
range.collapse(true);
var sel = window.getSelection();
sel.removeAllRanges();
try {
sel.addRange(range);
} catch (e) { }
}
document.getElementById('setStart').addEventListener('click', function() {
setToStart(document.getElementById('first'));
});
document.getElementById('setEnd').addEventListener('click', function() {
setToEnd(document.getElementById('first'));
});
<div contenteditable="true"><h1>Title</h1><p id="first">Vestibulum id ligula porta felis euismod semper. Curabitur blandit tempus porttitor. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p><p id="second">Nulla vitae elit libero, a pharetra augue. Aenean lacinia bibendum nulla sed consectetur.</p></div>
<button id="setStart">Set to START of first paragraph</button>
<button id="setEnd">Set to END of first paragraph</button>