I am trying to make current number and total number of slides using vue-slick-carousel.
This is what I tried so far.
<VueSlickCarousel ref="carousel">
<div>1 <button tabindex="-1">11</button></div>
<div>2 <button tabindex="-1">22</button></div>
<div>3 <button tabindex="-1">33</button></div>
<div>4<button tabindex="-1">44</button></div>
</VueSlickCarousel>
methods: {
customPaging: function (slider, i) {
var slideNumber = i + 1,
totalSlides = slider.slideCount;
return (
'<a class="custom-dot" role="button" title="' + slideNumber + ' of ' + totalSlides + '"><span class="string">' + slideNumber + '</span></a>'
);
},
},
But this is not working.
And this is vue-slick-carousel API url below.
https://github.com/gs-shop/vue-slick-carousel/blob/master/docs/API.md#methods
What do i need to fixed the code to show a current slide number and total slide.
ex) "3/10"
I had the same problem recently.
This probably comes late, but to whom it may still concern:
If you want to display current page numbers instead of the default dots, there is an example at the bottom of this VueSlickCarousel documentation page and you should be good.
If you want to display the current page number only once anywhere on your page, I found a solution that worked for me:
this.$refs solution did not work for me, but this was likely due to v-if that I was using to render the <VueSlickCarousel>.
v-if and this.$refs don't like each other very much - see also Vue.js refs are undefined, even though this.$refs shows they're there.
Eventually I tried looking at the events that the children emitted in Vue Devtools and I found this afterChange event.
The afterChange event is fired each time you move your carousel to the next page (regardless of whether you drag-slide or click the arrow) and contains a very useful param - the current page index. In my case, this param starts at 0 and for each change it is incremented or decremented by 3 - that is because my carrousel settings are set to slidesToScroll : 3.
So my solution was to:
Add event listener like this:
<VueSlickCarousel #afterChange="afterPageChange">
Create the sliderPageIndex in your data with the initial value 0.
data() {
return {
sliderPageIndex: 0;
}
}
Create the afterPageChange in methods: {}.
methods: {
afterPageChange(page) {
this.sliderPageIndex = page;
}
}
Create the currentPage in computed: {} with some additional logic to compensate for the abovementioned slidesToScroll setting and for the sliderPageIndex starting at 0, like this:
computed: {
currentPage() {
// always display 1 if page index is 0
if (this.sliderPageIndex == 0) {
return 1;
} else {
// compensate for slidesToScroll settings and compensate the shift by 1
return this.sliderPageIndex / this.carouselSettings.slidesToScroll + 1;
}
},
}
Now you should have access to the currentPage computed property and can use it anywhere in your <template>.
When it comes to the totalPages, I compute it from the length of the picture array that I send to the carousel instead of taking it from the carousel directly. Here, I also compensate for carouselSettings - if this requires further explanation, let me know.
You can read more about the VueSlickCarousel events here.
Hope this will be of use to someone! :)
Cheers and have a nice day.
Related
short description of the bug / issue, provide more detail below.
I am building a drag-and-drop quiz app. If a user drags a cloned item ( slick generates cloned items in infinite loop option by default) and drops it at the correct dropzone, I want to remove the dropped item from the carousel based on "data-slick-index" attribute value of the dropped item.
But the "slickRemove" method of Slick Carousel is unable to remove the "slick-cloned" slide + its original slide based on the "click" event on the cloned item or "data-slick-index" attribute value of the cloned item.
====================================================================
[ paste your jsfiddle link here ]
http://jsfiddle.net/anisur5/ehpacfvj/30/
====================================================================
Steps to reproduce the problem
Go to this link: http://jsfiddle.net/anisur5/ehpacfvj/30/
Click on the second dot (•) and Inspect "slide10" which contains
data-slick-index="-1". If you click on it (slide10), Slick js is
unable to delete the clicked item.
It happens whenever I click on
the "slick-cloned" slides.
====================================================================
What is the expected behaviour?
I want slick to remove the clicked item even though it is a "slick-cloned" item.
====================================================================
What is observed behaviour?
Slick's "slickRemove" method can not delete the clicked item if the item is "slick-cloned".
====================================================================
More Details
Which browsers/versions does it happen on? => All
Which jQuery/Slick version are you using? => Latest
Did this work before? => No
Here is the code that slick.js uses to remove slides. I added a comment tag for return false; so that Slick can remove items that come with negetive value in "data-slick-index" attribute( I also tried to remove items based on "data-slick-index" ).
Slick.prototype.removeSlide = Slick.prototype.slickRemove = function(index, removeBefore, removeAll) {
var _ = this;
if (typeof(index) === 'boolean') {
removeBefore = index;
index = removeBefore === true ? 0 : _.slideCount - 1;
} else {
index = removeBefore === true ? --index : index;
}
if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) {
// return false;
}
_.unload();
if (removeAll === true) {
_.$slideTrack.children().remove();
} else {
_.$slideTrack.children(this.options.slide).eq(index).remove();
}
_.$slides = _.$slideTrack.children(this.options.slide);
_.$slideTrack.children(this.options.slide).detach();
_.$slideTrack.append(_.$slides);
_.$slidesCache = _.$slides;
_.reinit();
};
If you add the count of original slides to the negative data-slick-index of the clones, it should give you the index of the original. Only slick does not appear to update that value correctly - so by using that alone, I ended up removing slides with a higher index than the clicked one, when clicking on an original.
Only workaround I could find on the quick, is to store the reference to the slide, on the slide, before the slider gets initialized - then the clones will still refer to the original. Via that reference, you can then find the index of the original in the list of original slides (exclude the clones), and then use that value to remove the slide.
// before slider initialization:
$('.slider div').each(function(i,e) {
$(e).data('self', e);
});
// slider init here
// ...
//Remove slick item based on click.
$(".slider").on("click", ".slick-slide", function() {
var originalSlide = $(this).data('self')
index = $('.slider .slick-slide:not(.slick-cloned)').index(originalSlide);
$(".slider").slick('slickRemove', index);
});
http://jsfiddle.net/1hx5s39z/2/
I have a table with columns of different widths. I use sticky headers for which I have to calculate the column widths.
Now I wrote a function to increase the column width by double clicking the header. This works for the first double click. But if I click on it 4 or 6 times nothing happens after the first double click.
How can I reset the event so that after 2 more clicks the event is triggered again?
When I move the mouse I can do several double clicks one after the other. But that is not the goal.
Here is the code snippet:
<th
v-for="c in data.columns"
v-if="visiblecolumns.includes(c)"
v-on:dblclick="COLUMN_DEFINITION[c]+=50"
:style="{ 'min-width': COLUMN_DEFINITION[c] + 'px', 'max-width': COLUMN_DEFINITION[c] + 'px' }">
{{ c }}
</th>
<th
v-for="c in data.columns"
v-if="visiblecolumns.includes(c)"
#click="changeColumnDefinition"
:style="{ 'min-width': COLUMN_DEFINITION[c] + 'px', 'max-width': COLUMN_DEFINITION[c] + 'px' }">
{{ c }}
</th>
From: vue.js: how to handle click and dblclick events on same element, and as suggested by #JBDouble05
new Vue({
el: '#app',
data: {
counter: 0, // count the clicks
timer: null // Needs to be specified here so it can be accessed on both clicks
},
methods: {
changeColumnDefinition: function(event){
var self = this
this.counter++
if(this.counter == 1) {
this.timer = setTimeout(function() {
// DO NOTHING BUT RESET IN CASE THERES JUST ONE CLICK
self.counter = 0
}, 500); // increase delay as you like
}else{
clearTimeout(this.timer);
// COLUMN_DEFINITION[c]+=50
self.counter = 0;
}
}
}
});
NOTE This goes beyond the question, but:
I would personally wrap this up in a component, since you probably will have more than one header. If you need to call an outside function just use:
this.$emit('someEvent', someValue);
To emit an event and then access it in your component as
<my-awesome-component #someEvent="someFunction"></my-awesome-component>
What you should do is make a modulo variable, and attach an incrementational statement to your v-on:dblclick attribute, that adds one to (increments) the value of a variable, and then, add an event listener in your JavaScript file, and when this happens, perform a modulus operation upon that variable: if it's divisible by two (counter % 2 == 0), then the user has double-clicked twice. If it's not divisible by two (counter % 2 != 0) then they've clicked on it an odd number of times, and you can re-engage the event that occurred when they first double-clicked on it. That was a mouthful, but hopefully you got it, and just ask if you need simplification or further explanation.
I used the slider where i got bug occur. I wanted to show counter pagination on slider but i was unable to do this. In form of Current Number of Page/ Total number of pages like 1/4,2/4 and so on.
https://codepen.io/anon/pen/WJRqQj
<div id="credit"><br>Slide No.<span id="count">1/4</span><br></div>
You can modify the left and right buttons click functions. Also do not forget to update the automatic slider accordingly. I'm also sure you can get the total index somewhere within so that you don't have to hardcode the "/4" part. Update the below functions:
var leftArrow = $('<div>', {'class': 'jislider__left-arrow'}).click(function () {
animate.control(--animate.index);
document.getElementById("count").textContent = animate.index+"/3";
});
var rightArrow = $('<div>', {'class': 'jislider__right-arrow'}).click(function () {
animate.control(++animate.index);
document.getElementById("count").textContent = animate.index+"/3"
});
This will not be enough, you probably should not hardcode the denominator "/4" part as well. I do not know the library you use, but I guess this is sufficient to give you the overall number of "unique" divs with different source:
var x = Array.prototype.slice.call(document.querySelectorAll(".jislider__img"))
.map(function(d,i){return {node:d,url:getComputedStyle(d).backgroundImage}})
.reduce(function(ac,d,i,a){
!ac.some(function(dd,ii){return dd.url === d.url})
? ac.push(d)
: void(0);
return ac
},[]).map(function(d,i){
return d.node;
})
x.length is 3 in your case. So although you have 5 divs, you have 3 images. You can also see it in the dots below (3 dots are there in your carousel). For the left and right arrow functions above, calculate var l = x.length before hand, and then you can do:
document.getElementById("count").textContent = animate.index+"/" + l;
so you don't have to hardcode it. I had to modify your slider a bit, a working fiddle:
https://jsfiddle.net/ibowankenobi/szwr20ec/5/
I have multiple buttons that when they are clicked an image is loaded and the image is supposed to stay there based even when the page refreshes. When I use this the button with the highest setItem value always shows even if I click on other button. How do I fix this?
here is one of the scripts:
<script type="text/javascript">
var isImage1 = sessionStorage.getItem('2');
function showImage1() {
sessionStorage.setItem('isImage1', '2');
$("#loadingImage1").show();
$("#loadingImage").hide();
$("#loadingImage2").hide();
$("#loadingImage3").hide();
$("#loadingImage4").hide();
$("#loadingImage5").hide();
$("#loadingImage6").hide();
}
if(isImage1 == 2) showImage1();
</script>
and here is one of my buttons:
<input name="EPL/MECH DESIGN - TECHS" style="white-space:normal"
onclick="moveText(this.name);showImage1();form1.submit()"
style="width: 275px" type="button" value="7SBD EPL/Mech. Design Techs" />
Update: I have updated this line
var isImage1 = sessionStorage.getItem('2');
to
var isImage1 = sessionStorage.getItem('isIamge1');
but my issue still exists, that the isImage with the largest value stays even when i click the other buttons, so help is still needed.
In your session storage, you are setting the value of the 'isImage1' Item to '2'
sessionStorage.setItem('isImage1', '2');
But in your code to retrieve the value you are actually retrieving the item '2'
var isImage1 = sessionStorage.getItem('2');
You need to change your sessionStorage.getItem to reference 'isImage1'
var isImage1 = sessionStorage.getItem('isImage1');
Then you should get the value you are expecting.
There are loads of good jsfiddles on session storage. you may get some ideas from this one:
http://jsfiddle.net/gabrieleromanato/XLRAH/
Incidently; this is a very small value you are storing, why not store it in a cookie instead?
EDIT:
based on the fact that you have multiple functions exactly like this one, you are better off following Ken's solution, the only thing I would add is a wildcard to turn off the other images:
function showImage(imgNum) {
sessionStorage.setItem('Image',imgNum);
$("[id^=loadingImage]").hide();
$("#loadingImage" + imgNum).show();
}
showImage(sessionStorage.getItem('Image'));
The code in the buttons would then be showImage(1) instead of showImage1();
_Pez
By re-factoring the code a little you can do something like this:
/// setup some vars including max number of images
var maxImages = 6, i = 1, v;
/// now loop through and get the items for each image
for(; i =< maxImages; i++) {
v = sessionStorage.getItem('isImage' + i);
/// if in storage, call show image with the number to show
if (v !== null) showImage(i);
}
/// show image based on number
function showImage(num) {
sessionStorage.setItem('isImage' + num, '1');
$("#loadingImage" + num).show();
}
Also note that sessionStorage only deals with strings. So in order to check a specific number you need to convert it to one first parseInt(value, 10);.
But in this case the 1 that we set can be anything - it's just to store some value so sessionStorage doesn't return null.
In the button code you can change it to do this:
<input name="EPL/MECH DESIGN - TECHS" style="white-space:normal"
onclick="moveText(this.name);showImage(1);form1.submit()"
style="width: 275px" type="button" value="7SBD EPL/Mech. Design Techs" />
I'm trying to get JScrollPane to reinitialize on expand/collapse of my accordion found here. You can demo the accordion by clicking on one of the parents (Stone Tiles, Stone Sinks, Stone Wall Clading, etc).
Right now I set it as a click event using the following JQuery...
var pane = $('.menuwrap')
pane.jScrollPane();
var api = pane.data('jsp');
var i = 1;
$("ul#widget-collapscat-5-top > li.collapsing").click(function() {
$(this).delay(3000);
api.reinitialise();
});
It seems to work when you click the parent the second time, but not the first. I have no idea why but I went into trying to edit the JS for the accordion so that I can add this function when the collapse is complete (as opposed to trying to do this click workaround). The collapse JS can be viewed here.
I tried to add the JS for the reinitialize function here, but I think I'm not doing something properly.
May you point me in the right direction?
Thanks!
The api.reinitialise() is working properly. What is happening is that it updates the size when you click, and at this moment the element is not expanded yet. You may notice that if you expand, colapse and expand again the same section, nothing happens. But if you expand one and then click another one, the ScrollPane will adjust to the size of the first expanded element.
You can solve this with events: place $(this).trigger('colapseComplete') when the colapse ends. Then you can use:
//Listening to the colapseComplete event we triggered above
$("#widget-collapscat-5-top > li.collapsing").on('colapseComplete', function() {
api.reinitialise();
});
Maybe you can alter the addExpandCollapse function to call the reinitialise function at the end of each of its click actions this way :
function addExpandCollapse(id, expandSym, collapseSym, accordion) {
jQuery('#' + id + ' .expand').live('click', function() {
if (accordion==1) {
var theDiv = jQuery(this).parent().parent().find('span.collapse').parent().find('div');
jQuery(theDiv).hide('normal');
jQuery(this).parent().parent().find('span.collapse').removeClass('collapse').addClass('expand');
createCookie(theDiv.attr('id'), 0, 7);
}
jQuery('#' + id + ' .expand .sym').html(expandSym);
expandCat(this, expandSym, collapseSym);
api.reinitialise(); // HERE
return false;
});
jQuery('#' + id + ' .collapse').live('click', function() {
collapseCat(this, expandSym, collapseSym);
api.reinitialise(); // and HERE
return false;
});
}
and to be on a safer side, make sure you have the var api = pane.data('jsp'); line before the above piece of code anywhere in the file.