Type: bug
Platform: all
I have a huge amount of slides, which im trying to display in an ion-slide-box. The problem of course is performance..which im trying to improve with using the following to approach:
Dynamically adding/removing slides, while sliding. So i start with 2 slides. After sliding from slide 1 to 2, im pushing a new slide (3) to the slides array, which is working great.
But (!) i dont want only to add new ones, i want to remove old ones too. So if im trying to remove the first (1) one, after pushing a third (3) one and beeing on the second (2) one, i have to use the $ionicSlideBoxDelegate.update() method within a timeout function.
After the update function gets triggered, im not on second (2) one anymore, it changes the focus to the earlier created third (3) one???
small exmaple here: http://codepen.io/anon/pen/OVjKmY
How can this even be? Any ideas? I cant found what the update method is exactly doing, so i wasn't able to investigate it on code level.
Any help is really appreciated!
Cheers,
AJ
I created a demo of this some time ago
http://codepen.io/mhartington/pen/kFhAp
Does the same thing, but instead of adding/remove the slides, it removes the content in the slides.
It's pretty performant, give it a test.
Is this the correct link? Because you are adding 200 slides directly to the DOM, which isn't what i wanted..
So you want an infinite-scroll-like slide-box? This is something that we have on our minds to make easier for a new version of slidebox. Right now adding and removing the slides is going to be problematic. Marking this for 1.1
Thanks for your reply!
Im just trying to improve the performance of slide-box elements with a huge amount of slides. And one idea was adding and removing slides dynamically, so on the one hand the DOM stays slim and performance is perfect and on the other hand the user has the feeling of an infinite-scroll-box. The funny thing is adding slides at the tail is no problem at all, just removing some from the head leads to errors..
Why is it currently a problem? The update-method is currently doing some magic which is destroying this idea completly. Is there no quick fix? Some dirty stuff, to use until version 1.1 comes out?
What are your release plans (nightly included) for 1.1 or at least this infinite-slide-box?
Thanks in advance!
Are you using shift() to remove the first element of the array? Say you have an array of slides like this
arrayOfSlides = ['1','2','3']
var index = $ionicSlideBoxDelegate.currentIndex() // index = 1
arrayOfSlides[index] // '2'
arrayOfSlides.shift(); // ['2',3']
arrayOfSlides.push('4') // ['2','3','4']
var index = $ionicSlideBoxDelegate.currentIndex() // index = 1
arrayOfSlides[index] // '3'
Now when $ionicSlideBoxDelegate.update() is run it's going to change update the slidebox to the slide at the currentIndex of 1, which is now slide 3 not slide 2.
Perhaps use $ionicSlideBoxDelegate.previous() after using shift() on your array and before using update()
As you can see in my example im using a prototype function of John Resig (Creator of jQuery):
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
I've updated my example using an activeSlide variable to demonstrate where i thing the problem is: http://codepen.io/anon/pen/OVjKmY
activeSlide remains 1 even im setting it to 0 again. So after updating the activeSlide should normally be 0, to be at the first slide again, but it isn't changing/considering this variable while updating..and if you check the DOM the data-index on the ion-slides elements aren't resettet, they are not 0 and 1 again, they are 1 and 2..and after all this magic sliding breaks completly :-1:
And thats why update() is some kind of destroying what im trying to achieve. The only possibility whould be calling previous() AFTER update(), but then it looks awful. And if you check the DOM the two new slides seems to be overlapping :confused: : http://codepen.io/anon/pen/KpXmpW
I have no idea what update() is exactly doing, but its somehow destroying everything :cry:
The update-method of ionSlideBox is actually calling setup under the hood, which is going through the DOM and recalculates all styles.
this.update = function() {
setTimeout(setup);
};
The index always starts at zero. All indices are recalculated based on the DOM. The small timeout is needed to wait for ngRepeat to finish and update the DOM.
I started implementing my own slideBox, but it isn't feature-equivalent.
@mhartington If there are any plans to rework the slideBox directive, I'd like to help. I have put a lot of thinking into this, already. Just point me the trello discussion or something. By the way, Framework7 has a really neat implementation using flexbox.
When its calling the setup method, why isn't it considering active-slide and/or selected? However im really interested in getting this done. Is there any quick fix to achieve what im trying to do?
We were able to implement something like this with three slides in the DOM at any given time. As a full-screen component, the code always keeps the current view in the middle with the previous and next on either side. This 3-element array is rebalanced after each slide change. We also required the ability to bounce at the beginning and end of the data source which prevented using circle as in this example where the data set is truly boundless.
I am not able to share all of the code for this (not terribly difficult, about 150 lines for a directive that manages the slide array in response to swipes and external changes to the selected item) but it did require a few minor changes to ionic.views.Slider that might be relevant to this discussion:
In ionic.views.Slider there is a private speed variable derived from the slider initialization options, and a slideSpeed parameter on the slide function. However, the slide function uses slideSpeed || speed which requires slideSpeed to be a truthy value. Similarly, speed is defined as options.speed || 300. Both of these need to instead test for undefined (or perhaps more robustly reject any non-numeric or negative value). For example, we made the following change to allow a zero slide speed:
slideSpeed = typeof slideSpeed === 'undefined' ? speed : slideSpeed;
Without this ability, it is impossible to change the slides array without flickering the UI, even with a 1-millisecond animation there was a brief flash back to a previous or next slide. If you decide to implement a solution like ours that changes the slides, this is a critical change. Then you can pass zero as the animation speed to the delegate's slide method like so:
scope.slides = adjustedSlides;
slideBoxDelegate.setup();
slideBoxDelegate.slide(currentSlideIndex, 0);
Hey everyone, try the new slider box we just pushed into master that will be available in 1.2 (and soon to replace the existing implementation):
<ion-slides options="options">
<ion-slide-page ng-repeat="slide in slides">
</ion-slide-page>
</ion-slides>
and supply default options:
controller('MyCtrl', function($scope) {
$scope.options = {
loop: true
};
});
this
www/ionic/js/ionic.bundle.js
// set continuous to false if only one slide
if (slides.length < 2) options.continuous = false;
//special case if two slides
if (browser.transitions && options.continuous && slides.length < 3) {
element.appendChild(slides[0].cloneNode(true));
element.appendChild(element.children[1].cloneNode(true));
slides = element.children;
}
comment this lines and its working fine.......
i dont know why the author added this special case in the first place, but he is a great mind to discover this whole thing so he might have anything in his mind,
whatever that may be but the problem is solved and nothing is wrong now after disabling the special case.............
written by : Ajay Mishra and Diljeet Singh @ ajaymshr42 && diljeets1994
As mentioned by my fellow mate ajamshr42, slider will work completely fine with 2 or more slides but in case of only one item in slide, the image wont be displayed, so you can fix that by commenting below mentioned lines only :
//special case if two slides
if (browser.transitions && options.continuous && slides.length < 3) {
element.appendChild(slides[0].cloneNode(true));
element.appendChild(element.children[1].cloneNode(true));
slides = element.children;
}
And don't comment line mentioned below :
if (slides.length < 2) options.continuous = false;
written by : Ajay Mishra and Diljeet Singh @ ajaymshr42 && diljeets1994
Most helpful comment
We were able to implement something like this with three slides in the DOM at any given time. As a full-screen component, the code always keeps the current view in the middle with the previous and next on either side. This 3-element array is rebalanced after each slide change. We also required the ability to bounce at the beginning and end of the data source which prevented using
circleas in this example where the data set is truly boundless.I am not able to share all of the code for this (not terribly difficult, about 150 lines for a directive that manages the slide array in response to swipes and external changes to the selected item) but it did require a few minor changes to
ionic.views.Sliderthat might be relevant to this discussion:Allow zero slide speed
In
ionic.views.Sliderthere is a privatespeedvariable derived from the slider initialization options, and aslideSpeedparameter on theslidefunction. However, theslidefunction usesslideSpeed || speedwhich requires slideSpeed to be a truthy value. Similarly,speedis defined asoptions.speed || 300. Both of these need to instead test forundefined(or perhaps more robustly reject any non-numeric or negative value). For example, we made the following change to allow a zero slide speed:Without this ability, it is impossible to change the slides array without flickering the UI, even with a 1-millisecond animation there was a brief flash back to a previous or next slide. If you decide to implement a solution like ours that changes the slides, this is a critical change. Then you can pass zero as the animation speed to the delegate's
slidemethod like so: