nexts / clusterize.js Goto Github PK
View Code? Open in Web Editor NEWTiny vanilla JS plugin to display large data sets easily
Home Page: https://clusterize.js.org
License: MIT License
Tiny vanilla JS plugin to display large data sets easily
Home Page: https://clusterize.js.org
License: MIT License
It'd be nice to be able to specify an offset to indicate where to start in the list (this would also allow someone to scroll up to previous items)
How do you use this within node.js (Specifically electron for desktop applications)?
When I try this I get an error:
require('clusterize.js');
var clusterize = new Clusterize({
rows: data,
scrollId: 'scrollArea',
contentId: 'contentArea'
});
Clusterize is not defined
I am playing with clusterize in Github' s Electron environment and noticed that the row rendering leaks with large amount of data. A reproducible example is at https://github.com/s-a/fileSharp/tree/abc29f2b872bb53f07e5a20cc8c1905dd83f81ac. The repo contains static test data (~8000 list items).
It should start easy with
npm install;
npm run dev;
Then switch to "test-folder" with a double click.
Hi,
I love your plugin!
Is support for horizontal lists planned in a future version?
cheers
olsn
My div list involves inserting new rows above the rest (animated slidein and moving the rest down) yet the plugin only seems to support appending to the bottom of the list.
Would I see a performance hit if I had to insert above myself and call update()
every time?
As i read on http://nexts.github.io/Clusterize.js/
there are some browser limitations:
Browsers limitations !
Although Clusterize allows to use unlimited amount of rows all browsers have height limitations so be aware of that, use wisely and don't go crazy with it.
- Webkit/Blink 134,217,726 px
- Gecko 10,737,418 px
- Trident 17,895,697 px
I also found out, that the limitations for IE seem to be much smaller than in Firefox:
If a DOM node is too high, browsers can not show it correctly. In FireFox, this limitation is 17895697px, in WebKit, 134217726px, both are big enough to contain tens of thousands of rows. But in IE, this limitation is as small as 1342177px. If there are 30000 rows and each row is 50px high, the browser won't be able to show it.
Source: https://github.com/oria/gridx/wiki/How-to-Create-a-Virtually-Scrolling-Gridx
So if one has 50k rows with each of a assumed height of 50px we are very fast at 2.500.000px for the whole height and we might unable to show it.
To solve this, I'd recommend to calculate a full height using top_space and bottom_space and to check if they exceed the maximum available size of around one million pixels.
If they exceed the maximum available height the calculation defines one million pixels as maximum height and uses only a percentual share of the max height for the top_space and the bottom_space.
I think about something like that:
// line 222
var items_start = // ...
top_space = items_start * opts.item_height,
bottom_space = (rows_len - items_end) * opts.item_height,
// ...
// patch to compensate browser limitations
fullHeight = top_space + bottom_space
maxHeight = 1000000; // maximum height for IE
if(fullHeight > maxHeight) {
top_space = Math.round(top_space / fullHeight * maxHeight);
bottom_space = Math.round(bottom_space / fullHeight * maxHeight);
}
// end patch
// and here the normal code line 228:
if(top_space > 0) {
// ...
I am not sure what happens if one has more than one Clusterize Object on a single page with each around one million px height. Would they sum up? Is the height limitation a limitation of rendered dom structures (e.g. for overflow:scroll) or a limitation of the html/body element?
Do you agree with my solution or do you see any problems with this?
Thank you for developing such a great lib. :-)
Scrollable element does not update after load malihu-custom-scrollbar-plugin
Please help me to integrate this one with you awesome library
I would like to integrate this superb plugin (that I was thinking to implement myself for a couple of years now) into my Angular app. I would like to implement infinite scrolling of my page and clusterize would help keeping page DOM lean and responsive.
It likely works with angular, but is there any example which steps one has to take, to make it work? I expect I'll have to call some $scope.$apply()
manually when clusterize changes content, but maybe there are other concerns as well?
Hi,
My table is rendered with a fixed layout.
My cells are all sized with a specific width.
When I scroll down, Clusterize creates the "top-space" row which is an empty tr.
So my browser cannot set the fixed width (the width comes from the first displayed row).
Here is the example : http://jsfiddle.net/kx9fa0se/9/
Thanks for very helpful plugin. Helps me a lot. Please add AMD and CommonJS support in the next update.
Thanks in advance!
It would be nice if the columns in Clusterize table can be reordered by drag and drop. I mean something like DT reorder feature: https://datatables.net/extensions/colreorder/
Regarding to #45 I am setting a selected
row flag on space
key press in the underlying data model and a CSS class of active row DOM element, but I lose the DOM information after (I guess) insertToDOM
was fired.
Because it is time critical to update the whole DOM after space
press I could need to call .update()
without DOM manipulation to refresh selected rows state.
I believe that make sense at a point where blocks_in_cluster
was reached before insertToDOM
acts DOM rendering.
In short what I need could be
.updateData(data) // update data rows without rendering.
.beforeDOMUpdate() // event that fires when blocks_in_cluster was reached.
What do you think?
Hello. I put Clusterize.js on OSSCDN: http://osscdn.com/#/clusterize.js
The service is free for open source projects and updates within 30 minutes when a new version is pushed to master.
Thanks and great work!
I just thought about if it might be possible to define an event before further
data will be appended e.g. using ajax like for paginated data.
E.g. you load page one from a REST service and want to load additional pages when the user scrolls down to the end and before he reaches the end further data will be loaded.
Pseudocode:
// user defined setting
options.percentageScrollOffsetBeforeLoadData = 0.95;
// clusterize
if(options.loadDataCallback()) {
$elementWithScrollbar.on('scroll',function(e) {
percentageScrollOffset = $(this).scrollTop / totalheight;
if(percentageScrollOffset > options.percentageScrollOffsetBeforeLoadData) {
options.loadDataCallback()
}
});
}
This would enable the user to handle additional page loads without manually
injecting in the event handling of clusterize.
Hi,
I try to test it, here is my setup:
<!--HTML-->
<div id="scrollArea" class="clusterize-scroll">
<div id="contentArea" class="clusterize-content">
<div class="clusterize-no-data">Loading data…</div>
</div>
</div>
var i = 1000;
var data = [];
var tmp = [];
while(--i >= 0) {
tmp.length = 0;
tmp.push('<article>')
tmp.push('<h1>Title {{id}}</h1>'.replace('{{id}}', i))
tmp.push('<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Error doloribus est commodi repellat tenetur eveniet quia nisi. Eos repellat ipsam neque veritatis aliquam voluptatem, dolorem distinctio dolore blanditiis dignissimos aperiam.</p>')
tmp.push('</article>')
data.push(tmp.join(''))
}
var clusterize = new Clusterize({
rows: data,
scrollId: 'scrollArea',
contentId: 'contentArea',
rows_in_block: 40
});
document.querySelectorAll('article')
NodeList[161]
I don't understand how to use it, onScroll nothing change. My list contains 160 article, I was thinking it would be 40. What's the problem with my setup ?
I didn't find any quick start readme.
Thanks
Math.ceil(nodes.length / 2)
not works correctly when nodes.length === 1
In the 500.000 rows example the scrollbar fails to properly reach the bottom of the table in Firefox 37 and several elements at the tail end position wrongly due to rounding error. In Internet Explorer 11, content rendering is cut-off halfway down the list.
Browser engines impose hard limits on the maximum size of DOM elements, on a Win7/x64 system these are:
Webkit/Blink | Gecko | Trident |
---|---|---|
134,217,726 px | 10,737,418 px | 17,895,697 px |
Said demo reports a height of 1.78932e+7px
on the computed style of the top spacer element in Firefox, which confirms that you are exceeding that limit.
Cutting the spacer elements up into separate elements may fix Firefox, but will probably not fix IE.
Sadly, the current implementation would have to be redone from scratch to fix this: you cannot use real table markup as that is apparantly always drawn in unison into the same layer, which would still grow to be too tall.
The only way to get this to work is to use an absolutely positioned surface that is super-imposed on top but outside of the element(s) used to stretch the viewport's contents to the desired height.
While scrolling large table, it shows grey screen or black lines or some other contorted picture, sometimes changing left and right part of table. After about 5 seconds after stopped scrolling it shows real picture. It doesn't seem to be smoothly. Hope bug can be found and fixed. Lib is really awesome.
Wouldn't it be better to use something like this?
<script>
function updateContent(source, target){
target.innerHTML = source.scrollTop;
}
</script>
<style>
* {
margin: 0px;
padding: 0px;
border: 0px;
}
.content {
position: absolute;
left: 0px;
top: 0px;
width: 300px;
height: 400px;
background-color: lightgrey;
}
.scrollbar {
position: relative;
left: 0px;
top: 0px;
width: 316px;
height: 400px;
background-color: lightgreen;
overflow-y: scroll;
}
</style>
<div class="scrollbar" onscroll="updateContent(this, this.nextSibling);"><div style="height: 5000px;"></div></div><div class="content">y</div>
Hi, how can I re-init whole table after resizing of the window. Scrolling seems to be broken after resizing whole table because height of the cells is different.
Thanks
Not really an issue, more of a question / feature request. Does this support variable row heights?
The only down side I've seen on the idea is that we can't use CTRL/command + F to locate something in a huge list... Any idea on how to solve this?
Is there an option to always keep top page of items, as users can always hit the Home key? At the moment whole list executes an animated scroll. If list is supposed to be loaded asynchronously, this would make many unnecessary HTTP requests to the server while scrolling would have to be paused. Having top page always loaded could simply jump to the top of the list (and maybe just animate this portion as it should hold more than a visible page of items). but it would definitely prevent HTTP requests.
How should this be solved?
Are you willing to publish via NPM? Since you removed bower version I do not know in which version I am 😄
In case clusterize inits with empty list it could not determine row height.
Previously this case was not reproduced but changes in (v0.9.1)[https://github.com/NeXTs/Clusterize.js/commit/e12e4ce38435fe7010cb9beb7562330573ebc41d#diff-f44ed6ae3a3f46f86f70b186bb38d5ffR209] breaks this.
That's because Math.max(NaN, 0) is NaN
I'm using firefox on windows; scrolling 5000 rows without clusterize is perfectly smooth; with clusterize it's noticably laggy (at a rough estimate say 10fps). Scrolling performance does remain consistent even with lots of rows.
Hey,
when you use something like backbone, it is quite necessary that the backbone view has its DOM Element assigned. Otherwise this.$el end events would not work properly.
How would a change look like, if we supported HTMLElements (not yet in dom) instead of simple strings?
Alternatively, would it be possible to delegate this work to a "callback" for each row? Depends on what is faster. Have you had any experience with HTMLElements or callback functions?
Would be glad if you would give me some hints what I would have to adapt in the code to get it work somehow like that. would pull request it back to you if you like.
We built a way to select rows in our table by clicking on them but we realized that when you resize the DOM gets rerendered and we lose our selected classes. clusterChanged
doesn't seem to fire when this happens. Is there some event or something I can hook into whenever Clusterize rerenders?
It appears that the scroll handoff between clusters inside a large list causes some problems with OS X smooth scrolling. See video: http://d.pr/v/1fQ67
It will be nice to allow data to be populated from existing markup. Say, there is a table with a lot of rows in the markup. Grab the data from the markup and remove it from the DOM tree. Clustrize that table and allow it to render. The page may feel a little slow until it is clustrized, but from there it will be performant again. This will provide a graceful degradation in unsupported browsers/clients. Also, the page will be easy to archive and index in search engines.
I understand that clusterize sets row height when it initializes, but I'm trying to display a list of article excerpts which may have significantly different amount of text in them resulting in significantly variable row height.
I expect this to break scrolling when dummy elements are added at the beginning and at the end of the list when being scrolled.
How does one solve this problem? Apparently Facebook has gotten away with it somehow as it does a similar trick with their feed.
Doing things like this isn't really ideal as it greatly increases the risk of XSS:
var empty_row = '<' + opts.tag + ' class="' + opts.no_data_class + '">';
Have you considered using DOM methods (document.createElement
) instead?
I have a map up top and a table below. The table rows below link to a marker on the map. I want to make this bidirectional. So if you click on a marker it selects a in clusterize and marks it selected. The issue I'm running into is how do I scroll to elements that dont exist yet. Is there a trick to figuring out where a row will be so I know what to scrollTo()
?
I haven't tried it yet but the only other idea I had was to remove height restriction, find the offset of the element, reapply the height, then scrollTo.
Implement useful callbacks:
Hi, Nice job!
This is an amazing plugin and I need to use it into my meteor app, but first I have one question, when this plugin will be available on atmospherejs.com?
Thanks!
I'm currently trying to implement it with React but it doesn't work.
I've tried a bunch of implementations and normally doesn't happen, at all. Just render as always.
Then I try:
var clusterize = new Clusterize({
rows: data,
scrollId: 'scrollArea',
contentId: 'contentArea'
})
Where data
were my custom ReactElements
and I get the following error:
Uncaught TypeError: Cannot read property 'tagName' of undefined
on
Line 173 in 5b4ac69
I don't if it helps, maybe I'm just trying something impossible or doing it totally wrong. Any help is welcomed!
Is it possible to do clusterize table width height of 100% page? I see the only way how to do it? Use absolute positioning of .clusterize-scroll
element. Is there any different workaround for this?
If height of rows not the same then appears emply space.
This is really nice concept, but I think you need to look at https://github.com/Polymer/core-list
demo: https://www.polymer-project.org/0.5/components/core-list/demo.html
If this project will became dependency-free alternative for polymer-core-list it will be awesome.
Didn't see anything to control the render
On your website, if I follow the example ("Follow these easy steps to see the benefits that clusterize.js provides") up to step 4, when clusterize gets initialized, it suddenly cuts the list to 182 entries and then it stops working. Through steps 5 to 8, it stays the same way.
(The same things happends locally with a test size of 1000, it gets cut off at 350).
This happens in Firefox as well as Chrome. The examples below seem to be working fine.
I try to implement an active row cursor on key up and down. For this reason I want to return false in key down to prevent scrolling when the next / previous item is already in view.
I have tried this, but I am missing something here... The algo stumbles on clusterized offset.
View.prototype.isInView = function($elem) {
var id = "scrollArea" + this.id;
var $scrollArea = $('#' + id);
var docViewTop = $scrollArea.scrollTop();
var docViewBottom = docViewTop + $scrollArea.height();
var elemTop = $elem.offset().top;
var elemBottom = elemTop + $elem.height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
};
Can you tell me what I am doing wrong here?
I need it. Some other people need it.
So I added it.
Feature checks for support of forEach
and event listener methods, and converted the NodeList childNodes
to an array manually.
My forEach
substitution is currently only made to provide a direct drop-in replacement for the exact forEach
use-cases in the present code. This means if you want to add something like a context change later, or use the callback arguments as you would expect (aka, (current, index, array)
instead of just (current)
), it can be added to the polyfill pretty easily.
Really only making an issue for tracking purposes though since the PR is already submitted.
Hi, I wanted to use the clusterize.update method but couldn't get it working. How does clusterize know how to format the html based on the objects in the Json data?
https://github.com/NeXTs/Clusterize.js/blob/master/clusterize.js#L131
better would be:
last_cluster = Math.floor(rows.length / (this.options.rows_in_cluster - this.options.rows_in_block));
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.