forked from audreyt/ethercalc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplayer.ls
More file actions
357 lines (331 loc) · 17 KB
/
player.ls
File metadata and controls
357 lines (331 loc) · 17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
@include = -> @client '/player/main.js': ->
$ = window.jQuery || window.$
return location.reload! unless $
doPlay = ~>
window.SocialCalc ?= {}
SocialCalc._username = Math.random!toString!
SocialCalc.isConnected = true
requestParams = SocialCalc.requestParams
SocialCalc._auth = requestParams[\auth] if requestParams[\auth]?
SocialCalc._app = true if requestParams[\app]?
SocialCalc._view = true if requestParams[\view]?
#SocialCalc._view = SocialCalc._auth is \0
SocialCalc._room ?= window.EtherCalc?_room || window.location.hash.replace \# ''
SocialCalc._room = "#{SocialCalc._room}".replace /^_+/ '' .replace /\?.*/ ''
endpoint = $('script[src*="/socket.io/socket.io.js"]')?attr(\src)?replace(/\.?\/socket.io\/socket.io.js.*/ '')
if endpoint is ''
endpoint = location.pathname .replace // /(view|edit)$ // ''
endpoint.=replace // #{ SocialCalc._room } $ // ''
if window.Drupal?sheetnode
if // overlay=node/\d+ //.test window.location.hash
SocialCalc._room = window.location.hash.match // =node/(\d+) // .1
else if // /node/\d+ //.test window.location.href
SocialCalc._room = window.location.href.match // /node/(\d+) // .1
else if SocialCalc._room
unless SocialCalc.CurrentSpreadsheetControlObject
<- setTimeout _, 100ms
window.history.pushState {} '' "./#{ SocialCalc._room }#{
switch
| SocialCalc._app => '/app'
| SocialCalc._view => '/view'
| SocialCalc._auth => '/edit'
| otherwise => ''
}"
if location.host is /^(?:www\.)?ethercalc\.net$/
$ -> $('<a />', {
id: "restore", target: "_blank"
href: "https://ethercalc.net/log/?#{ SocialCalc._room }"
title: "View & Restore Backups"
}).text("↻").appendTo('body')
else
window.location = './_start'
return
options = { 'connect timeout': 1500ms, +reconnect, 'reconnection delay': 500ms, 'max reconnection attempts': 1800 }
options.path = endpoint.replace(// /?$ // \/socket.io) if endpoint
showError = ->
vex?closeAll!
vex?defaultOptions.className = 'vex-theme-flat-attack'
vex?dialog.open do
message: it
buttons: []
window.addEventListener \offline ->
showError SocialCalc.Constants.s_loc_error_offline
@connect('/', options)?io
..?on \reconnect ->
return unless SocialCalc?isConnected
SocialCalc.Callbacks.broadcast \ask.log
..?on \connect_error ->
showError SocialCalc.Constants.s_loc_error_connection
..?on \connect_timeout ->
showError SocialCalc.Constants.s_loc_timeout_connection
..?on \reconnect_error ->
return unless SocialCalc?isConnected
SocialCalc.hadSnapshot = false
showError SocialCalc.Constants.s_loc_error_reconnecting
..?on \connect_failed ->
showError SocialCalc.Constants.s_loc_error_reconnection_failed
emit = (data) ~> @emit {data}
SocialCalc.Callbacks.broadcast = (type, data={}) ~>
return unless SocialCalc.isConnected
data.user = SocialCalc._username
data.room = SocialCalc._room if !data.room?
data.type = type
data.auth = SocialCalc._auth if SocialCalc._auth
emit data
SocialCalc.isConnected = true
SocialCalc.RecalcInfo.LoadSheetCache = {}
SocialCalc.RecalcInfo.LoadSheet = (ref) ->
return if ref is /[^.=_a-zA-Z0-9]/
ref.=toLowerCase!
emit type: \ask.recalc, user: SocialCalc._username, room: ref
@on data: !->
return unless SocialCalc?isConnected
return if @data.user == SocialCalc._username and @data.room == SocialCalc._room #ignore self calls to main spreadsheet, but formdata calls will still be processed
return if @data.to and @data.to != SocialCalc._username
ss = window.spreadsheet
return unless ss
return if @data.room and @data.room != SocialCalc._room and ss.formDataViewer?._room != @data.room and @data.type == "log"
if @data.room and @data.room != SocialCalc._room and @data.type != "recalc" and @data.type != "log"
return if ss.formDataViewer?._room != @data.room
ss = ss.formDataViewer # process the form data sheet event
editor = ss.editor
switch @data.type
| \confirmemailsent => SocialCalc.EditorSheetStatusCallback(null, "confirmemailsent", @data.message, editor);
| \chat => window.addmsg? @data.msg
| \ecells
break if SocialCalc._app
do => for user, ecell of @data.ecells
continue if user is SocialCalc._username
peerClass = " #user defaultPeer"
find = new RegExp peerClass, \g
cr = SocialCalc.coordToCr ecell
cell = SocialCalc.GetEditorCellElement editor, cr.row, cr.col
if cell?element.className.search(find) == -1
cell.element.className += peerClass
| \ecell
peerClass = " #{@data.user} defaultPeer"
find = new RegExp peerClass, \g
if @data.original
origCR = SocialCalc.coordToCr @data.original
origCell = SocialCalc.GetEditorCellElement editor, origCR.row, origCR.col
origCell?.element.className = origCell.element.className.replace find, ''
if @data.original is editor.ecell.coord or @data.ecell is editor.ecell.coord
SocialCalc.Callbacks.broadcast \ecell,
to: @data.user
ecell: editor.ecell.coord
break if SocialCalc._app
cr = SocialCalc.coordToCr @data.ecell
cell = SocialCalc.GetEditorCellElement editor, cr.row, cr.col
cell.element.className += peerClass if cell?element?className.search(find) == -1
| \ask.ecell
break if SocialCalc._app
SocialCalc.Callbacks.broadcast \ecell do
to: @data.user
ecell: editor.ecell.coord
| \log
ss = window.spreadsheet #
vex?closeAll!
#eddy
if ss.formDataViewer?._room is @data.room
if @data.snapshot
parts = ss.DecodeSpreadsheetSave @data.snapshot
ss.formDataViewer.sheet.ResetSheet!
ss.formDataViewer.loaded = true
SocialCalc.Callbacks.broadcast \ask.log
# if formData sheet already exists
if parts?sheet
ss.formDataViewer.ParseSheetSave( @data.snapshot.substring( parts.sheet.start, parts.sheet.end))
ss.formDataViewer.context.sheetobj.ScheduleSheetCommands "recalc\n", false, true
break
#}
break if SocialCalc.hadSnapshot
SocialCalc.hadSnapshot = true
if @data.snapshot
parts = ss.DecodeSpreadsheetSave @data.snapshot
if parts?
if parts.sheet
ss.sheet.ResetSheet!
ss.ParseSheetSave @data.snapshot.substring parts.sheet.start, parts.sheet.end
if parts.edit
ss.editor.LoadEditorSettings @data.snapshot.substring parts.edit.start, parts.edit.end
# render not needed, render is triggered by: CreateTableEditor (renders empty sheet) then RecalcTimerRoutine (renders loaded sheet)
window.addmsg? @data.chat.join(\\n), true
cmdstr = [ line for line in @data.log
| not /^re(calc|display)$/.test(line) ].join \\n
if cmdstr.length
refreshCmd = \recalc
ss.context.sheetobj.ScheduleSheetCommands "#cmdstr\n#refreshCmd\n", false, true
else
ss.context.sheetobj.ScheduleSheetCommands "recalc\n", false, true
| \snapshot
vex?closeAll!
SocialCalc.hadSnapshot = true
if @data.snapshot
parts = ss.DecodeSpreadsheetSave @data.snapshot
if parts?sheet
ss.sheet.ResetSheet!
ss.ParseSheetSave @data.snapshot.substring parts.sheet.start, parts.sheet.end
ss.context.sheetobj.ScheduleSheetCommands "recalc\n", false, true
| \recalc
if @data.force
# only remove updated sheet - fix cycle problem when using many sheets
delete SocialCalc.Formula.SheetCache.sheets[@data.room]
ss?sheet.recalconce = true
parts = ss.DecodeSpreadsheetSave @data.snapshot if @data.snapshot
if parts?sheet
sheetdata = @data.snapshot.substring(parts.sheet.start, parts.sheet.end)
SocialCalc.RecalcLoadedSheet(
@data.room,
sheetdata,
true # recalc
)
if SocialCalc.RecalcInfo.LoadSheetCache[@data.room] isnt sheetdata
SocialCalc.RecalcInfo.LoadSheetCache[@data.room] = sheetdata
ss.context.sheetobj.ScheduleSheetCommands "recalc\n", false, true
else
SocialCalc.RecalcLoadedSheet @data.room, '', true
| \execute
ss.context.sheetobj.ScheduleSheetCommands @data.cmdstr, @data.saveundo, true
if ss.currentTab is ss.tabnums?graph
setTimeout do
-> window.DoGraph false false
100ms
| \stopHuddle
$(\#content)uiDisable!
alert """
[Collaborative Editing Session Completed]
Thank you for your participation.
Check the activity stream to see the newly edited page!
"""
window.onunload = null
window.onbeforeunload = null
window.location = '/'
| \error
vex?closeAll!
vex?defaultOptions.className = 'vex-theme-flat-attack'
vex?dialog.open do
message: @data.message
buttons: [
$.extend {}, vex?dialog.buttons.YES, text: 'Return to ready-only mode', click: ->
location.href = "../#{ SocialCalc._room }"
]
window.doresize = !-> window.spreadsheet?DoOnResize!
onReady = ->
return onLoad! unless window.Drupal?sheetnode?sheetviews?length
$container = window.Drupal?sheetnode.sheetviews[0].$container
$container.bind \sheetnodeReady (_, {spreadsheet}) ->
if spreadsheet.tabbackground is 'display:none;'
if spreadsheet.InitializeSpreadsheetControl
return
SocialCalc._auth = \0
onLoad spreadsheet
$ -> setTimeout onReady, 1ms
onLoad = (ssInstance=SocialCalc.CurrentSpreadsheetControlObject) ->
window.spreadsheet = ss = ssInstance || (
if SocialCalc._view || SocialCalc._app
new SocialCalc.SpreadsheetViewer!
else
new SocialCalc.SpreadsheetControl!
)
# eddy {
if !window.GraphOnClick?
SocialCalc.Callbacks.broadcast \ask.log
return
# } eddy
ss.ExportCallback = (s) ->
alert SocialCalc.ConvertSaveToOtherFormat(SocialCalc.Clipboard.clipboard, "csv")
# eddy {
# add Form tab as first tab
#ss.tabs?[0]?html = ss.tabs?[0]?html.replace("style=\"", "style=\"display:none;")
ss.tabnums.form = ss.tabs.length if ss.tabs
ss.tabs?push do
name: \form
text: SocialCalc.Constants.s_loc_form
html: """
<div id="%id.formtools" style="display:none;"><div style="%tbt."><table cellspacing="0" cellpadding="0">
<tr><td style="vertical-align:middle;padding-right:32px;padding-left:16px;"><div style="%tbt.">
<input type="button" value="%loc!Live Form!" onclick="parent.location='#{SocialCalc._room}/form'" style="background-color: #5cb85c;border-color: #4cae4c;cursor: pointer;"> #{document.location.origin}/#{SocialCalc._room}/form </div></td>
</tr></table></div></div>
"""
view: \sheet
onclick: null
onclickFocus: true
# }
ss.tabnums.graph = ss.tabs.length if ss.tabs
ss.tabs?push do
name: \graph
text: SocialCalc.Constants.s_loc_graph
html: """
<div id="%id.graphtools" style="display:none;"><div style="%tbt."><table cellspacing="0" cellpadding="0"><tr><td style="vertical-align:middle;padding-right:32px;padding-left:16px;"><div style="%tbt.">%loc!Cells to Graph!</div><div id="%id.graphrange" style="font-weight:bold;">%loc!Not Set!</div></td><td style="vertical-align:top;padding-right:32px;"><div style="%tbt.">%loc!Set Cells To Graph!</div><select id="%id.graphlist" size="1" onfocus="%s.CmdGotFocus(this);"><option selected>[select range]</option><option>%loc!Select all!</option></select></td><td style="vertical-align:middle;padding-right:4px;"><div style="%tbt.">%loc!Graph Type!</div><select id="%id.graphtype" size="1" onchange="window.GraphChanged(this);" onfocus="%s.CmdGotFocus(this);"></select><input type="button" value="%loc!OK!" onclick="window.GraphSetCells();" style="font-size:x-small;"></div></td><td style="vertical-align:middle;padding-right:16px;"><div style="%tbt."> </div><input id="%id.graphhelp" type="button" onclick="DoGraph(true);" value="%loc!Help!" style="font-size:x-small;"></div></td><td style="vertical-align:middle;padding-right:16px;">%loc!Min X! <input id="%id.graphMinX" onchange="window.MinMaxChanged(this,0);" onfocus="%s.CmdGotFocus(this);" size=5/>%loc!Max X! <input id="%id.graphMaxX" onchange="window.MinMaxChanged(this,1);" onfocus="%s.CmdGotFocus(this);" size=5/><br/>%loc!Min Y! <input id="%id.graphMinY" onchange="window.MinMaxChanged(this,2);" onfocus="%s.CmdGotFocus(this);" size=5/>%loc!Max Y! <input id="%id.graphMaxY" onchange="window.MinMaxChanged(this,3);" onfocus="%s.CmdGotFocus(this);" size=5/></div></td></tr></table></div></div>
"""
view: \graph
onclick: window.GraphOnClick
onclickFocus: true
ss.views?graph =
name: \graph
divStyle: "overflow:auto;"
values: {}
html: '<div style="padding:6px;">Graph View</div>'
ss.editor?SettingsCallbacks.graph =
save: window.GraphSave
load: window.GraphLoad
# Spinner - shows when sheet data is loading
ss.sheet.cells["A1"] = new SocialCalc.Cell("A1")
ss.sheet.cells["A1"].displaystring = '<div class="loader"></div>'
ss.InitializeSpreadsheetViewer? \tableeditor, 0, 0, 0
ss.InitializeSpreadsheetControl? \tableeditor, 0, 0, 0
# eddy {
if !SocialCalc._view? && ss.formDataViewer?
# request formData and then the spreadsheet data
ss.formDataViewer.sheet._room = ss.formDataViewer._room = SocialCalc._room + "_formdata"
SocialCalc.Callbacks.broadcast \ask.log {room: ss.formDataViewer._room}
else
# request the spreadsheet data
SocialCalc.Callbacks.broadcast \ask.log
# } eddy
ss.ExecuteCommand? \redisplay, ''
ss.ExecuteCommand? 'set sheet defaulttextvalueformat text-wiki'
$ document .on \mouseover '.te_download tr:nth-child(2) td:first' ->
$ @ .attr title: SocialCalc.Constants.s_loc_export
$ document .on \click '.te_download tr:nth-child(2) td:first' ->
SocialCalc.Keyboard.passThru = yes if vex?dialog.open
isMultiple = (window.__MULTI__ or SocialCalc._room is /\.[1-9]\d*$/)
vex?defaultOptions.className = 'vex-theme-flat-attack'
vex?dialog.open do
message: SocialCalc.Constants.s_loc_export_format+"#{
if isMultiple then "<br><small>(ODS and EXCEL support multiple sheets.)</small>" else ""
}"
callback: -> SocialCalc.Keyboard.passThru = no
buttons: [
$.extend {}, vex?dialog.buttons.YES, text: 'Excel', click: ->
if isMultiple
if window.parent.location.href.match(/(^.*\/=[^?/]+)/)
window.open "#{ RegExp.$1 }.xlsx"
else
window.open ".#{if window.parent.location.pathname.match('\/.*\/view$') || window.parent.location.pathname.match('\/.*\/edit$') then '.' else ''}/=#{ SocialCalc._room.replace(/\.[1-9]\d*$/, '') }.xlsx"
else
window.open ".#{if window.parent.location.pathname.match('\/.*\/view$') || window.parent.location.pathname.match('\/.*\/edit$') then '.' else ''}/#{ SocialCalc._room }.xlsx"
$.extend {}, vex?dialog.buttons.YES, text: 'CSV', click: ->
window.open ".#{if window.parent.location.pathname.match('\/.*\/view$') || window.parent.location.pathname.match('\/.*\/edit$') then '.' else ''}/#{ SocialCalc._room }.csv"
$.extend {}, vex?dialog.buttons.YES, text: 'HTML', click: ->
window.open ".#{if window.parent.location.pathname.match('\/.*\/view$') || window.parent.location.pathname.match('\/.*\/edit$') then '.' else ''}/#{ SocialCalc._room }.html"
$.extend {}, vex?dialog.buttons.YES, text: 'ODS', click: ->
if isMultiple
if window.parent.location.href.match(/(^.*\/=[^?/]+)/)
window.open "#{ RegExp.$1 }.ods"
else
window.open ".#{if window.parent.location.pathname.match('\/.*\/view$') || window.parent.location.pathname.match('\/.*\/edit$') then '.' else ''}/=#{ SocialCalc._room.replace(/\.[1-9]\d*$/, '') }.ods"
else
window.open ".#{if window.parent.location.pathname.match('\/.*\/view$') || window.parent.location.pathname.match('\/.*\/edit$') then '.' else ''}/#{ SocialCalc._room }.ods"
$.extend {}, vex?dialog.buttons.NO, text: SocialCalc.Constants.s_loc_cancel
]
# In-situ import courtesy of
# SocialCalc.CurrentSpreadsheetControlObject.tabs[6] ("Clipboard")
if window.Document?Parser
SocialCalc.Callbacks.expand_wiki = (val) -> """
<div class="wiki">#{
new Document.Parser.Wikitext!
.parse val, new Document.Emitter.HTML!
}</div>
"""
doPlay!