狠狠撸

狠狠撸Share a Scribd company logo
EtherCalc

 多人即時
協作試算表
EtherCalc
  for Drupal
 多人即時
協作試算表
仅代表个人立场
只講故事
不講程式
概念
只講故事
不講程式
SheetNode.org
SheetNode.org
SheetNode.org




? npm install -g ethercalc

? ethercalc
 Please connect to: http://0:8000/
?開源應用架構?

EtherCalc.tw


aosabook.org
缘起
VisiCalc, 1979




Dan Bricklin
哈佛商學院, 1977
哈佛商學院, 1977
哈佛商學院, 1977
哈佛商學院, 1977
哈佛商學院, 1977
最初的愿景
最初的愿景




 Alto 工作站
最初的愿景




         Alto 工作站
滑鼠計算機
最初的愿景




         Alto 工作站
滑鼠計算機               頭戴顯示器
最初的愿景




         Alto 工作站
滑鼠計算機               頭戴顯示器
EtherCalc for Drupal
EtherCalc for Drupal
=SUM( )   0
10       20    30

     =SUM( )        60
                    30
                    10
                     0
10       20    30

     =SUM( )        60
                    30
                    10
                     0
1977 → 1978
1977 → 1978
1977 → 1978



       +



  Integer BASIC
1978 → 1979
1978 → 1979
  10      20   30
  =SUM(        )    60
1978 → 1979
    A       B    C    D
1   10      20   30

2   =SUM(        )    60
1978 → 1979
    A     B     C    D
1   10    20    30

2   =SUM(A1,B1,C1)   60
1978 → 1979
    A     B     C    D
1   10    20    30

2   =SUM(A1,B1,C1)   60




                     Bob & Dan
1978 → 1979
         A     B     C    D
     1   10    20    30

     2   =SUM(A1,B1,C1)   60


? 6 年售出 700,000 套

                          Bob & Dan
1978 → 1979
        A     B     C    D
    1   10    20    30

    2   =SUM(A1,B1,C1)   60


? 6 年售出 700,000 套
? 「殺手級應用」的始祖
                         Bob & Dan
1981
EtherCalc for Drupal
EtherCalc for Drupal
EtherCalc for Drupal
EtherCalc for Drupal
EtherCalc for Drupal
二十年来
二十年来
二十年来
二十年来
二十年来


  始終如一
EtherCalc for Drupal
“打不开”
“打不开”
“變亂碼”
“打不开”
“變亂碼”
“有病毒!”
EtherCalc for Drupal
維基百科, 2001
維基百科, 2001
維基百科, 2001
wikiCalc, 2005
wikiCalc, 2005
? 跨伺服器引用數值。
wikiCalc, 2005
? 跨伺服器引用數值。
? 保留每個版本,可隨時回復 。
wikiCalc, 2005
? 跨伺服器引用數值。
? 保留每個版本,可隨時回復 。
? 支援純文字、HTML、Wiki 語法。
wikiCalc, 2005
? 跨伺服器引用數值。
? 保留每個版本,可隨時回復 。
? 支援純文字、HTML、Wiki 語法。
? 開放源碼!
wikiCalc.pl
wikiCalc.pl
       網站
./wkcdata/sites/Foo
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz
wikiCalc.pl
       網站               頁面
./wkcdata/sites/Foo
                        XXX
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz   YYY
                        ZZZ
wikiCalc.pl
       網站               頁面
./wkcdata/sites/Foo
                        XXX
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz   YYY
                        ZZZ


               儲存格
wikiCalc.pl
       網站               頁面
./wkcdata/sites/Foo
                        XXX
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz   YYY
                        ZZZ


               儲存格
    A1: 100
wikiCalc.pl
       網站               頁面
./wkcdata/sites/Foo
                        XXX
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz   YYY
                        ZZZ


               儲存格
    A1: 100
    A2: =A1*2
wikiCalc.pl
       網站                 頁面
./wkcdata/sites/Foo
                          XXX
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz     YYY
                          ZZZ


               儲存格
    A1: 100 B1: =XXX!C1
    A2: =A1*2
wikiCalc.pl
       網站                 頁面
./wkcdata/sites/Foo
                          XXX
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz     YYY
                          ZZZ


               儲存格
    A1: 100 B1: =XXX!C1
    A2: =A1*2
wikiCalc.pl
       網站                   頁面
./wkcdata/sites/Foo
                            XXX
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz       YYY
                            ZZZ


               儲存格
    A1: 100 B1: =XXX!C1
    A2: =A1*2 B2: =YYY!D2
wikiCalc.pl
       網站                   頁面
./wkcdata/sites/Foo
                            XXX
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz       YYY
                            ZZZ


               儲存格
    A1: 100 B1: =XXX!C1
    A2: =A1*2 B2: =YYY!D2
wikiCalc.pl
       網站                   頁面
./wkcdata/sites/Foo
                            XXX
 ./wkcdata/sites/Bar
  ./wkcdata/sites/Baz       YYY
                            ZZZ


               儲存格
    A1: 100 B1: =XXX!C1
    A2: =A1*2 B2: =YYY!D2
                            跨頁引用
wikiCalc 編輯流程
wikiCalc 編輯流程
   A1: 100
   A2: =A1*2
wikiCalc 編輯流程
   A1: 100
   A2: =A1*2
wikiCalc 編輯流程
     A1: 100
     A2: =A1*2


  POST /
  ajaxsetcell=host:page:A1:300
                                 wikicalc.pl
wikiCalc 編輯流程
     A1: 100
     A2: =A1*2


  POST /
  ajaxsetcell=host:page:A1:300
                                    wikicalc.pl
        200 OK
        <?xml version="1.0"?>
        <root><![CDATA[
        A1:v:300:300:right:1:1::
        A2:f:600:A1*2:right:1:1::
        ]]></root>
“载入中…”
“载入中…”
“载入中…”




“C100k” 問題
“载入中…”




“C100k” 問題
EtherCalc for Drupal
打掉重练
打掉重练
SocialCalc, 2006



Dan Bricklin   Ross May?eld
设计目标
设计目标

? 引擎用 JavaScript 重写。
设计目标

? 引擎用 JavaScript 重写。
? 即時編輯及還原/重作。
设计目标

? 引擎用 JavaScript 重写。
? 即時編輯及還原/重作。
? 能處理十萬個儲存格。
系统架构
系统架构
SocialCalc.js




HTTP Server
系统架构
      SocialCalc.js


GET



      HTTP Server
系统架构
      SocialCalc.js


GET



      HTTP Server
系统架构
      SocialCalc.js


GET   GET



      HTTP Server
系统架构
      SocialCalc.js


GET   GET
       ($)



      HTTP Server
系统架构
      SocialCalc.js

                      PUT
GET   GET
       ($)



      HTTP Server
指令设计模式
指令设计模式
set A1 value n 42
指令设计模式
set A1 value n 42
set A2 formula A1*2
指令设计模式
set A1 value n 42
set A2 formula A1*2
merge A1:B2
cut A3
paste A4
sort A1:B9 A up B down
set sheet defaultcolor blue
...
指令设计模式
set A1 value n 42
set A2 formula A1*2

? 背景處理計算。
指令设计模式
set A1 value n 42
set A2 formula A1*2

? 背景處理計算。
? 無限次還原重做。
指令设计模式
set A1 value n 42
set A2 formula A1*2

? 背景處理計算。
? 無限次還原重做。
? 鍵盤滑鼠隨時可用!
“社會化” 試算表
“社會化” 試算表
“社會化” 試算表




 評論、按讚、推薦、
    标记、分享、嵌入...
社会物件   人际连结
社会物件   人际连结
社会物件   人际连结
EtherCalc for Drupal
工
CPAL 通用公共授權
CPAL 通用公共授權
  ?
BSD, MIT
CPAL 通用公共授權
              ?
  ?
BSD, MIT   LGPL, MPL
CPAL 通用公共授權
              ?        ++?
  ?
BSD, MIT   LGPL, MPL   GPL
CPAL 通用公共授權
              ?                                         ++?
  ?
BSD, MIT   LGPL, MPL                                    GPL
               “ASP
?    ”
CPAL 通用公共授權
              ?                                          ++?
  ?
BSD, MIT   LGPL, MPL                                      GPL
               “ASP
?      ”
                                                        Affero GPL
CPAL 通用公共授權
              ?                                          ++?
  ?
BSD, MIT   LGPL, MPL                                      GPL
               “ASP
?      ”

             CPAL                                       Affero GPL
CPAL 通用公共授權
              ?                                          ++?
  ?
BSD, MIT   LGPL, MPL                                      GPL
               “ASP
?      ”

             CPAL                                       Affero GPL
CPAL 通用公共授權
              ?                                          ++?
  ?
BSD, MIT   LGPL, MPL                                      GPL
               “ASP
?      ”

             CPAL                                       Affero GPL
CPAL 通用公共授權
              ?                                          ++?
  ?
BSD, MIT   LGPL, MPL                                      GPL
               “ASP
?      ”

             CPAL                                       Affero GPL
Sheetnode, 2008




Karim Ratib
Sheetnode, 2008
              Views + Fields + CCK




Karim Ratib
Sheetnode, 2008
              Views + Fields + CCK



                  SocialCalc.js


Karim Ratib
Sheetnode, 2008
              Views + Fields + CCK



                  SocialCalc.js


Karim Ratib
Sheetnode, 2008
              Views + Fields + CCK



                  SocialCalc.js


Karim Ratib
Sheetnode, 2008
              Views + Fields + CCK



                  SocialCalc.js


Karim Ratib
Sheetnode, 2008
Sheetnode, 2008
I was looking for an open source
equivalent to Google Docs that
would allow tighter integration
with a company's data:
Sheetnode, 2008
      I was looking for an open source
      equivalent to Google Docs that
      would allow tighter integration
      with a company's data:

    “Real-time reports,
created out of Drupal data.”
SheetNode.org
SheetNode.org
SheetNode.org




Views
OLPC, 2008
OLPC, 2008




Luke Closs  Dan
EtherCalc for Drupal
EtherCalc for Drupal
Mesh
網絡
EtherCalc for Drupal
Manusheel
  Gupta




Vijit Singh
SocialCalcActivity.py
                  Gecko/XPCOM
                 SocialCalc.js
                    XoCom.js

                    XoCom.py



Manusheel
  Gupta




Vijit Singh
SocialCalcActivity.py
                                      Gecko/XPCOM
                                     SocialCalc.js
                                        XoCom.js

              set A1 value n 42         XoCom.py



Manusheel
  Gupta




Vijit Singh
SocialCalcActivity.py
                                      Gecko/XPCOM
                                     SocialCalc.js
                                        XoCom.js

              set A1 value n 42         XoCom.py

                                      D-Bus + Telepathy

Manusheel
  Gupta




Vijit Singh
SocialCalcActivity.py
                                      Gecko/XPCOM
                                     SocialCalc.js
                                        XoCom.js

              set A1 value n 42         XoCom.py

                                      D-Bus + Telepathy
                            OLPC Mesh
Manusheel
  Gupta                      網絡廣播




Vijit Singh
SocialCalcActivity.py
                                            Gecko/XPCOM
                                           SocialCalc.js
                                              XoCom.js

              set A1 value n 42               XoCom.py

                                            D-Bus + Telepathy
                               OLPC Mesh
Manusheel
  Gupta                          網絡廣播
                    D-Bus + Telepathy


                       Gecko/XPCOM
                      SocialCalc.js
                         XoCom.js

                         XoCom.py
Vijit Singh        SocialCalcActivity.py
SocialCalcActivity.py
                                            Gecko/XPCOM
                                           SocialCalc.js
                                              XoCom.js

              set A1 value n 42               XoCom.py

                                            D-Bus + Telepathy
                               OLPC Mesh
Manusheel
  Gupta                          網絡廣播
                    D-Bus + Telepathy


                       Gecko/XPCOM
                                              set A1 value n 42
                      SocialCalc.js
                         XoCom.js

                         XoCom.py
Vijit Singh        SocialCalcActivity.py
很讚,但是...
很讚,但是...

? 漏接訊息無法復原。
很讚,但是...

? 漏接訊息無法復原。
? 編輯同一格時會衝突。
很讚,但是...

? 漏接訊息無法復原。
? 編輯同一格時會衝突。
? 只能在 OLPC 上使用!
YAPC::Tiny, 2009
EV: 事件驅動
Tatsumaki    EV: 事件驅動




 @miyagawa
Tatsumaki  EV: 事件驅動
        Web::Hippie




 @miyagawa   @clkao
Tatsumaki  EV: 事件驅動
        Web::Hippie
                 Feersum



 @miyagawa   @clkao   @stash
WebSocket 同步編輯
     multiserver.pl

      Web::Hippie
         Plack
        Feersum
        EV/libev
WebSocket 同步編輯
  SpreadsheetControl
                        multiserver.pl

                         Web::Hippie
ScheduleScheetCommand
 set A1 value n 2046        Plack
   RenderSheet
                           Feersum
                           EV/libev
WebSocket 同步編輯
  SpreadsheetControl
                            multiserver.pl

                             Web::Hippie
ScheduleScheetCommand
 set A1 value n 2046            Plack
   RenderSheet
                       傳送      Feersum
                               EV/libev
WebSocket 同步編輯
  SpreadsheetControl
                            multiserver.pl


ScheduleScheetCommand
                             Web::Hippie     群播
 set A1 value n 2046            Plack
   RenderSheet
                       傳送      Feersum
                               EV/libev
WebSocket 同步編輯
  SpreadsheetControl
                            multiserver.pl


ScheduleScheetCommand
                             Web::Hippie     群播
 set A1 value n 2046            Plack
                                             ScheduleScheetCommand
   RenderSheet
                       傳送      Feersum         set A1 value n 2046
                                                 (isRemote = true)
                               EV/libev
                                                   RenderSheet
新增功能
新增功能

?斷線重連可以復原。
新增功能

?斷線重連可以復原。
?顯示別人的游標位置。
新增功能

?斷線重連可以復原。
?顯示別人的游標位置。
?可以在各平台上運行!
新增功能

?斷線重連可以復原。
?顯示別人的游標位置。
?可以在各平台上運行!
更讚了,但是...
更讚了,但是...

? 要相信誰的目前狀態?
更讚了,但是...

? 要相信誰的目前狀態?
? 所有人離線:資料消失?
更讚了,但是...

? 要相信誰的目前狀態?
? 所有人離線:資料消失?
? 重新连接:回播所有指令?
更讚了,但是...

? 要相信誰的目前狀態?
? 所有人離線:資料消失?
? 重新连接:回播所有指令?
EtherCalc for Drupal
打掉重练
打掉重练
YAPC::NA, 2006
YAPC::NA, 2006
“I think, but I cannot prove, that by
the next year JavaScript 2.0 will
bootstrap itself, complete self
hosting, compile back to JavaScript,
and replace Ruby as the Next Big
Thing in all environments. ”
YAPC::NA, 2006
YAPC::NA, 2006
“JavaScript will become the common
backend for all dynamic languages,
and so you can write Perl to run in the
browser, on the server, and inside
databases, all with the same set of
development tools. ”
YAPC::NA, 2006
YAPC::NA, 2006
“Because, as we all know,
worse is better, so the worst
scripting language is doomed
to become the best.”
YAPC::NA, 2006
“Because, as we all know,
worse is better, so the worst
scripting language is doomed
to become the best.”

      劣即是夯
EtherCalc for Drupal
EtherCalc for Drupal
EtherCalc for Drupal
JavaScript: 缺點減少
JavaScript: 缺點減少
 Co?eeScript: 標點減半
  cs = (js) - js/2


 Jeremy
Ashkenas
JavaScript: 缺點減少
 Co?eeScript: 標點減半
  cs = (js) - js/2


 Jeremy
Ashkenas
JavaScript: 缺點減少
 Co?eeScript: 標點減半
  cs = (js) - js/2

           “原 JavaScript 行數: 22k。
            重寫過的 Co?eeScript 行數: 5k。
            {async, jsdom, zappa, optimist etc}++”
 Jeremy
Ashkenas
EtherCalc for Drupal
{x,y} = @offset
{x,y} = @offset
var offset = this.offset;
{x,y} = @offset
var offset = this.offset;
var x = offset.x;
{x,y} = @offset
var offset = this.offset;
var x = offset.x;
var y = offset.y;
{x,y} = @offset
var offset = this.offset;
var x = offset.x;
var y = offset.y;

           js2coffee.org
COSCUP, 2011
COSCUP, 2011
COSCUP, 2011




hack
?hack
?hack
?...
COSCUP, 2011




hack
?hack
?hack
?...
EtherCalc 系统架构
EtherCalc 系统架构
      main.co?ee
 sc.co?ee
                 Socket.io
SocialCalc.js
 SocialCalc.js
                 Express
                 Node.js
 db.co?ee        EV/libuv
   redis.js       Zappa
EtherCalc 系统架构
      main.co?ee
 sc.co?ee
                 Socket.io
SocialCalc.js
 SocialCalc.js
                 Express
                 Node.js
 db.co?ee        EV/libuv
   redis.js       Zappa



  Redis
 (optional)
EtherCalc 系统架构
      main.co?ee
 sc.co?ee
                 Socket.io
SocialCalc.js
 SocialCalc.js
                 Express
                 Node.js
 db.co?ee        EV/libuv    player.co?ee
   redis.js       Zappa       SocialCalc.js
                              SocialCalc.js




  Redis
 (optional)
EtherCalc 系统架构
      main.co?ee
 sc.co?ee                    GET snapshot
                 Socket.io
SocialCalc.js
 SocialCalc.js               LRANGE log
                 Express
                 Node.js
 db.co?ee        EV/libuv    player.co?ee
   redis.js       Zappa       SocialCalc.js
                              SocialCalc.js




  Redis
 (optional)
EtherCalc 系统架构
      main.co?ee
 sc.co?ee                     GET snapshot
                 Socket.io
SocialCalc.js
 SocialCalc.js                LRANGE log
                 Express
                 Node.js
 db.co?ee        EV/libuv     player.co?ee
   redis.js       Zappa        SocialCalc.js
                               SocialCalc.js



                             RPUSH log cmd
  Redis
 (optional)
EtherCalc 系统架构
      main.co?ee
 sc.co?ee                     GET snapshot
                 Socket.io
SocialCalc.js
 SocialCalc.js                LRANGE log
                 Express
                 Node.js
 db.co?ee        EV/libuv     player.co?ee
   redis.js       Zappa        SocialCalc.js
                               SocialCalc.js



                             RPUSH log cmd
  Redis
 (optional)
EtherCalc 系统架构
      main.co?ee
 sc.co?ee                     GET snapshot
                 Socket.io
SocialCalc.js
 SocialCalc.js                LRANGE log
                 Express
                 Node.js
 db.co?ee        EV/libuv     player.co?ee
   redis.js       Zappa        SocialCalc.js
                               SocialCalc.js



                             RPUSH log cmd
  Redis
 (optional)
EtherCalc 系统架构
      main.co?ee
 sc.co?ee                    GET snapshot
                 Socket.io
SocialCalc.js
 SocialCalc.js               LRANGE log
                 Express
                 Node.js
 db.co?ee        EV/libuv    player.co?ee
   redis.js       Zappa       SocialCalc.js
                              SocialCalc.js




  Redis            DEL log RPUSH log cmd
 (optional)        SET snapshot snapshot
跨页即时更新
跨页即时更新

伺
服
端
跨页即时更新

伺            客
服            戶
端            端
跨页即时更新
      ask.log: XXX


伺                    客
服                    戶
端                    端
跨页即时更新
               ask.log: XXX


伺   log: XXX,snapshot,log
                              客
服                             戶
端                             端
跨页即时更新
               ask.log: XXX


伺   log: XXX,snapshot,log
                              客
            execute: set A1
服            formula YYY!B2   戶
端                             端
跨页即时更新
               ask.log: XXX


伺   log: XXX,snapshot,log
                              客
            execute: set A1
服            formula YYY!B2   戶
    recalc: YYY,snapshot
端                             端
跨页即时更新
               ask.log: XXX


伺   log: XXX,snapshot,log
                              客
            execute: set A1
服            formula YYY!B2   戶
    recalc: YYY,snapshot
端   recalc: YYY,snapshot
                              端
跨页即时更新
               ask.log: XXX


伺   log: XXX,snapshot,log
                              客
            execute: set A1
服            formula YYY!B2   戶
    recalc: YYY,snapshot
端   recalc: YYY,snapshot
                              端
    recalc: YYY,snapshot
REST 資源界面
REST 資源界面
GET /_/page
PUT /_/page
REST 資源界面
GET /_/page   POST /_/page
PUT /_/page    {commands:[…]}
REST 資源界面
GET /_/page   POST /_/page
PUT /_/page    {commands:[…]}


   GET /_/page/cells/A1
   PUT /_/page/cells/B2
EtherCalc for Drupal
+   =
+   =

+   = Coco
+   =

       +   = Coco

Coco   +   =
EtherCalc for Drupal
stove.on(heat, function() {
stove.on(heat, function() {
    pot.on(boil, function() {
stove.on(heat, function() {
    pot.on(boil, function() {
        rice.on(ready, function(dish) {
stove.on(heat, function() {
    pot.on(boil, function() {
        rice.on(ready, function(dish) {
            setTimeout(function() {
stove.on(heat, function() {
    pot.on(boil, function() {
        rice.on(ready, function(dish) {
            setTimeout(function() {
                dish.serve();
            }, 60000);
stove.on(heat, function() {
    pot.on(boil, function() {
        rice.on(ready, function(dish) {
            setTimeout(function() {
                dish.serve();
            }, 60000);
        });
    });
});
stove.on(heat, function() {
    pot.on(boil, function() {
        rice.on(ready, function(dish) {
            setTimeout(function() {
                dish.serve();
            }, 60000);
        });
    });
});
stove.on(heat, function() {
    pot.on(boil, function() {
        rice.on(ready, function(dish) {
            setTimeout(function() {
                dish.serve();
            }, 60000);
        });
    });
});
EtherCalc for Drupal
stove.on heat, -
stove.on heat, -
    pot.on boil, -
stove.on heat, -
    pot.on boil, -
        rice.on ready, (dish) -
stove.on heat, -
    pot.on boil, -
        rice.on ready, (dish) -
            setTimeout(
stove.on heat, -
    pot.on boil, -
        rice.on ready, (dish) -
            setTimeout(
                - dish.serve()
stove.on heat, -
    pot.on boil, -
        rice.on ready, (dish) -
            setTimeout(
                - dish.serve()
                60000
stove.on heat, -
    pot.on boil, -
        rice.on ready, (dish) -
            setTimeout(
                - dish.serve()
                60000
            )
stove.on heat, -
    pot.on boil, -
        rice.on ready, (dish) -
            setTimeout(
                - dish.serve()
                60000
            )
EtherCalc for Drupal
- stove.on heat
- stove.on heat
- pot.on   boil
- stove.on heat
- pot.on   boil
dish - rice.on ready
- stove.on heat
- pot.on   boil
dish - rice.on ready
- (`setTimeout` 60000)
- stove.on heat
- pot.on   boil
dish - rice.on ready
- (`setTimeout` 60000)
dish.serve!
- stove.on heat
- pot.on   boil
dish - rice.on ready
- (`setTimeout` 60000)
dish.serve!
OSDC.tw, 2012
OSDC.tw, 2012
OSDC.tw, 2012
OSDC.tw, 2012
哪来的「高风亮节」…
哪来的「高风亮节」…

只是沒寫過
Drupal 模組。
EtherCalc for Drupal
雖然 Isis 架過
許多 Drupal 網站
我也幫忙改了一些…
雖然 Isis 架過
許多 Drupal 網站
我也幫忙改了一些…
雖然 Isis 架過
許多 Drupal 網站
我也幫忙改了一些…
雖然 Isis 架過
許多 Drupal 網站
我也幫忙改了一些…
可是我對架構

完全沒有概念。
可是我對架構

完全沒有概念。
EtherCalc for Drupal
?開源之樂?, 2012. 7. 1.
?開源之樂?, 2012. 7. 1.
?開源之樂?, 2012. 7. 1.
?開源之樂?, 2012. 7. 1.


     “內容過於抽象。”
?開源之樂?, 2012. 7. 1.


     “內容過於抽象。”
     “這跟 Drupal
      到底有何關係?”
EtherCalc for Drupal
2012. 7. 2.
2012. 7. 2.
“你還是把
EtherCalc
 for Drupal
  寫出來,
比較有意義。”
2012. 7. 2.
“你還是把
EtherCalc
 for Drupal
  寫出來,
比較有意義。”
2012. 7. 2.
“你還是把
EtherCalc
 for Drupal
  寫出來,
比較有意義。”
EtherCalc for Drupal
2012. 7. 3.
2012. 7. 3.

感謝 Karim 幫忙
2012. 7. 3.

 感謝 Karim 幫忙

 一個早上
 就寫完了。
/**
 *
 * Implements hook_menu().
 *
 * In sheetnode_ethercalc_menu.info:
 *    configure = admin/config/content/sheetnode/ethercalc
 *
 */

function sheetnode_ethercalc_menu() {
  array('admin/config/content/sheetnode/ethercalc' = array(
    'title'            = 'EtherCalc',
    'access arguments' = array('administer site configuration'),
    'page callback'    = 'drupal_get_form',
    'page arguments'   = array('_sheetnode_ethercalc_settings'),
    'description'      = 'Administer settings for EtherCalc.',
    'type'             = MENU_LOCAL_TASK,
  ));
}
/**
 *
 * Implements hook_menu().
 *
 * In sheetnode_ethercalc_menu.info:
 *    configure = admin/config/content/sheetnode/ethercalc
 *
 */

function sheetnode_ethercalc_menu() {
  array('admin/config/content/sheetnode/ethercalc' = array(
    'title'            = 'EtherCalc',
    'access arguments' = array('administer site configuration'),
    'page callback'    = 'drupal_get_form',
    'page arguments'   = array('_sheetnode_ethercalc_settings'),
    'description'      = 'Administer settings for EtherCalc.',
    'type'             = MENU_LOCAL_TASK,
  ));
}
/**
  * Implements hook_sheetnode_plugins().
  */
function sheetnode_ethercalc_sheetnode_plugins(
   $value, $save_element, $context
) {
   // Only turn on Ethercalc if we're editing the node.
   if (!empty($save_element)) {
     $ethercalc_host = variable_get('sheetnode_ethercalc_host', '');
     $ethercalc_port = variable_get('sheetnode_ethercalc_port', '8000');
     $ethercalc_path = …;
     drupal_add_js($ethercalc_path . '/socket.io/socket.io.js#');
     drupal_add_js($ethercalc_path . '/zappa/zappa.js#');
     drupal_add_js($ethercalc_path . '/static/md5.js#');
     drupal_add_js($ethercalc_path . '/player/broadcast.js#');
     drupal_add_js($ethercalc_path . '/player/main.js#');
   }
}
/**
  * Implements hook_sheetnode_plugins().
  */
function sheetnode_ethercalc_sheetnode_plugins(
   $value, $save_element, $context
) {
   // Only turn on Ethercalc if we're editing the node.
   if (!empty($save_element)) {
     $ethercalc_host = variable_get('sheetnode_ethercalc_host', '');
     $ethercalc_port = variable_get('sheetnode_ethercalc_port', '8000');
     $ethercalc_path = …;
     drupal_add_js($ethercalc_path . '/socket.io/socket.io.js#');
     drupal_add_js($ethercalc_path . '/zappa/zappa.js#');
     drupal_add_js($ethercalc_path . '/static/md5.js#');
     drupal_add_js($ethercalc_path . '/player/broadcast.js#');
     drupal_add_js($ethercalc_path . '/player/main.js#');
   }
}
EtherCalc for Drupal
2012. 7. 4.
2012. 7. 4.

More Related Content

Similar to EtherCalc for Drupal (16)

igdshare 110220: LuaJIT intro
igdshare 110220: LuaJIT introigdshare 110220: LuaJIT intro
igdshare 110220: LuaJIT intro
igdshare
?
手把手教你把痴颈尘改装成一个滨顿贰编程环境(图文)
手把手教你把痴颈尘改装成一个滨顿贰编程环境(图文)手把手教你把痴颈尘改装成一个滨顿贰编程环境(图文)
手把手教你把痴颈尘改装成一个滨顿贰编程环境(图文)
King Hom
?
Groovy Introduction for Java Programmer
Groovy Introduction for Java ProgrammerGroovy Introduction for Java Programmer
Groovy Introduction for Java Programmer
Li Ding
?
from Source to Binary: How GNU Toolchain Works
from Source to Binary: How GNU Toolchain Worksfrom Source to Binary: How GNU Toolchain Works
from Source to Binary: How GNU Toolchain Works
National Cheng Kung University
?
美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术沙龙05 - 前后端联调方案探索与应用美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术团队
?
使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會
使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會
使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會
Johnny Sung
?
IoTDB Quick Start
IoTDB Quick StartIoTDB Quick Start
IoTDB Quick Start
JialinQiao
?
爲何開源 why open source
爲何開源 why open source爲何開源 why open source
爲何開源 why open source
Kenson Chou
?
fis
fisfis
fis
fansekey
?
顿2冲狈辞诲别在淘宝的应用实践
顿2冲狈辞诲别在淘宝的应用实践顿2冲狈辞诲别在淘宝的应用实践
顿2冲狈辞诲别在淘宝的应用实践
Jackson Tian
?
搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流
jondynet
?
搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流
bj
?
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
OpenFoundry
?
深入浅出Netty l.t
深入浅出Netty   l.t深入浅出Netty   l.t
深入浅出Netty l.t
oleone
?
Android C Library: Bionic 成長計畫
Android C Library: Bionic 成長計畫Android C Library: Bionic 成長計畫
Android C Library: Bionic 成長計畫
Kito Cheng
?
igdshare 110220: LuaJIT intro
igdshare 110220: LuaJIT introigdshare 110220: LuaJIT intro
igdshare 110220: LuaJIT intro
igdshare
?
手把手教你把痴颈尘改装成一个滨顿贰编程环境(图文)
手把手教你把痴颈尘改装成一个滨顿贰编程环境(图文)手把手教你把痴颈尘改装成一个滨顿贰编程环境(图文)
手把手教你把痴颈尘改装成一个滨顿贰编程环境(图文)
King Hom
?
Groovy Introduction for Java Programmer
Groovy Introduction for Java ProgrammerGroovy Introduction for Java Programmer
Groovy Introduction for Java Programmer
Li Ding
?
美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术沙龙05 - 前后端联调方案探索与应用美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术团队
?
使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會
使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會
使用 Kong 與 GitOps 來管理您企業的 API 呼叫 @ 2024 台灣雲端大會
Johnny Sung
?
IoTDB Quick Start
IoTDB Quick StartIoTDB Quick Start
IoTDB Quick Start
JialinQiao
?
爲何開源 why open source
爲何開源 why open source爲何開源 why open source
爲何開源 why open source
Kenson Chou
?
顿2冲狈辞诲别在淘宝的应用实践
顿2冲狈辞诲别在淘宝的应用实践顿2冲狈辞诲别在淘宝的应用实践
顿2冲狈辞诲别在淘宝的应用实践
Jackson Tian
?
搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流
jondynet
?
搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流
bj
?
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
OpenFoundry
?
深入浅出Netty l.t
深入浅出Netty   l.t深入浅出Netty   l.t
深入浅出Netty l.t
oleone
?
Android C Library: Bionic 成長計畫
Android C Library: Bionic 成長計畫Android C Library: Bionic 成長計畫
Android C Library: Bionic 成長計畫
Kito Cheng
?

More from Audrey Tang (20)

Social Innovation & Digital Transformation
Social Innovation & Digital TransformationSocial Innovation & Digital Transformation
Social Innovation & Digital Transformation
Audrey Tang
?
Stories from the Future of Democracy
Stories from the Future of DemocracyStories from the Future of Democracy
Stories from the Future of Democracy
Audrey Tang
?
TEDxTaipei 2017: 社會企業
TEDxTaipei 2017: 社會企業TEDxTaipei 2017: 社會企業
TEDxTaipei 2017: 社會企業
Audrey Tang
?
唐凤政务委员业务工作报告
唐凤政务委员业务工作报告唐凤政务委员业务工作报告
唐凤政务委员业务工作报告
Audrey Tang
?
資訊服務採購契約範本 修正明細對照 1060713
資訊服務採購契約範本 修正明細對照 1060713資訊服務採購契約範本 修正明細對照 1060713
資訊服務採購契約範本 修正明細對照 1060713
Audrey Tang
?
服務型智慧政府推動計畫 v9
服務型智慧政府推動計畫 v9服務型智慧政府推動計畫 v9
服務型智慧政府推動計畫 v9
Audrey Tang
?
共通性应用程式介面规范
共通性应用程式介面规范共通性应用程式介面规范
共通性应用程式介面规范
Audrey Tang
?
打造一站式的防救灾资讯整合平臺
打造一站式的防救灾资讯整合平臺打造一站式的防救灾资讯整合平臺
打造一站式的防救灾资讯整合平臺
Audrey Tang
?
开放政府联络人第11次协作会议简报
开放政府联络人第11次协作会议简报开放政府联络人第11次协作会议简报
开放政府联络人第11次协作会议简报
Audrey Tang
?
第7次协作会议会后会简报惫6.0
第7次协作会议会后会简报惫6.0第7次协作会议会后会简报惫6.0
第7次协作会议会后会简报惫6.0
Audrey Tang
?
临时动议:社会公司连繫会议分组
临时动议:社会公司连繫会议分组临时动议:社会公司连繫会议分组
临时动议:社会公司连繫会议分组
Audrey Tang
?
议程及歷次列管表
议程及歷次列管表议程及歷次列管表
议程及歷次列管表
Audrey Tang
?
讨论案一:中、南、东部在地社企会谈规划情形
讨论案一:中、南、东部在地社企会谈规划情形讨论案一:中、南、东部在地社企会谈规划情形
讨论案一:中、南、东部在地社企会谈规划情形
Audrey Tang
?
报告案四之一:创柜板协助社会公司筹资之推动现况
报告案四之一:创柜板协助社会公司筹资之推动现况报告案四之一:创柜板协助社会公司筹资之推动现况
报告案四之一:创柜板协助社会公司筹资之推动现况
Audrey Tang
?
报告案四之二:国发基金运用资金协助社会发展办理方式
报告案四之二:国发基金运用资金协助社会发展办理方式报告案四之二:国发基金运用资金协助社会发展办理方式
报告案四之二:国发基金运用资金协助社会发展办理方式
Audrey Tang
?
报告案二:组团参加2017年社会公司世界论坛办理进度报告
报告案二:组团参加2017年社会公司世界论坛办理进度报告报告案二:组团参加2017年社会公司世界论坛办理进度报告
报告案二:组团参加2017年社会公司世界论坛办理进度报告
Audrey Tang
?
報告案三 :SEWF申辦2019進度說明
報告案三 :SEWF申辦2019進度說明報告案三 :SEWF申辦2019進度說明
報告案三 :SEWF申辦2019進度說明
Audrey Tang
?
2017-06-17 臺灣網路治理論壇
2017-06-17 臺灣網路治理論壇2017-06-17 臺灣網路治理論壇
2017-06-17 臺灣網路治理論壇
Audrey Tang
?
行政院数位国家创新经济推动小组设置要点
行政院数位国家创新经济推动小组设置要点行政院数位国家创新经济推动小组设置要点
行政院数位国家创新经济推动小组设置要点
Audrey Tang
?
DIGI? 數位政府
DIGI? 數位政府DIGI? 數位政府
DIGI? 數位政府
Audrey Tang
?
Social Innovation & Digital Transformation
Social Innovation & Digital TransformationSocial Innovation & Digital Transformation
Social Innovation & Digital Transformation
Audrey Tang
?
Stories from the Future of Democracy
Stories from the Future of DemocracyStories from the Future of Democracy
Stories from the Future of Democracy
Audrey Tang
?
TEDxTaipei 2017: 社會企業
TEDxTaipei 2017: 社會企業TEDxTaipei 2017: 社會企業
TEDxTaipei 2017: 社會企業
Audrey Tang
?
唐凤政务委员业务工作报告
唐凤政务委员业务工作报告唐凤政务委员业务工作报告
唐凤政务委员业务工作报告
Audrey Tang
?
資訊服務採購契約範本 修正明細對照 1060713
資訊服務採購契約範本 修正明細對照 1060713資訊服務採購契約範本 修正明細對照 1060713
資訊服務採購契約範本 修正明細對照 1060713
Audrey Tang
?
服務型智慧政府推動計畫 v9
服務型智慧政府推動計畫 v9服務型智慧政府推動計畫 v9
服務型智慧政府推動計畫 v9
Audrey Tang
?
共通性应用程式介面规范
共通性应用程式介面规范共通性应用程式介面规范
共通性应用程式介面规范
Audrey Tang
?
打造一站式的防救灾资讯整合平臺
打造一站式的防救灾资讯整合平臺打造一站式的防救灾资讯整合平臺
打造一站式的防救灾资讯整合平臺
Audrey Tang
?
开放政府联络人第11次协作会议简报
开放政府联络人第11次协作会议简报开放政府联络人第11次协作会议简报
开放政府联络人第11次协作会议简报
Audrey Tang
?
第7次协作会议会后会简报惫6.0
第7次协作会议会后会简报惫6.0第7次协作会议会后会简报惫6.0
第7次协作会议会后会简报惫6.0
Audrey Tang
?
临时动议:社会公司连繫会议分组
临时动议:社会公司连繫会议分组临时动议:社会公司连繫会议分组
临时动议:社会公司连繫会议分组
Audrey Tang
?
议程及歷次列管表
议程及歷次列管表议程及歷次列管表
议程及歷次列管表
Audrey Tang
?
讨论案一:中、南、东部在地社企会谈规划情形
讨论案一:中、南、东部在地社企会谈规划情形讨论案一:中、南、东部在地社企会谈规划情形
讨论案一:中、南、东部在地社企会谈规划情形
Audrey Tang
?
报告案四之一:创柜板协助社会公司筹资之推动现况
报告案四之一:创柜板协助社会公司筹资之推动现况报告案四之一:创柜板协助社会公司筹资之推动现况
报告案四之一:创柜板协助社会公司筹资之推动现况
Audrey Tang
?
报告案四之二:国发基金运用资金协助社会发展办理方式
报告案四之二:国发基金运用资金协助社会发展办理方式报告案四之二:国发基金运用资金协助社会发展办理方式
报告案四之二:国发基金运用资金协助社会发展办理方式
Audrey Tang
?
报告案二:组团参加2017年社会公司世界论坛办理进度报告
报告案二:组团参加2017年社会公司世界论坛办理进度报告报告案二:组团参加2017年社会公司世界论坛办理进度报告
报告案二:组团参加2017年社会公司世界论坛办理进度报告
Audrey Tang
?
報告案三 :SEWF申辦2019進度說明
報告案三 :SEWF申辦2019進度說明報告案三 :SEWF申辦2019進度說明
報告案三 :SEWF申辦2019進度說明
Audrey Tang
?
2017-06-17 臺灣網路治理論壇
2017-06-17 臺灣網路治理論壇2017-06-17 臺灣網路治理論壇
2017-06-17 臺灣網路治理論壇
Audrey Tang
?
行政院数位国家创新经济推动小组设置要点
行政院数位国家创新经济推动小组设置要点行政院数位国家创新经济推动小组设置要点
行政院数位国家创新经济推动小组设置要点
Audrey Tang
?

Recently uploaded (6)

阿伯丁大学毕业证(鲍辞础学位证学历认证国外留学)办理
阿伯丁大学毕业证(鲍辞础学位证学历认证国外留学)办理阿伯丁大学毕业证(鲍辞础学位证学历认证国外留学)办理
阿伯丁大学毕业证(鲍辞础学位证学历认证国外留学)办理
kaozytf
?
Build_With_AI_2025 Gemini 2.0 New Function
Build_With_AI_2025  Gemini 2.0 New FunctionBuild_With_AI_2025  Gemini 2.0 New Function
Build_With_AI_2025 Gemini 2.0 New Function
kevinchiu59
?
2025 NVIDIA GTC: Crack the AI Black Box: Practical Techniques for Explainable AI
2025 NVIDIA GTC: Crack the AI Black Box: Practical Techniques for Explainable AI2025 NVIDIA GTC: Crack the AI Black Box: Practical Techniques for Explainable AI
2025 NVIDIA GTC: Crack the AI Black Box: Practical Techniques for Explainable AI
David vonThenen
?
2025 DeveloperWeek - The Sound of Innovation: Why Voice Cloning Will Redefine...
2025 DeveloperWeek - The Sound of Innovation: Why Voice Cloning Will Redefine...2025 DeveloperWeek - The Sound of Innovation: Why Voice Cloning Will Redefine...
2025 DeveloperWeek - The Sound of Innovation: Why Voice Cloning Will Redefine...
David vonThenen
?
匹兹堡大学毕业证(笔滨罢罢学位证范本毕业证书)办理
匹兹堡大学毕业证(笔滨罢罢学位证范本毕业证书)办理匹兹堡大学毕业证(笔滨罢罢学位证范本毕业证书)办理
匹兹堡大学毕业证(笔滨罢罢学位证范本毕业证书)办理
kaozytf
?
Cantonmade 2025 Hotel Supplier Catalog: Technical Specs for Engineers & Integ...
Cantonmade 2025 Hotel Supplier Catalog: Technical Specs for Engineers & Integ...Cantonmade 2025 Hotel Supplier Catalog: Technical Specs for Engineers & Integ...
Cantonmade 2025 Hotel Supplier Catalog: Technical Specs for Engineers & Integ...
RayChan91
?
阿伯丁大学毕业证(鲍辞础学位证学历认证国外留学)办理
阿伯丁大学毕业证(鲍辞础学位证学历认证国外留学)办理阿伯丁大学毕业证(鲍辞础学位证学历认证国外留学)办理
阿伯丁大学毕业证(鲍辞础学位证学历认证国外留学)办理
kaozytf
?
Build_With_AI_2025 Gemini 2.0 New Function
Build_With_AI_2025  Gemini 2.0 New FunctionBuild_With_AI_2025  Gemini 2.0 New Function
Build_With_AI_2025 Gemini 2.0 New Function
kevinchiu59
?
2025 NVIDIA GTC: Crack the AI Black Box: Practical Techniques for Explainable AI
2025 NVIDIA GTC: Crack the AI Black Box: Practical Techniques for Explainable AI2025 NVIDIA GTC: Crack the AI Black Box: Practical Techniques for Explainable AI
2025 NVIDIA GTC: Crack the AI Black Box: Practical Techniques for Explainable AI
David vonThenen
?
2025 DeveloperWeek - The Sound of Innovation: Why Voice Cloning Will Redefine...
2025 DeveloperWeek - The Sound of Innovation: Why Voice Cloning Will Redefine...2025 DeveloperWeek - The Sound of Innovation: Why Voice Cloning Will Redefine...
2025 DeveloperWeek - The Sound of Innovation: Why Voice Cloning Will Redefine...
David vonThenen
?
匹兹堡大学毕业证(笔滨罢罢学位证范本毕业证书)办理
匹兹堡大学毕业证(笔滨罢罢学位证范本毕业证书)办理匹兹堡大学毕业证(笔滨罢罢学位证范本毕业证书)办理
匹兹堡大学毕业证(笔滨罢罢学位证范本毕业证书)办理
kaozytf
?
Cantonmade 2025 Hotel Supplier Catalog: Technical Specs for Engineers & Integ...
Cantonmade 2025 Hotel Supplier Catalog: Technical Specs for Engineers & Integ...Cantonmade 2025 Hotel Supplier Catalog: Technical Specs for Engineers & Integ...
Cantonmade 2025 Hotel Supplier Catalog: Technical Specs for Engineers & Integ...
RayChan91
?

EtherCalc for Drupal