I'm trying to create a circular progress bar around dots in owl carousel and ClassyLoader (https://andy.su/classyloader/). All fine but I got stuck with this error Cannot read property 'getContext' of undefined.
HTML
<div class="header-slider">
<div class="header-slider-1">
some slider content
</div><!-- .header-slider-1 -->
<div class="header-slider-2">
some slider content
</div><!-- .header-slider-2 -->
</div><!-- .header-slider -->
<div class="owl-dots" id="owldots">
<div class="owl-dot"><canvas class="loader"></canvas><span></span></div>
<div class="owl-dot"><canvas class="loader"></canvas><span></span></div>
</div>
JS
<script type="text/javascript">
/* ------------------------- Owl settings -------------------------- */
jQuery(function($){
$(document).ready(function() {
var timeout = 5000;
var owl = $('.header-slider').owlCarousel({
items: 1,
dots: true,
nav: false,
loop:true,
autoplay: true,
autoplayTimeout: timeout,
dotsContainer: '#owldots',
onChanged: function () {
$(function() {
var loader = $('.header-slider .owl-dot.active .loader').ClassyLoader({
width: 60,
height: 60,
percentage: 100,
speed: 20,
animate: true,
showRemaining: false,
showText: false,
diameter: 20,
lineColor: 'rgba(245,206,12,1)',
lineWidth: 2
});
})
}
});
});
});
</script>
Any idea how can I get this working?
There are several problems with your code, but the most important is: ClassyLoader must be instancied on a canvas, from the page you linked:
Next, you create the canvas element on which you want to trigger the plugin.
Also as I stated in a comment, $(function() { ... }); is an alias to $(document).ready(function() { ... });. And because in your code $ is an alias to jQuery, it can be simplified. I personnally prefer document ready syntax, it's more evident what it does for future readers.
NOTE: you'll see in the corrected codepen that you will probably have additional trouble with the CSS for your slides (they are not showing, probably conflict with owl carousel styles). I arbitrarily chose to set the canvas to fixed because it has to be a separate element and this will make it show upon the slides, but that can be improved. Note also that you need to use owl version 2 because of your syntax (changed your pen settings) and I directly copied ClassyLoader code because it doesn't work from filebin.
corrected code:
HTML:
<canvas class="header-loader"></canvas>
<div class="header-slider">
<div class="header-slider-1">
<p>some slider content 1</p>
</div><!-- .header-slider-1 -->
<div class="header-slider-2">
<p>some slider content 2</p>
</div><!-- .header-slider-2 -->
</div><!-- .header-slider -->
<div class="owl-dots" id="owldots">
<div class="owl-dot"><canvas class="loader"></canvas><span></span></div>
<div class="owl-dot"><canvas class="loader"></canvas><span></span></div>
</div>
JS:
$(document).ready(function() { //you can also use "$(function() {" instead
var timeout = 5000;
var owl = $('.header-slider').owlCarousel({
items: 1,
dots: true,
nav: false,
loop:true,
autoplay: true,
autoplayTimeout: timeout,
dotsContainer: '#owldots',
onChanged: function () {
//don't use "$(function() {" here!
var loader = $('.header-loader').ClassyLoader({ //changed the class
width: 60,
height: 60,
percentage: 100,
speed: 20,
animate: true,
showRemaining: false,
showText: false,
diameter: 20,
lineColor: 'rgba(245,206,12,1)',
lineWidth: 2
});
}
});
});
Related
Main Issue
I am trying to use Swiper within a div that has it's visibility toggled. However, after hiding and showing the div, Swiper does not autoplay - even after triggering mySwiper.Update(), mySwiper.autoplay.start(), with observer and observeParents options set true.
Alternative Solution
Using new Swiper inside the toggle visibility function does work to make it autoplay, but it causes a new set of problems. Dragging doesn't work properly and the autoplay will jump around sporadically.
Code
I created two codepens to demonstrate:
Main (Update & Autoplay)
Alternative (Destroy & Re-create)
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.0/js/swiper.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.0/css/swiper.min.css">
</head>
<style>
.hidden {
display: none;
}
.nav, .swiper-container {
text-align: center;
margin: 10px;
}
</style>
<body>
<div class="nav">
Toggle Hidden
Start Autoplay
</div>
<!-- Swiper parent container -->
<div class="swiper-parent active">
<!-- Slider main container -->
<div class="swiper-container">
<!-- Additional required wrapper -->
<div class="swiper-wrapper">
<!-- Slides -->
<div class="swiper-slide">
<img src='https://cdn.pixabay.com/photo/2019/08/19/07/45/pets-4415649_960_720.jpg' class="slide-image"/>
</div>
<div class="swiper-slide">
<img src='https://cdn.pixabay.com/photo/2019/07/02/08/10/sunny-4311828_960_720.jpg' class="slide-image"/>
</div>
<div class="swiper-slide">
<img src='https://cdn.pixabay.com/photo/2019/08/25/16/57/purple-4429887_960_720.jpg' class="slide-image"/>
</div>
<div class="swiper-slide">
<img src='https://cdn.pixabay.com/photo/2019/02/15/11/04/book-3998252_960_720.jpg' class="slide-image"/>
</div>
</div>
</div>
</div>
<script>
//Swiper Initialization
new Swiper('.swiper-container', {
// Optional parameters
observer: true,
observeParents: true,
loop: true,
loopedSlides: 4,
slidesPerView: 1,
speed: 1800,
autoplay: {
delay: 100,
disableOnInteraction: true,
},
});
var mySwiper = document.querySelector('.swiper-container').swiper;
function startFunction(){
mySwiper.autoplay.start();
};
function toggleHidden(){
if ($('.swiper-parent').hasClass('active')){
$('.swiper-parent').removeClass('active');
$('.swiper-parent').addClass('hidden');
} else {
$('.swiper-parent').removeClass('hidden');
$('.swiper-parent').addClass('active');
mySwiper.update();
mySwiper.autoplay.start();
};
};
</script>
</body>
</html>
Alternative toggle function:
function toggleHidden(){
if ($('.swiper-parent').hasClass('active')){
$('.swiper-parent').removeClass('active');
$('.swiper-parent').addClass('hidden');
mySwiper.destroy();
} else {
$('.swiper-parent').removeClass('hidden');
$('.swiper-parent').addClass('active');
new Swiper('.swiper-container', {
observer: true,
observeParents: true,
loop: true,
loopedSlides: 4,
slidesPerView: 1,
speed: 1800,
autoplay: {
delay: 100,
disableOnInteraction: true,
},
});
var mySwiper = document.querySelector('.swiper-container').swiper;
};
};
I found a solution, though, I am inexperienced so I imagine it is not the best or cleanest way to accomplish this.
Here is the codepen solution
I used this line $("#swiper-parent-id").load(location.href+" #swiper-parent-id>*",""); to reload the div content, causing the instance of Swiper to be destroyed when hiding the div.
Then when showing the div, I created a new instance of Swiper.
This is what I intended to do with the alternative solution, but for some reason this worked, while mySwiper.destroy(); did not work.
EDIT:
Since I posted originally I have gotten mySwiper.destroy(); to work properly. If anyone else is having this problem, it was due to the way I was initializing swiper. It works best to do so in a document.ready function at the end of your body code.
I have BXSlider (https://bxslider.com/) installed. Now I want the following jQuery script to run on entering a "slide".
$(document).ready(function () {
$(".next-prev-nav").fadeTo( "slow", 1 );
$(".disable-slide-nav").hide();
});
(The script enables the navigation of the slider again.)
I tried to search the website of BXslider, but I couldn't find anything about it.
Hope someone can help me out.
You are looking for either onSlideBefore (executes immediately before each slide transition) or onSlideAfter (executes immediately after each slide transition - when transition completes) depending on your needs both can be found here - look at the section Callbacks.
Here is an example:
$(function(){
var slider = $('.bxslider').bxSlider({
mode: 'horizontal',
captions: true,
slideWidth: 600,
auto: true,
pause: 1000,
onSlideBefore: function () {
console.log('onSlideBefore');
// Your code either goes here or...
},
onSlideAfter: function () {
console.log('onSlideAfter');
// Goes here...
// For example lets turn the slider off after the second slide appears
slider.stopAuto();
}
});
});
#import url('https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.12/jquery.bxslider.min.css');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.12/jquery.bxslider.min.js"></script>
<div class="bxslider">
<div><img src="https://bxslider.com/assets/images/coffee1.jpg" title="Funky roots"></div>
<div><img src="https://bxslider.com/assets/images/coffee2.jpg" title="The long and winding road"></div>
<div><img src="https://bxslider.com/assets/images/coffee3.jpg" title="Happy trees"></div>
</div>
I want to use slick.js for a simple news ticker. So I have a box where text is coming from the right and automatically scrolls to the left in a loop. The problem is that slick.js refuses to move the text if there is just one slide. I want the slide to move from the right to the left and after passing the left edge it should start moving from the right again. Does anyone know how to achieve this? Here is a little fiddle showing my problem. It uses this javascript code:
$(function(){
$('.slider').slick({
speed: 10000,
autoplay: true,
autoplaySpeed: 0,
cssEase: 'linear',
slidesToShow: 1,
slidesToScroll: 1,
variableWidth: true,
infinite: true
});
});
Looks like slick carousel isn't built to work with only one element. How about using jQuery to clone your slide once so the plugin works? See functional example below:
$(function() {
if ($('.slider div').length == 1) {
$('.slider div').clone().appendTo('.slider');
}
$('.slider').slick({
speed: 10000,
autoplay: true,
autoplaySpeed: 0,
cssEase: 'linear',
slidesToShow: 1,
slidesToScroll: 1,
variableWidth: true,
infinite: true
});
});
img {
margin: 10px;
border: 1px solid black;
}
<link rel="stylesheet" type="text/css" href="http://kenwheeler.github.io/slick/slick/slick.css">
<link rel="stylesheet" type="text/css" href="http://kenwheeler.github.io/slick/slick/slick-theme.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="http://kenwheeler.github.io/slick/slick/slick.js"></script>
<section class="slider">
<div>
<img src="http://placehold.it/350x150" />
</div>
</section>
Jon's answer is good, but it will give you two same slides which you can slide (change). If you wish to show single slide without cloning, you can use initialSlide setting.
$(function() {
var start = 0;
if ($('.slider div').length == 1) {
start = -1;
}
$('.slider').slick({
speed: 10000,
autoplay: true,
autoplaySpeed: 0,
cssEase: 'linear',
slidesToShow: 1,
slidesToScroll: 1,
variableWidth: true,
infinite: true,
initialSlide: start
});
});
I am currently working on a new project which required a slider. I have implemented slick JS for one of my project.
Now I need to add thumbnails which will appear when we hover the dots which will link to the slider
For example, click on first thumb and slider will advance to first slide,....click on third and slides to third slide.
HTML
<html>
<head>
<title>My Now Amazing Webpage</title>
<link rel="stylesheet" type="text/css" href="slick/slick.css"/>
<link rel="stylesheet" type="text/css" href="slick/style.css"/>
</head>
<body>
<!-- THis is the slider code -->
<div class="center">
<div><img alt="slide 2" src="images/img1.jpg"></div>
<div><img alt="slide 2" src="images/img2.jpg"></div>
<div><img alt="slide 2" src="images/img3.jpg"></div>
<div><img alt="slide 2" src="images/img4.jpg"></div>
<div><img alt="slide 2" src="images/img5.jpg"></div>
</div>
<script type="text/javascript" src="slick/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="slick/jquery-migrate-1.2.1.min.js"></script>
<script type="text/javascript" src="slick/slick.min.js"></script>
<script type="text/javascript">
$('.center').slick({
centerMode: true,
centerPadding: '60px',
slidesToShow: 1,
dots: !0, /* It is for the navigation dots */
draggable: !1,
responsive: [
{
breakpoint: 768,
settings: {
arrows: false,
centerMode: true,
centerPadding: '40px',
slidesToShow: 1
}
},
{
breakpoint: 480,
settings: {
arrows: false,
centerMode: true,
centerPadding: '40px',
slidesToShow: 1
}
}
]
});
</script>
</body>
</html>
You may replace dots with custom thumbnails. You would need to add thumbnails somewhere (for example, in a hidden div inside the image slide wrapper. See the code for reference:
$('.slideme').slick({
dots: true,
customPaging: function(slider, i) {
// this example would render "tabs" with titles
return '<button class="tab">' + $(slider.$slides[i]).find('.slide-title').text() + '</button>';
},
});
You would also need tweak up the native Slick pager css to remove dots and add more space and styles for your thumbnails
add a data attribute to the slide like the bellow
<div class="slide" data-thumb="{{assets}}/images/image-name.jpg"></div>
after that add customPaging function inside the script like bellow
$('.slider').slick({
dots: true,
customPaging: function(slider, i) {
return '<button><span class="thumbImg" style="background-image:url('+$(slider.$slides[i]).data('thumb')+');"></span></button>';
},
});
OK so I have a Jquery plugin that works great and all except it puts all of the images on top of each other until the plugin has finished loading, and then they all go into place. Is there a way to have the first image be a placeholder for the size 843 w 345 h and have it load hidden until they are all ready so my page site doesn't expand down then back up when it has loaded. thanks!
$(window).load(function(){
$('#slide-me').carousel({
style: 'fade',
transitionSpeed: 'slow',
carouselSpeed: 3500,
arrows: true,
buttons: false,
buttonsTheme: 'lines',
stopOnHover: false,
carouselHeight: 'crop',
carouselWidth: 'crop'
});
});
html
<div id="slide-me">
<img src="/tour/images/bigslider1.jpg" />
<img src="/tour/images/bigslider2.jpg" />
<img src="/tour/images/bligslider3.jpg" />
<img src="/tour/images/bligslider4.jpg" />
<img src="/tour/images/bigslider5.jpg" />
</div>
Give it a try, worked for me:
$(function(){
setTimeout(function(){
$('#slide-me').carousel({
style: 'fade',
transitionSpeed: 'slow',
carouselSpeed: 3500,
arrows: true,
buttons: false,
buttonsTheme: 'lines',
stopOnHover: false,
carouselHeight: 'crop',
carouselWidth: 'crop'
});
},500);
});
I actually got the answer for this and wanted to share in case anyone wanted to see it.
In my css all that was needed to do was this
#slide-me img { display: none; }
#slide-me img:first-child { display: block; }
Which allowed the first image to be shown first and hide the rest while script loaded.