
Show HN: X-spreadsheet – A JavaScript canvas spreadsheet for web - myliang
https://github.com/myliang/x-spreadsheet
======
chatmasta
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:

> "dependencies": {}

:)

~~~
myliang
thx

------
williamstein
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](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!

~~~
dartf
It looks like it's case sensitive. Worked for me with "=SUM(A5:A8)"

~~~
y4mi
i was about to say the same thing...

to anyone else wondering: you can browse the available function with the
button to the right. ( SUM, AVERAGE, MIN, MAX and CONCAT )

~~~
selimthegrim
Wonder how much demand there will be for SUMPRODUCT

~~~
codetrotter
For anyone else wondering about that formula.

[https://exceljet.net/excel-functions/excel-sumproduct-
functi...](https://exceljet.net/excel-functions/excel-sumproduct-function)

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.

------
davidy123
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.

~~~
codetrotter
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.

~~~
davidy123
That's true, but I hope people would hesitate before using this for
spreadsheets that don't require virtual rendering.

~~~
c0brac0bra
Good luck finding a full-featured browser grid product that doesn't do virtual
rendering. They all have to, even Google Sheets.

~~~
swiley
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

------
kevsim
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.

~~~
microcolonel
> _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.

~~~
Technetium_Hat
Tables are also extremely performant in internet explorer, where table
rendering is gpu accelerated.

~~~
microcolonel
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]).

------
sramam
This looks really good - the speed of rendering of the default sheet was
surprising and pleasant.

Is there a reason you switched from the earlier version in TypeScript[1] to
this version in JavaScript?

[1]
[https://github.com/myliang/xspreadsheet](https://github.com/myliang/xspreadsheet)

~~~
myliang
Reduce dependency on development processes

------
ryanianian
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.

------
dustingetz
The canvas fonts are fuzzy? Stock OSX and Chrome, 4k display @ 3200 scaled

edit:
[https://github.com/myliang/x-spreadsheet/issues/5](https://github.com/myliang/x-spreadsheet/issues/5)

~~~
c-smile
By nature of <canvas>, it uses grayscale antialiasing of text

Here (MS Edge, Windows, High-DPI screen):

[http://cloud.sciter.com/index.php/s/fcTbout1oQqwIJg](http://cloud.sciter.com/index.php/s/fcTbout1oQqwIJg)

You see how different text rendering in normal DOM rendering (text "Normal")
and the text inside canvas.

Grayscale AA text looks blurred. Grayscale AA works only for relatively large
font sizes, for standard UI text sizes it is highly non-desirable.

~~~
bijection
Although canvas does do grayscale anti-aliasing, this particular app is blurry
because the canvas is being rendered at a lower resolution than your screen.
To make it crisp, the author would have to set the canvas' javascript
canvas.width property to be twice the canvas' css canvas.style.width property.

~~~
c-smile
Yes, oversampling will reduce blurriness but it will be there anyway.
ClearType is there for the purpose.

Yet all that with the price of memory and CPU consumption - number of pixels
to rasterize on 192 PPI monitor is four times of the one with "standard" 96
PPI.

~~~
Avery3R
It's not oversampling, it's native sampling. On high DPI displays browsers
automatically apply a zoom to the page, so the canvas ends up being a smaller
size that gets blown up. You have to detect this and create the canvas bigger
to begin with to counteract this.

------
paulfitz
Nice! Would be interested in how this compares to e.g. handsontable[1]. What
do you think of audreyt's ethercalc[2] myliang?

[1]
[https://github.com/handsontable/handsontable](https://github.com/handsontable/handsontable)

[2]
[https://github.com/audreyt/ethercalc](https://github.com/audreyt/ethercalc)

~~~
myliang
1 canvas performance is higher than dom rendering 2 easy to write code

~~~
eddyparkinson
Formula calculation speed.

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](http://sheet.cellmaster.com.au/examples)

Eddy.

------
eternalny1
This strongly goes against the best practices for Canvas:

[https://www.w3.org/TR/2dcontext/#best-
practices](https://www.w3.org/TR/2dcontext/#best-practices)

~~~
bartq
Yes, but it may be worth effort. See for example this editor:
[http://evanw.github.io/sky/](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.

~~~
z3t4
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 ;)

* [https://news.ycombinator.com/item?id=11689481](https://news.ycombinator.com/item?id=11689481)

------
cm2187
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

------
_bxg1
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.

~~~
rkangel
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 post is a good read: [https://medium.com/flutter-io/hummingbird-building-
flutter-f...](https://medium.com/flutter-io/hummingbird-building-flutter-for-
the-web-e687c2a023a8)

------
kybernetikos
Here's a canvas datagrid that I've come across in case anyone is interested in
the genre:

[https://tonygermaneri.github.io/canvas-
datagrid/](https://tonygermaneri.github.io/canvas-datagrid/)

~~~
chatmasta
Related note, I would warn people to stay away from this one, which I've
hacked around in production for the past year:
[https://github.com/adazzle/react-data-grid](https://github.com/adazzle/react-
data-grid)

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.

------
juretriglav
This is amazing! I'm doing a deep dive into the code now to see how the
extensibility is done.

Some folks here might be interested in Stencila Sheets too
([https://stenci.la/blog/2017-08-features-stencila-
sheets/](https://stenci.la/blog/2017-08-features-stencila-sheets/),
[https://stenci.la/blog/introducing-
sheets/](https://stenci.la/blog/introducing-sheets/)),
[https://github.com/stencila/stencila/tree/develop/src/sheet](https://github.com/stencila/stencila/tree/develop/src/sheet).
It's a web-based spreadsheets where cells can execute other programming
languages, such as R or Python.

Disclaimer: I know the authors. Even so, it's very interesting tech.

~~~
yoz
What's happening with Stencila? I only found it recently, and it looks like a
potentially fantastic project, but development seems to have slowed right
down.

~~~
nokome
Hi yoz, Stencila dev here. Thank for your interest. We're definitely still
around!

Development of the frontend has indeed slowed down while we focus on more
lower-level "backend" tools for research reproduciblity (e.g.
[https://github.com/stencila/dockter](https://github.com/stencila/dockter)).

But were currently recruiting for a frontend designer and an engineer. So will
be definitely be getting back to the interfaces soon!

------
based2
alt: [https://ethercalc.net/](https://ethercalc.net/)

[https://github.com/audreyt/ethercalc](https://github.com/audreyt/ethercalc)

[https://github.com/audreyt/ethercalc/blob/master/LICENSE.txt](https://github.com/audreyt/ethercalc/blob/master/LICENSE.txt)
cpal

[http://livescript.net/](http://livescript.net/) ^CoffeeScript

~~~
eddyparkinson
UI formulas - to build web apps
[http://sheet.cellmaster.com.au/examples](http://sheet.cellmaster.com.au/examples)

I added these :)

------
leonardoeloy
First time I login in 5 years just to say GOOD EFFING JOB!

------
voctor
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](https://github.com/astiopin/webgl_fonts)).
Also, we may need some sort of API to trigger keyboard showing on mobile
device. Anyway, congratulations!

------
Avery3R
In firefox entering a value in a cell for the first time works, but after that
any time you enter a value in a cell it will duplicate the character.

------
barrowclift
Fun concept, but the cell text is blurry to the point of being a distraction
for me, unfortunately. Is this a side effect of rendering to a canvas?

~~~
todd3834
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.

~~~
deckar01
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.

[https://developer.mozilla.org/en-
US/docs/Web/API/Window/devi...](https://developer.mozilla.org/en-
US/docs/Web/API/Window/devicePixelRatio)

------
vdm
[http://mesh-spreadsheet.com/](http://mesh-spreadsheet.com/)

------
crnote
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?

~~~
myliang
will add more formulas in the future

------
deckar01
The cells need to have some kind of hover styling. Without it the demo feels
non-interactive.

~~~
stronglikedan
I'm not sure I've ever seen hover styling in any spreadsheet app, whether
native or online. I think it would detract from the user's focus.

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?

~~~
deckar01
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).

------
nkingsy
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.

~~~
myliang
thx

------
niix
Reminds me a bit of [https://github.com/SheetJS/js-
xlsx](https://github.com/SheetJS/js-xlsx)

------
nwsm
Very slick. Looks incredibly similar to google sheets.

~~~
myliang
yes

------
rayvy
This looks amazing (as everyone else said). Hope this remains somewhat stable
so I/we can build on top of it. 5 stars.

------
airstrike
I really like this and I can see the potential, but I certainly miss being
able to type directly into the cell as opposed to double-clicking on it first.
F2 should also enable editing and toggle between Edit and Enter modes.

It's hard to spend more than a few seconds on the demo when my very first
interaction with it hits a major roadblock like that.

~~~
myliang
input a-z1-9 to edit or F2 or double-clicking

------
tobyhinloopen
It’s abbreviated as “XSS”, lol

------
PretzelFisch
Can this do multiple row per cell? I tried alt + enter and it didn't work.

------
iddan
If you're looking for a simple, light and highly customizable Spreadsheet for
the web checkout React Spreadsheet ([https://www.npmjs.com/package/react-
spreadsheet](https://www.npmjs.com/package/react-spreadsheet)).

------
laszlokorte
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.

------
tianshuo
Breaks easily, to reproduce bug: Put =B1 in A1 and =A1 in B1.

~~~
Schampu
or just B1=B1

------
kovek
Let's render iframes in spreadsheet cells, and only display a selected element
of the page in the iframe. We'll build interfaces that help us deal with
information accross webpages and websites in no time!

------
fareesh
X Spread Sheet

XSS

probably not the best abbreviation

~~~
gordo4
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?

~~~
slantyyz
>> I have literally never seen spreadsheet abbreviated as SS.

I thought it was pretty common. I guess it depends on the environment you work
in.

~~~
myliang
How should the spreadsheet be abbreviated ? 's' first letter

------
xiaodai
no web assembly used. If there is for the underlying calculation engine then
it will be perfect.

------
marknadal
Holy cow this is INCREDIBLE. Thank you.

~ sincerely, super critical HN person. Mind blown.

------
iraldir
Was ready to open it and mock the results of a poor technological choice but
it's actually quite nice!

------
c-smile
Well, <canvas> is not the best tool for doing such things.

<canvas> by its definition is essentially an <img> with its content (pixmap)
modifiable from script side.

Better solution would be for browser to support immediate mode drawing. Like
in my sciter ([https://sciter.com](https://sciter.com)) where you can define
immediate mode painting methods
(Element.paintBackground|Content|Foreground|Outline):

    
    
        var elGrid = …
    
        elGrid.paintBackground = function(gfx) {
          for(var r in ROWS ) 
            gfx.hline(0,r * cellh, width);
          for(var c in COLS ) 
            gfx.vline(c * cellw, 0, height);
        }
    

That paintBackground callback is invoked as a part of WM_PAINT window handler
and with the same Graphics that window uses for rendering the DOM - no
intermediate bitmaps.

Such model requires slightly different Graphics architecture than what is used
by browsers. At least Path, Brush and TextLayout classes need to be added in
order all that to work effectively.

Or to redefine all that on top of WebGL but that will be weird - browsers
already have all 2D primitives (Direct2D, Skia, Cairo) implemented natively.

