I am interested in talking, as I work on ethercalc.
The big issue I have seen is formula calculation speed. I understand render speed is also an issue. I don't know your use case, but the use cases I see tend to have formulas. It is hard to makes formulas fast enough with JS.
The main speed problems with ethercalc are loading the data from the server and calculating the formulas. I did strip down the code to remove these problems to make web apps work.
Web apps as simple as spreadsheets. My aim is to make it easy to add a UI to a spreadsheet. Spreadsheets often have a UI bottle neck. I have seen many spreadsheets that would be much more valuable to business if it had a UI, as more people could use it. So I added UI formulas to ethercalc http://sheet.cellmaster.com.au/examples
I have literally never seen spreadsheet abbreviated as SS. Spreadsheet is one word. Your comment comes off as trying too hard to be negative. Try some actual constructive feedback why don't ya?
I think a description of why canvas was used would be nice in the README. My (probably naive) view is that browsers are pretty good at table-ish layouts so it’d be great to know why canvas was chosen.
> My (probably naive) view is that browsers are pretty good at table-ish layouts so it’d be great to know why canvas was chosen.
The browser certainly makes this convenient... until you have more than a few thousand cells. At some point even just having the whole table loaded into the DOM is too layout and memory intensive (except on servo, sometimes).
When you try, then, to work around those limitations, continuing to use the DOM for it becomes impractical. This gets especially difficult with a spreadsheet, where row and column size is user defined, and thus a scroll offset is a sum of all of those sizes.
I've done this several times, so I eventually settled on a bucketed, run-length encoded cache of row and column sizes, but keeping this data structure current was a mess. The mess further escalated since eventually I worked on an application where the row and column sizes could change in a different chunk with a network update, and that would need to be reconciled somehow.
Yes, if you can determine the natural height of every preceding row, the position of the next cell is a vector reduction of the previous heights. You still run in to memory limitations though (unless they've produced some incredible magical compaction scheme which can extract hidden classes from DOM structures, which I can't imagine happened without my knowing it since last I looked at tables in IE [spring 2017]).
Dom gives you a lot more though. Hit testing and events, css text alignment and wrapping.
In general, unless you are doing something very simple, replicating the dom and css engine with canvas is an uphill battle.
That being said, I love that the xterm terminal uses a canvas renderer and now going to move to a webgl renderer. Terminal like UI with monospaced fonts are an excellent candidate for low level rendering.
If by table-ish layouts you mean using the <table> element to render something like this then browsers might be OK at it but the <table> woefully inadequate to do anything more than the most basic table renderings. Virtual scrolling or frozen rows/columns is a lot of manual work to do on top of a <table>.
I've tried to do what OP did more than a couple times using native HTML tables (for the same reason you suggest) and I've found it to be nearly impossible. Trying to force a table to keep columns one specific width and not jump around every time you change one of the cells is somewhere between an exercise in futility and not worth the pain. I think OP went the right way here.
What about CSS grid? I did a very basic one https://caub.github.io/misc/sheet without resizable columns, but I believe it'd work more easily than with tables
You make a lot of trade-offs by picking either Canvas or the DOM to render your web app. If you do pick the DOM you will probably abstract out all the DOM operations anyway. But if you pick the Canvas you have to implement everything yourself. With DOM you can do very nice stuff using CSS. The browser (DOM) comes with everything you need "out of the box", but interacting with the DOM, and make it do stuff that are not specified - it will be very "hacky", and you have to deal with different browsers (mobile browsers) working differently.
All DOM update and layout algorithms are O(N) complex (at best). So as less DOM elements you have as more responsive your UI is.
As an ultimate solution - to remove DOM at all and replace it by <canvas>. Minimization of updates is developer's business in this case. Presumably he/she will be able to do it better other than to walk through all DOM elements while handling, say this:
Every DOM cell is a very large object with thousands of properties (most of which a spreadsheet will never use). A cell in a spreadsheet contains a handful of properties and immediate render works much better for less complex layouts (VS Code moved from DOM to Canvas in the terminal because layout performance was better with much less complexity).
Another big reason is wasm. It would be a big performance increase to write the layout engine in Rust/wasm. Native performance would be great.
I’ve often seen this solved by drawing a canvas at at least 2x the viewable size and then using css to force it to be smaller. This is because of retina displays. Very much like images these days. It is often a very easy thing to solve.
The browser has a global for the DPR. If you multiply the reported dimensions by this value and keep the canvas stretched to 100% it should look crisp on any screen.
Yes, but it may be worth effort. See for example this editor: http://evanw.github.io/sky/ and paste there even tens of thousands long text. It will work super smooth, like Sublime Text does.
If only browsers provided low level APIs for text, font calculations and accessbility (what they already support internally), those kind of editors would make a lot of sense.
Sublime Text actually use the "same" * rendering engine (Skia) that is used by browsers (Chrome et.al) for the canvas. So there is no excuse for web based editors to be slow ;)
Nice work! The UI is really good. In my one of the projects, I was looking for excel kind of functionality - and would like to give it a try. But the biggest value IMO excel offers is ability to define formulas. Is there any plans of adding that functionality?
AFAIK (and in evidence in this case) you can't use the normal "find in page" (control-f) when using canvas. Consistency in functions like find is one of the greatest things about the browser, this approach removes it. Probably (!) an implementation will add its own find, which may be better or worse, but as browsers are best thought of as universal information vehicles, it won't automatically fit into accessibility and extension schemes.
You'll basically have to reimplement Ctrl+F yourself regardless of whether you are using canvas or not because if you have say a spreadsheet with fifteen thousand columns and fourty million rows of data then I doubt any browser would be able to handle having all of those elements in the DOM at once. So I don't think that is a compelling argument against canvas.
I remember in a little personal experiment I did you could just set content-editable:true on a table and then add a couple buttons with some js to do things like add rows etc. and you got a decent mini spreadsheet-like UI. Formulas wouldn't work without something special obviously but I remember being surprised with how much was implemented in the browser.
One very neat thing about this approach is that read-only access works without javascript
Generally I agree, however even some DOM-based implementations of spreadsheets (and similar applications with very long lists of things) break "find in page" due to them only rendering visible cells for performance reasons.
For example, Google Sheets hijacks command/control-F to show their own search for this reason.
Google Sheets is a combo. The sheet display is canvas, but a lot of interaction is DOM (and—notably—all text is initially stored in DOM, but then paged out for perf reasons as the above commenter mentions).
That said, X-Spreadsheet does also use DOM for some text interactions at least—seemingly much less so than Google from what I can initially/briefly see though.
Looks very nice. Couple of nitpicks:
1. Tooltips go into a flicker loop when you hover over the tooltip arrow ( the triangle hanging off of the tooltip box ).
2. Dropdowns should close when you click a second time on the dropdown toggle.
scrolling is weird. looks like the canvas is bigger than the window. So when scrolling both the native document/window scrolling is happing and the custom build scrolling of the canvas itself.
I think part of the problem was the canvas is being rendered below native resolution on a retinal display, so the blurry upscaling made it look like a screenshot.
None of the spreadsheet apps I tested have hover styling, but that seems like a violation of basic UX principles. Cells are the primary element of interaction, so I would expect some visual indicator to communicate interactivity (even if it is just the cursor changing).
The speed of the rendering is amazing compared especially to e.g. google sheets. I just informally timed both and gsheets was rendered and editable in 4 seconds whereas this took 0.2 seconds.
However nearly every native UI interaction seems kinda broken. Even entering a value on Firefox doesn't work well. The first letter typed is entered into the cell but then every subsequent letter triggers firefox's fine-in-page (which also doesn't work as others have pointed out). Similarly copy/paste doesn't work, and the context menu (right-click) closes immediately. Maybe it works better in Chrome.
I wonder if there's a case to be made for a hybrid rendering/ui approach here. Rendering could be handled by canvas but native elements swapped in when actual text-editing is invoked?
Cool little demo in any case. I liked some of the simple but effective spreadsheet evaluation code.
It's neat and fast. I do think that you should consider implementing a few more common excel shortcuts, to make it really seamless to an advanced excel user. For instance:
- CTRL ARROWS: to move on the grid to the next populated cell
- F2: edit the first cell of the selected range
- CTR ENTER: applies the content of the first cell of the selected range to the whole range (after you pressed F2 to edit it)
- when edit mode, pressing down arrow should leave edit mode and move to the cell below
- CTR *: select area
- SHIFT SPACE / CTR SPACE: to select a row / column
This is amazing and fast. I'm complaining about it actually being easily broken only because I really wished this worked well, so I could build on it. It crashed for me on literally the very first thing I tried. I opened up the demo page, typed in 4 numbers in a column (in positions a5,a6,a7,a8), then typed "=sum(a5:a8)" in position a9, hit enter, and the demo crashed (with canvas all messed up). There's a traceback in the console log that starts "Uncaught TypeError: Cannot read property 'render' of undefined at cell.js:146". I'm using Chrome 71. I refreshed and tried the same test and it crashed again. There is a test suite (https://github.com/myliang/x-spreadsheet/tree/master/test) but the files have mostly not been touched in four months. In any case, awesome work - please make it even better!
Awesome job so far! This is obviously a monumental undertaking, especially since the quality of spreadsheet software seems mostly correlated with volume of features. This project looks like a great start, with an extensible architecture that will allow the project to eventually attain that "volume of features." I think my favorite line of code is this one, from package.json:
It's a very solid project, also based on canvas, and works (mostly) as advertised, but there are some strange procedures around repo maintenance and releases, and it's a massive dependency bundle. Docs can also out of date or missing information. If you don't require much customization and intend to release it as an internal tool, it will suit your purposes. But anything beyond that, I would look elsewhere. Nothing against adazzle, it's just an old repo and they inherited quite a bit of technical debt.
I've theorized for a while about what it would look like to try and build a generic, app-focused layout engine on Canvas. The DOM gives you lots of things for free and has a long history of backward-compatibility, but both of those things come with huge costs in terms of performance and (to a degree) complexity. The fact that the DOM a) is stateful and b) was originally designed for documents, not apps, causes lots of challenges when what you want to build are apps. The entire reason React exists is to try and force the stateful DOM back into a functional paradigm.
I'd be very curious to learn how generic this project's layout system is.
What you describe is similar to what the flutter developers
are trying to achieve with their web port 'Hummingbird'. Flutter is currently almost entirely aimed at mobile apps, but it would be wonderful to be able to share UI code between apps and web frontend, with a consistent layout model.
This is really interesting!
I've hoped of a scenegraph based web in the past, all rendered in a canvas (indexing can be done by serving a simplified html representation by checking the user agent).
I think the most challenging part is text rendering, but some people have done some work in this area (https://github.com/astiopin/webgl_fonts).
Also, we may need some sort of API to trigger keyboard showing on mobile device.
Anyway, congratulations!
107 comments
[ 0.29 ms ] story [ 147 ms ] thread[1] https://github.com/handsontable/handsontable
[2] https://github.com/audreyt/ethercalc
I am interested in talking, as I work on ethercalc.
The big issue I have seen is formula calculation speed. I understand render speed is also an issue. I don't know your use case, but the use cases I see tend to have formulas. It is hard to makes formulas fast enough with JS.
The main speed problems with ethercalc are loading the data from the server and calculating the formulas. I did strip down the code to remove these problems to make web apps work.
Web apps as simple as spreadsheets. My aim is to make it easy to add a UI to a spreadsheet. Spreadsheets often have a UI bottle neck. I have seen many spreadsheets that would be much more valuable to business if it had a UI, as more people could use it. So I added UI formulas to ethercalc http://sheet.cellmaster.com.au/examples
Eddy.
XSS
probably not the best abbreviation
I thought it was pretty common. I guess it depends on the environment you work in.
The browser certainly makes this convenient... until you have more than a few thousand cells. At some point even just having the whole table loaded into the DOM is too layout and memory intensive (except on servo, sometimes).
When you try, then, to work around those limitations, continuing to use the DOM for it becomes impractical. This gets especially difficult with a spreadsheet, where row and column size is user defined, and thus a scroll offset is a sum of all of those sizes.
I've done this several times, so I eventually settled on a bucketed, run-length encoded cache of row and column sizes, but keeping this data structure current was a mess. The mess further escalated since eventually I worked on an application where the row and column sizes could change in a different chunk with a network update, and that would need to be reconciled somehow.
2 easy to write code
github.com/xspreadsheet used table
In general, unless you are doing something very simple, replicating the dom and css engine with canvas is an uphill battle.
That being said, I love that the xterm terminal uses a canvas renderer and now going to move to a webgl renderer. Terminal like UI with monospaced fonts are an excellent candidate for low level rendering.
As an ultimate solution - to remove DOM at all and replace it by <canvas>. Minimization of updates is developer's business in this case. Presumably he/she will be able to do it better other than to walk through all DOM elements while handling, say this:
You can style them such a way that updates do not cause re-layout, except for auto-sized cells.
Another big reason is wasm. It would be a big performance increase to write the layout engine in Rust/wasm. Native performance would be great.
https://developer.mozilla.org/en-US/docs/Web/API/Window/devi...
In general <canvas> is acceptable for graphics but not for text.
https://www.w3.org/TR/2dcontext/#best-practices
* https://news.ycombinator.com/item?id=11689481
One very neat thing about this approach is that read-only access works without javascript
For example, Google Sheets hijacks command/control-F to show their own search for this reason.
That said, X-Spreadsheet does also use DOM for some text interactions at least—seemingly much less so than Google from what I can initially/briefly see though.
Is there a reason you switched from the earlier version in TypeScript[1] to this version in JavaScript?
[1] https://github.com/myliang/xspreadsheet
This certainly feels interactive when I interact with it like I would any other spreadsheet. Are you unable to select cells and/or type in them?
None of the spreadsheet apps I tested have hover styling, but that seems like a violation of basic UX principles. Cells are the primary element of interaction, so I would expect some visual indicator to communicate interactivity (even if it is just the cursor changing).
However nearly every native UI interaction seems kinda broken. Even entering a value on Firefox doesn't work well. The first letter typed is entered into the cell but then every subsequent letter triggers firefox's fine-in-page (which also doesn't work as others have pointed out). Similarly copy/paste doesn't work, and the context menu (right-click) closes immediately. Maybe it works better in Chrome.
I wonder if there's a case to be made for a hybrid rendering/ui approach here. Rendering could be handled by canvas but native elements swapped in when actual text-editing is invoked?
Cool little demo in any case. I liked some of the simple but effective spreadsheet evaluation code.
- CTRL ARROWS: to move on the grid to the next populated cell
- F2: edit the first cell of the selected range
- CTR ENTER: applies the content of the first cell of the selected range to the whole range (after you pressed F2 to edit it)
- when edit mode, pressing down arrow should leave edit mode and move to the cell below
- CTR *: select area
- SHIFT SPACE / CTR SPACE: to select a row / column
to anyone else wondering: you can browse the available function with the button to the right. ( SUM, AVERAGE, MIN, MAX and CONCAT )
https://exceljet.net/excel-functions/excel-sumproduct-functi...
All I can say is, I am grateful I don’t have to deal with other people’s spreadsheets.
My jam is programming languages and SQL, not obscure formulas and weird constructs made from surprising ways of using them.
> "dependencies": {}
:)
https://tonygermaneri.github.io/canvas-datagrid/
It's a very solid project, also based on canvas, and works (mostly) as advertised, but there are some strange procedures around repo maintenance and releases, and it's a massive dependency bundle. Docs can also out of date or missing information. If you don't require much customization and intend to release it as an internal tool, it will suit your purposes. But anything beyond that, I would look elsewhere. Nothing against adazzle, it's just an old repo and they inherited quite a bit of technical debt.
I'd be very curious to learn how generic this project's layout system is.
This post is a good read: https://medium.com/flutter-io/hummingbird-building-flutter-f...