svelte-tiny-virtual-list + svelte-infinite-loading crashing on page load - infinite-scroll

I have used svelte-infinite-loading, and it worked fine at first,
but as the list got very long, my web app started using substantial amounts of memory, using as much as 2gb.
So, I needed to virtualize this infinite list.
I used svelte-tiny-virtual-list as recommended by svelte-infinite-loading's author:
<script>
....
function onInfinite({ detail }) {
const skip = items !== undefined ? items.length : 0;
fetchItems(skip).then((data) => {
if (data.length === 0) {
items = [];
detail.complete();
return;
}
if (items === undefined) items = data;
else items = [...items, ...data];
detail.loaded();
});
}
onMount(() => {
fetchItems(0).then((data) => {
Items = data;
});
});
</script>
{#if items !== undefined}
{#if items.length === 0}
<p><i>No items found</i></p>
{:else}
<VirtualList
itemCount={items.length}
itemSize={200}
height="100%">
<div slot="item" let:index>
<Item
item={items[index]} />
</div>
<div slot="footer">
<InfiniteLoading on:infinite={onInfinite} />
</div>
</VirtualList>
{/if}
{/if}
The problem comes when the page loads:
The first few items are fetched and displayed correctly, but then the page grows to abnormal lengths, then the list disappears and I get the following error:
InfiniteLoading.svelte:103 executed the callback function more than 10 times for a short time, it looks like searched a wrong scroll wrapper that doest not has fixed height or maximum height, please check it.
What have I done wrong?

A VirtualList creates items until the height of the list exceed the height of the parent. It then fakes a scrollbar to select which items it should render.
Apparently, you have placed the VirtualList in a container without height/max-height and it can't determine how many items it should create.
You have to set a max-height or a height on the parent element.

Related

Clickable listitem in Scrollable Material Ui List while using array in list

I am trying to implement List in material-ui. And i am trying to display randomly generated array of elements, they are being displayed with scrollbar list as i want. But i want to select that particular List Item which is the issue as i m unable to select it, even by using on click. So can anyone help me in this.
Here is my code:
var MuiListElement = React.createClass(
{
handleClick() {
console.log("secondList clicked")
},
render()
{
let faker = require('faker')
let myItems = []
for(let i = 0; i < 5000; i++)
{
let name = faker.Name.findName()
myItems.push(<ListItem onClick={this.handleClick()} key={i.toString()}>{name}</ListItem>)
}
return(
<div style={{width:'400px'}}>
<Paper style={{maxHeight: 200, overflow: 'auto'}}>
<List selectable='true'>
{myItems}
</List>
</Paper>
</div>
)
}
}
)
this.handleClick() calls handleClick function during your render, you should call it when the user clicks the list item. You wan't to pass the function to onClick, not call the function.
myItems.push(
<ListItem
onClick={this.handleClick} //pass function, don't call function
key={i}> //note: you can pass key as number
{name}
</ListItem>)
Now let me predict the future, you would like to know what item was clicked. You can use bind.
myItems.push(
<ListItem
onClick={this.handleClick.bind(this, i)} //bind returns a function
key={i}>
{name}
</ListItem>)
now you know what was passed
handleClick(i) {
console.log("secondList clicked", i)
},
However, every time you render, you are creating a new function and will slightly degrade performance.
See this discussion,
React js onClick can't pass value to method
Let me know if you don't understand.

Protractor scrollleft but class have multiple instance

I have an element with class="objbox" but this attribute have multiple instances.
The current code that I use for scrolling is browser.executeScript('$(".objbox").scrollLeft(' + strPixels + ')'); but since there are multiple instances, it seems like it is getting the first instance and scroll was not successfully done to the target element.
I am wondering if it is possible to include the parent element on my code, or if there is a different work around.
<div class="dhxgrid2-wrapper">
<div class="dhtmlxgrid-container gridbox">
<div class="objbox">
...
</div>
</div>
</div>
It's possible.
What you need to do is the following
// Define the elementfinder of your parent, pick option A or B
const elementFinderWithParentA = $('.dhtmlxgrid-container .objbox');
// Or
const elementFinderWithParentB = $('.dhtmlxgrid-container').$('.objbox');
// The amount to scroll
const scrollLeft = 50;
browser.executeScript('arguments[0].scrollLeft = arguments[1];', elementFinderWithParentA, scrollLeft);
// Or making it more readable, make a function for the scrolling
// and pass it to the browser.executeScript
function scrollToLeft(element, scrollAmount) {
element.scrollLeft = scrollAmount;
}
browser.executeScript(scrollToLeft, elementFinderWithParentA, scrollLeft);
Hope it helps

Customizing fullpage.js to skip section(s) dynamically

The question is simple but i'm not able to make a script by myself for what i need...
I am actually using a script ( fullpage.js ) who toggle some classes into a container ( in my case switching from fp-viewing-1 to fp-viewing-x ) when you scroll down/up between sections.
I need to make a script that listen from this container and toggle a new class into a div ONLY when a class ( in my case fp-viewing-3 ) is added to this container ( from the fullpage.js script of course ).
Any way to make it?
I need to make a script that listen from this container
That's not the way to go for it.
If you want to use the status class, then just create a new class based on the previous ones as explained in this fullpage.js tutorial.
Create a conditional CSS class that will only get applied when its parent class matches your requirement.
Something like this, for example, would only apply the red color to element with myClass when you are in section 1 slide 0.
.fp-viewing-1-0 .myClass{
color: red;
}
Having:
<div id="fullpage">
<div class="section"></div>
<div class="section myClass"></div>
<div class="section"></div>
<div>
If for some other reason (use of plugins etc) you really need to add the class dynamically, then go for fullpage.js callbacks onLeave or afterLoad:
$('#fullpage').fullpage({
onLeave: function(index, nextIndex, direction){
var destination = $('.section').eq(nextIndex - 1);
destination.find('.my-element').addClass('myClass');
}
});
This is the solution to my problem.
Fullpage works as intended except for section 2.
Section 2 will be usable only scrolling down, the script ignore it when scrolling up.
$(document).ready(function() {
$('#application').fullpage({
onLeave: function(index, nextIndex, direction){
var destinationToIgnore = $('.fp-section').hasClass('ignore');
if(destinationToIgnore && direction =='up'){
var destination = nextIndex = 1
$.fn.fullpage.moveTo(destination);
}
},
afterLoad: function(anchorLink, index){
var loadedSection = $(this);
if(index !== 1){
$('.section-intro').removeClass('ignore');
}
if(index == 3){
$('.section-intro').addClass('ignore');
}
}
});
});

How to manage DOM element dependencies

I am trying to create a web-page where some elements (forms and buttons) become visible or are being hidden when some other elements (buttons) are clicked.
I try to find a way to manage this, that is re-usable, and easy to maintain.
My current solution is shown below, but I hope someone has a more elegant solution.
The problem with my own solution is that it will become difficult to read when the number of dependencies increase. It will then also require a lot of editing when I add another button and form.
My current solution is to use an observable to manage the state of the forms, like this:
HTML:
<button id="button-A">Show form A, hide button A and B</button>
<button id="button-B">Show form B, hide button A and B</button>
<form id="form-A">
...this form is initially hidden
...some form elements
<button id="cancel-A">Hide form A, show button A and B</button>
</form>
<form id="form-B">
...this form is initially hidden
...some form elements
<button id="cancel-B">Hide form B, show button A and B</button>
</form>
Dart:
import 'dart:html';
import 'package:observe/observe.dart';
final $ = querySelector;
final $$ = querySelectorAll;
Map<String, bool> toBeObserved = {
"showFormA" : false,
"showFormB" : false
};
// make an observable map
ObservableMap observeThis = toObservable(toBeObserved);
// start managing dependencies
main() {
// add click event to buttons
$('#button-A')
..onClick.listen((E) => observeThis["showFormA"] = true);
$('#button-B')
..onClick.listen((E) => observeThis["showFormB"] = true);
// add click events to form buttons
$('#cancel-A')
..onClick.listen((E) {
E.preventDefault();
E.stopPropagation();
observeThis["showFormA"] = false;
});
$('#cancel-B')
..onClick.listen((E) {
E.preventDefault();
E.stopPropagation();
observeThis["showFormB"] = false;
});
// listen for changes
observeThis.changes.listen((L) {
L.where((E) => E.key == 'showFormA').forEach((R) {
$('#form-A').style.display = (R.newValue) ? 'block' : 'none';
$('#button-A').style.display = (R.newValue || observeThis['showFormB']) ? 'none' : 'inline-block';
$('#button-B').style.display = (R.newValue || observeThis['showFormB']) ? 'none' : 'inline-block';
});
L.where((E) => E.key == 'showFormB').forEach((R) {
$('#form-B').style.display = (R.newValue) ? 'block' : 'none';
$('#button-A').style.display = (R.newValue || observeThis['showFormA']) ? 'none' : 'inline-block';
$('#button-B').style.display = (R.newValue || observeThis['showFormA']) ? 'none' : 'inline-block';
});
});
}
You can use basic CSS to show/hide the elements.
HTML
<div id="container" class="show-buttons">
<button id="button-A" class="btn" data-group="a">...</button>
<button id="button-B" class="btn" data-group="b">...</button>
<form id="form-A" class="form group-a">...</button>
<form id="form-B" class="form group-b">...</button>
</div>
CSS
.btn, .form {
display: none;
}
.show-buttons .btn,
.show-a .form.group-a,
.show-b .form.group-b {
display: block;
}
In Dart just get the data-group (or whatever you want to call this) attribute from the button. Toggle the CSS classes (show-buttons, show-a and show-b) on the container element to switch between the buttons and the specific forms.
This solution is very easy to extend on.
You can use something like this to handle all the elements in a generic way :
final Iterable<ButtonElement> buttons = querySelectorAll('button')
.where((ButtonElement b) => b.id.startsWith('button-'));
final Iterable<ButtonElement> cancels = querySelectorAll('button')
.where((ButtonElement b) => b.id.startsWith('cancel-'));
final Iterable<FormElement> forms = querySelectorAll('form')
.where((FormElement b) => b.id.startsWith('form-'));
buttons.forEach((b) {
b.onClick.listen((e) {
// name of clicked button
final name = b.id.substring(b.id.indexOf('-') + 1);
// hide all buttons
buttons.forEach((b) => b.hidden = true)
// show the good form
querySelector('#form-$name').hidden = false;
});
});
cancels.forEach((b) {
b.onClick.listen((e) {
// show all buttons
buttons.forEach((b) => b.hidden = false);
// hide all forms
forms.forEach((b) => b.hidden = true);
// prevent default
e.preventDefault();
});
});
// hide all form at startup
forms.forEach((f) => f.hidden = true);
You could use polymer's template functionality like
<template if="showA">...
This should work without embedding your elements within Polymer elements too.
This discussion provides some information how to use <template> without Polymer elements.
Using Polymer elements could also be useful.
It all depends on your requirements/preferences.
Angular.dart is also useful for such view manipulation.
If you want to use plain Dart/HMTL I don't have ideas how to simplify your code.

jQuery show div if value > x

I've been reading lots of topics about jQuery and showing div's, but I haven't found the answer to my specific question yet. Here's the thing:
Based on my value I want to show either div A or div B. The select field is filled with 20 countries, of which 19 get the same div (B) and only one get's another div (A). The one that get's div A has "value=1", so I figured to apply a "if select value > 1, show div B" principle. However, I can't manage to get it working. My other select-show-div mechanism was based on the exact value (I've posted it below), but this if-else thing makes me going crazy.
Any help would be appreciated!
My old value=exact code:
$('.div').hide();
$('#country').change(function() {
$('.div').hide();
$('#country' + $(this).val()).show();
});
});
And the corresponding HTML:
<div id="country1" class="div">
BLABLA
</div>
<div id="country2" class="div">
BLABLA
</div>
etc
I don't understand if you have a select menu, or divs. A possible solution could be the following:
$('select').change(function() {
var countryVal = $("select option:selected").val(); //get the value of the selected
$("#country1, #country2").hide(); //hide country divs, of previous selection
if(countryVal == 1) {$("#country1").show();} else {$("#country2").show()}; //if countryVal is 1 (the diffrent value) show the div #country1 else show the div #country2
});
updated Demo: http://jsfiddle.net/YnYxD/1
If I understood correctly, all the others countries have a value > 1, so you can't simply use the value to generate the id. The id must be 1 if the value is 1 and 2 otherwise.
Try :
$('#country').change(function() {
$('.div').hide();
var id = $(this).val() == 1 ? 1 : 2;
$('#country' + id).show();
});
});