statebus 6.1.20 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{client.js → clients.js} +257 -141
- package/extras/tests.js +292 -412
- package/package.json +9 -3
- package/{server.js → servers.js} +288 -333
- package/statebus.js +299 -620
- package/extras/coffee.js +0 -12
- package/extras/dash.coffee +0 -302
- package/extras/diffsync.js +0 -1462
- package/extras/getCaretCoordinates.js +0 -141
- package/extras/react.js +0 -18147
- package/extras/sockjs.js +0 -27
package/{client.js → clients.js}
RENAMED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
var websocket_prefix = (clientjs_option('websocket_path')
|
|
3
3
|
|| '_connect_to_statebus_')
|
|
4
4
|
|
|
5
|
+
// Todo: remove this global
|
|
5
6
|
window.dom = window.dom || new Proxy({}, {
|
|
6
7
|
get: function (o, k) { return o[k] },
|
|
7
8
|
set: function (o, k, v) {
|
|
@@ -37,12 +38,12 @@
|
|
|
37
38
|
// link.href = url
|
|
38
39
|
// url = link.href
|
|
39
40
|
// }
|
|
40
|
-
|
|
41
|
+
|
|
41
42
|
return new WebSocket(url + '/' + websocket_prefix + '/websocket')
|
|
42
43
|
// return new SockJS(url + '/' + websocket_prefix)
|
|
43
44
|
}
|
|
44
45
|
function client_creds (server_url) {
|
|
45
|
-
var me = bus.
|
|
46
|
+
var me = bus.get('ls/me')
|
|
46
47
|
bus.log('connect: me is', me)
|
|
47
48
|
if (!me.client) {
|
|
48
49
|
// Create a client id if we have none yet.
|
|
@@ -51,19 +52,20 @@
|
|
|
51
52
|
me.client = c || (Math.random().toString(36).substring(2)
|
|
52
53
|
+ Math.random().toString(36).substring(2)
|
|
53
54
|
+ Math.random().toString(36).substring(2))
|
|
54
|
-
bus.
|
|
55
|
+
bus.set(me)
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
set_cookie('client', me.client)
|
|
58
59
|
return {clientid: me.client}
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
function
|
|
62
|
+
function http_mount (prefix, url) {
|
|
62
63
|
var preprefix = prefix.slice(0,-1)
|
|
63
64
|
var has_prefix = new RegExp('^' + preprefix)
|
|
64
65
|
var is_absolute = /^https?:\/\//
|
|
65
|
-
var
|
|
66
|
-
|
|
66
|
+
var subscriptions = {}
|
|
67
|
+
var put_counter = 0
|
|
68
|
+
|
|
67
69
|
function add_prefix (key) {
|
|
68
70
|
return is_absolute.test(key) ? key : preprefix + key }
|
|
69
71
|
function rem_prefix (key) {
|
|
@@ -73,45 +75,146 @@
|
|
|
73
75
|
function rem_prefixes (obj) {
|
|
74
76
|
return bus.translate_keys(bus.clone(obj), rem_prefix) }
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
var puts = new Map()
|
|
79
|
+
function enqueue_put (url, body) {
|
|
80
|
+
var id = put_counter++
|
|
81
|
+
puts.set(id, {url: url, body: body, id: id})
|
|
82
|
+
send_put(id)
|
|
83
|
+
}
|
|
84
|
+
function send_put (id) {
|
|
85
|
+
try {
|
|
86
|
+
puts.get(id).status = 'sending'
|
|
87
|
+
braid_fetch(
|
|
88
|
+
puts.get(id).url,
|
|
89
|
+
{
|
|
90
|
+
method: 'put',
|
|
91
|
+
headers: {
|
|
92
|
+
'content-type': 'application/json',
|
|
93
|
+
'put-order': id,
|
|
94
|
+
},
|
|
95
|
+
body: puts.get(id).body
|
|
96
|
+
}
|
|
97
|
+
).then(function (res) {
|
|
98
|
+
if (res.status !== 200)
|
|
99
|
+
console.error('Server gave error on PUT:',
|
|
100
|
+
e, 'for', puts.get(id).body)
|
|
101
|
+
puts.delete(id)
|
|
102
|
+
}).catch(function (e) {
|
|
103
|
+
console.error('Error on PUT, waiting...', puts.get(id).url)
|
|
104
|
+
puts.get(id).status = 'waiting'
|
|
105
|
+
})
|
|
106
|
+
} catch (e) {
|
|
107
|
+
console.error('Error on PUT, waiting...', puts.get(id).url)
|
|
108
|
+
puts.get(id).status = 'waiting'
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function retry_put (id) {
|
|
112
|
+
setTimeout(function () {send_put(id)}, 1000)
|
|
113
|
+
}
|
|
114
|
+
function send_all_puts () {
|
|
115
|
+
for (var id of puts.keys())
|
|
116
|
+
if (puts.get(id).status === 'waiting') {
|
|
117
|
+
console.log('Sending waiting put', id)
|
|
118
|
+
send_put(id)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
78
121
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
// if (t.parents) x.parents = t.parents
|
|
82
|
-
// if (t.patch) x.patch = t.patch
|
|
83
|
-
// if (t.patch) x.save = rem_prefix(x.save.key)
|
|
122
|
+
bus(prefix).to_set = function (obj, t) {
|
|
123
|
+
bus.set.fire(obj)
|
|
84
124
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
125
|
+
var put = {
|
|
126
|
+
url: url + rem_prefix(obj.key),
|
|
127
|
+
body: JSON.stringify(obj.val)
|
|
128
|
+
}
|
|
129
|
+
if (t.version) put.version = t.version
|
|
130
|
+
if (t.parents) put.parents = t.parents
|
|
131
|
+
if (t.patch) put.patch = t.patch
|
|
132
|
+
var put_id = put_counter++
|
|
133
|
+
puts.set(put_id, put)
|
|
134
|
+
send_put(put_id)
|
|
91
135
|
}
|
|
92
136
|
|
|
93
|
-
bus(prefix).
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
137
|
+
bus(prefix).to_get = function (key, t) {
|
|
138
|
+
// Subscription can be in states:
|
|
139
|
+
// - connecting
|
|
140
|
+
// - connected
|
|
141
|
+
// - reconnect
|
|
142
|
+
// - reconnecting
|
|
143
|
+
// - aborted
|
|
144
|
+
|
|
145
|
+
// If we have an outstanding get running, then let's tell it to
|
|
146
|
+
// re-activate!
|
|
147
|
+
if (subscriptions[key]) {
|
|
148
|
+
// We should only be here if an existing subscription was
|
|
149
|
+
// aborted, but hasn't cleared yet.
|
|
150
|
+
console.assert(subscriptions[key].status === 'aborted',
|
|
151
|
+
'Regetting a subscription of status '
|
|
152
|
+
+ subscriptions[key].status)
|
|
153
|
+
|
|
154
|
+
console.trace('foo')
|
|
155
|
+
|
|
156
|
+
// Let's tell it to reconnect when it tries to clear!
|
|
157
|
+
subscriptions[key].status = 'reconnect'
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Otherwise, create a new subscription
|
|
161
|
+
else
|
|
162
|
+
subscribe (key, t)
|
|
163
|
+
|
|
164
|
+
function subscribe (key, t) {
|
|
165
|
+
var aborter = new AbortController(),
|
|
166
|
+
reconnect_attempts = 0
|
|
167
|
+
|
|
168
|
+
// Start the subscription!
|
|
169
|
+
braid_fetch(
|
|
170
|
+
// URL
|
|
171
|
+
url + rem_prefix(key),
|
|
172
|
+
|
|
173
|
+
// Options
|
|
174
|
+
{
|
|
175
|
+
method: 'get',
|
|
176
|
+
subscribe: true,
|
|
177
|
+
headers: {accept: 'application/json'},
|
|
178
|
+
signal: aborter.signal
|
|
179
|
+
}
|
|
180
|
+
).andThen( function (x) {
|
|
181
|
+
// New update received!
|
|
182
|
+
if (subscriptions[key].status === 'connecting') {
|
|
183
|
+
console.log('%c[*] opened ' + key,
|
|
184
|
+
'color: blue')
|
|
185
|
+
reconnect_attempts = 0
|
|
186
|
+
subscriptions[key].status = 'connected'
|
|
187
|
+
send_all_puts()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Return the update
|
|
191
|
+
t.return({
|
|
192
|
+
key: key,
|
|
193
|
+
val: add_prefixes(JSON.parse(x.body))
|
|
194
|
+
})
|
|
195
|
+
}).catch( function (e) {
|
|
196
|
+
if (subscriptions[key].status === 'aborted') {
|
|
197
|
+
// Then this get is over and done with!
|
|
198
|
+
delete subscriptions[key]
|
|
199
|
+
return
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Reconnect!
|
|
203
|
+
setTimeout(function () { subscribe(key, t) },
|
|
204
|
+
reconnect_attempts > 0 ? 5000 : 1500)
|
|
205
|
+
subscriptions[key].status = 'reconnecting'
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
// Remember this subscription
|
|
209
|
+
subscriptions[key] = {
|
|
210
|
+
aborter: aborter,
|
|
211
|
+
status: 'connecting'
|
|
212
|
+
}
|
|
109
213
|
}
|
|
110
|
-
client_fetched_keys.add(key)
|
|
111
214
|
}
|
|
112
215
|
bus(prefix).to_forget = function (key) {
|
|
113
|
-
|
|
114
|
-
|
|
216
|
+
subscriptions[key].status = 'aborted'
|
|
217
|
+
subscriptions[key].aborter.abort()
|
|
115
218
|
}
|
|
116
219
|
}
|
|
117
220
|
|
|
@@ -127,31 +230,31 @@
|
|
|
127
230
|
var bus = this
|
|
128
231
|
bus.log(this)
|
|
129
232
|
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
var
|
|
133
|
-
var
|
|
233
|
+
// Get returns the value immediately in a set
|
|
234
|
+
// Sets are queued up, to store values with a delay, in batch
|
|
235
|
+
var sets_are_pending = false
|
|
236
|
+
var pending_sets = {}
|
|
134
237
|
|
|
135
|
-
function
|
|
136
|
-
bus.log('localstore: saving',
|
|
137
|
-
for (var k in
|
|
138
|
-
localStorage.setItem(k, JSON.stringify(
|
|
139
|
-
|
|
238
|
+
function set_the_pending_sets() {
|
|
239
|
+
bus.log('localstore: saving', pending_sets)
|
|
240
|
+
for (var k in pending_sets)
|
|
241
|
+
localStorage.setItem(k, JSON.stringify(pending_sets[k]))
|
|
242
|
+
sets_are_pending = false
|
|
140
243
|
}
|
|
141
244
|
|
|
142
|
-
bus(prefix).
|
|
245
|
+
bus(prefix).to_get = function (key) {
|
|
143
246
|
var result = localStorage.getItem(key)
|
|
144
247
|
return result ? JSON.parse(result) : {key: key}
|
|
145
248
|
}
|
|
146
|
-
bus(prefix).
|
|
249
|
+
bus(prefix).to_set = function (obj) {
|
|
147
250
|
// Do I need to make this recurse into the object?
|
|
148
|
-
bus.log('localStore:
|
|
149
|
-
|
|
150
|
-
if (!
|
|
151
|
-
setTimeout(
|
|
152
|
-
|
|
251
|
+
bus.log('localStore: on_set:', obj.key)
|
|
252
|
+
pending_sets[obj.key] = obj
|
|
253
|
+
if (!sets_are_pending) {
|
|
254
|
+
setTimeout(set_the_pending_sets, 50)
|
|
255
|
+
sets_are_pending = true
|
|
153
256
|
}
|
|
154
|
-
bus.
|
|
257
|
+
bus.set.fire(obj)
|
|
155
258
|
return obj
|
|
156
259
|
}
|
|
157
260
|
bus(prefix).to_delete = function (key) { localStorage.removeItem(key) }
|
|
@@ -160,6 +263,7 @@
|
|
|
160
263
|
// Hm... this update stuff doesn't seem to work on file:/// urls in chrome
|
|
161
264
|
function update (event) {
|
|
162
265
|
bus.log('Got a localstorage update', event)
|
|
266
|
+
bus.dirty(event.key)
|
|
163
267
|
//this.get(event.key.substr('statebus '.length))
|
|
164
268
|
}
|
|
165
269
|
if (window.addEventListener) window.addEventListener("storage", update, false)
|
|
@@ -184,39 +288,16 @@
|
|
|
184
288
|
data = (data && JSON.parse(data)) || {key : key}
|
|
185
289
|
// Then I would need to:
|
|
186
290
|
// - Change the key prefix
|
|
187
|
-
// -
|
|
291
|
+
// - Set this into the cache
|
|
188
292
|
|
|
189
|
-
bus(prefix).
|
|
293
|
+
bus(prefix).to_set = function (obj) {
|
|
190
294
|
window.history.replaceState(
|
|
191
295
|
'',
|
|
192
296
|
'',
|
|
193
297
|
document.location.origin
|
|
194
298
|
+ document.location.pathname
|
|
195
299
|
+ escape('?'+key+'='+JSON.stringify(obj)))
|
|
196
|
-
bus.
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function live_reload_from (prefix) {
|
|
201
|
-
if (!window.live_reload_initialized) {
|
|
202
|
-
var first_time = true
|
|
203
|
-
this(function () {
|
|
204
|
-
var re = new RegExp(".*/" + prefix + "/(.*)")
|
|
205
|
-
var file = window.location.href.match(re)[1]
|
|
206
|
-
var code = bus.fetch('/code/invisible.college/' + file).code
|
|
207
|
-
if (!code) return
|
|
208
|
-
if (first_time) {first_time = false; return}
|
|
209
|
-
var old_scroll_position = window.pageYOffset
|
|
210
|
-
document.body.innerHTML = code
|
|
211
|
-
var i = 0
|
|
212
|
-
var d = 100
|
|
213
|
-
var interval = setInterval(function () {
|
|
214
|
-
if (i > 500) clearInterval(interval)
|
|
215
|
-
i += d
|
|
216
|
-
window.scrollTo(0, old_scroll_position)
|
|
217
|
-
}, d)
|
|
218
|
-
})
|
|
219
|
-
window.live_reload_initialized = true
|
|
300
|
+
bus.set.fire(obj)
|
|
220
301
|
}
|
|
221
302
|
}
|
|
222
303
|
|
|
@@ -224,30 +305,40 @@
|
|
|
224
305
|
// ****************
|
|
225
306
|
// Wrapper for React Components
|
|
226
307
|
|
|
308
|
+
function react_version () {
|
|
309
|
+
if (!window.React) return undefined;
|
|
310
|
+
return Number(window.React.version.split('.')[0])
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Newer React requires createReactClass as a separate libary
|
|
314
|
+
if (window.React && !React.createClass && window.createReactClass)
|
|
315
|
+
React.createClass = createReactClass
|
|
316
|
+
|
|
227
317
|
// XXX Currently assumes there's a statebus named "bus" in global
|
|
228
318
|
// XXX scope.
|
|
229
319
|
|
|
230
320
|
var components = {} // Indexed by 'component/0', 'component/1', etc.
|
|
231
321
|
var components_count = 0
|
|
232
322
|
var dirty_components = {}
|
|
233
|
-
function
|
|
323
|
+
function create_react_class(component) {
|
|
234
324
|
function wrap(name, new_func) {
|
|
235
325
|
var old_func = component[name]
|
|
236
326
|
component[name] = function wrapper () { return new_func.bind(this)(old_func) }
|
|
237
327
|
}
|
|
238
328
|
|
|
239
329
|
// Register the component's basic info
|
|
240
|
-
wrap('
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
330
|
+
wrap((react_version() >= 16 ? 'UNSAFE_' : '') + 'componentWillMount',
|
|
331
|
+
function new_cwm (orig_func) {
|
|
332
|
+
// if (component.displayName === undefined)
|
|
333
|
+
// throw 'Component needs a displayName'
|
|
334
|
+
//this.name = component.displayName.toLowerCase().replace(' ', '_')
|
|
244
335
|
this.key = 'component/' + components_count++
|
|
245
336
|
components[this.key] = this
|
|
246
337
|
|
|
247
338
|
function add_shortcut (obj, shortcut_name, to_key) {
|
|
248
339
|
delete obj[shortcut_name]
|
|
249
340
|
Object.defineProperty(obj, shortcut_name, {
|
|
250
|
-
get: function () { return bus.
|
|
341
|
+
get: function () { return bus.get(to_key) },
|
|
251
342
|
configurable: true })
|
|
252
343
|
}
|
|
253
344
|
add_shortcut(this, 'local', this.key)
|
|
@@ -268,7 +359,7 @@
|
|
|
268
359
|
&& typeof this.props[k] === 'object'
|
|
269
360
|
&& this.props[k].key)
|
|
270
361
|
|
|
271
|
-
bus.
|
|
362
|
+
bus.get(this.props[k].key)
|
|
272
363
|
|
|
273
364
|
// Call the renderer!
|
|
274
365
|
return orig_render.apply(this, arguments)
|
|
@@ -339,17 +430,12 @@
|
|
|
339
430
|
props['data-key'] = props.key
|
|
340
431
|
props['data-widget'] = component.displayName
|
|
341
432
|
|
|
342
|
-
return
|
|
343
|
-
? React.createElement(react_class, props, children)
|
|
344
|
-
: react_class(props, children))
|
|
433
|
+
return React.createElement(react_class, props, children)
|
|
345
434
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
result.prototype = react_class.prototype
|
|
435
|
+
Object.defineProperty(result, 'name',
|
|
436
|
+
{value: component.displayName, writable: false})
|
|
349
437
|
return result
|
|
350
438
|
}
|
|
351
|
-
window.React_View = React_View
|
|
352
|
-
if (window.statebus) window.statebus.create_react_class = window.statebus.createReactClass = React_View
|
|
353
439
|
|
|
354
440
|
// *****************
|
|
355
441
|
// Re-rendering react components
|
|
@@ -384,7 +470,7 @@
|
|
|
384
470
|
|
|
385
471
|
function make_client_statebus_maker () {
|
|
386
472
|
var extra_stuff = ['localstorage_client make_websocket client_creds',
|
|
387
|
-
'url_store components
|
|
473
|
+
'url_store components'].join(' ').split(' ')
|
|
388
474
|
if (window.statebus) {
|
|
389
475
|
var orig_statebus = statebus
|
|
390
476
|
window.statebus = function make_client_bus () {
|
|
@@ -405,17 +491,17 @@
|
|
|
405
491
|
if (statebus_dir) statebus_dir = statebus_dir[1] + '/'
|
|
406
492
|
else statebus_dir = ''
|
|
407
493
|
|
|
408
|
-
var js_urls = {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
if (statebus_dir == 'https://stateb.us/')
|
|
415
|
-
|
|
494
|
+
// var js_urls = {
|
|
495
|
+
// react: statebus_dir + 'extras/react.js',
|
|
496
|
+
// sockjs: statebus_dir + 'extras/sockjs.js',
|
|
497
|
+
// coffee: statebus_dir + 'extras/coffee.js',
|
|
498
|
+
// statebus: statebus_dir + 'statebus.js'
|
|
499
|
+
// }
|
|
500
|
+
// if (statebus_dir == 'https://stateb.us/')
|
|
501
|
+
// js_urls.statebus = statebus_dir + 'statebus4.js'
|
|
416
502
|
|
|
417
|
-
for (var name in js_urls)
|
|
418
|
-
|
|
503
|
+
// for (var name in js_urls)
|
|
504
|
+
// document.write('<script src="' + js_urls[name] + '" charset="utf-8"></script>')
|
|
419
505
|
|
|
420
506
|
document.addEventListener('DOMContentLoaded', scripts_ready, false)
|
|
421
507
|
}
|
|
@@ -426,57 +512,50 @@
|
|
|
426
512
|
function clientjs_option (option_name) {
|
|
427
513
|
// This function must be copy/paste synchronized with statebus.js. Be
|
|
428
514
|
// sure to clone all edits there.
|
|
429
|
-
var script_elem = (
|
|
430
|
-
document.querySelector('script[src*="/client"][src$=".js"]') ||
|
|
431
|
-
document.querySelector('script[src^="client"][src$=".js"]'))
|
|
515
|
+
var script_elem = document.querySelector('script[src$="statebus/client.js"]')
|
|
432
516
|
return script_elem && script_elem.getAttribute(option_name)
|
|
433
517
|
}
|
|
434
518
|
var loaded_from_file_url = window.location.href.match(/^file:\/\//)
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
window.
|
|
519
|
+
|
|
520
|
+
// Todo: remove this global
|
|
521
|
+
window.statebus_server = clientjs_option('server')
|
|
438
522
|
var react_render
|
|
439
523
|
function scripts_ready () {
|
|
440
|
-
react_render =
|
|
524
|
+
react_render = ReactDOM.render
|
|
441
525
|
make_client_statebus_maker()
|
|
442
526
|
window.bus = window.statebus()
|
|
443
527
|
bus.label = 'bus'
|
|
444
|
-
if (clientjs_option('braid_mode'))
|
|
445
|
-
bus.state = bus.braid_proxy()
|
|
446
|
-
else
|
|
447
|
-
window.sb = bus.sb
|
|
448
|
-
statebus.widget = React_View
|
|
449
|
-
statebus.create_react_class = React_View
|
|
450
|
-
statebus.createReactClass = React_View
|
|
451
|
-
|
|
452
|
-
improve_react()
|
|
453
|
-
window.ignore_flashbacks = false
|
|
454
|
-
if (statebus_server !== 'none') {
|
|
455
|
-
if (clientjs_option('braid_mode')) {
|
|
456
|
-
console.log('We socket-free!')
|
|
457
|
-
braid_http_mount ('/*', statebus_server)
|
|
458
|
-
} else {
|
|
459
|
-
bus.net_mount ('/*', statebus_server)
|
|
460
|
-
console.log('We going websocket!')
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
528
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
529
|
+
statebus.create_react_class = create_react_class
|
|
530
|
+
statebus.createReactClass = create_react_class
|
|
531
|
+
|
|
532
|
+
// improve_react()
|
|
533
|
+
statebus.ignore_flashbacks = false
|
|
534
|
+
bus.libs = {}
|
|
535
|
+
bus.libs.http_out = http_mount
|
|
536
|
+
bus.libs.react_class = create_react_class
|
|
537
|
+
bus.libs.input = make_better_input_17()
|
|
538
|
+
// if (statebus_server !== 'none') {
|
|
539
|
+
// if (clientjs_option('braid_mode')) {
|
|
540
|
+
// console.log('Using Braid-HTTP!')
|
|
541
|
+
// http_mount ('/*', statebus_server)
|
|
542
|
+
// } else {
|
|
543
|
+
// bus.ws_mount ('/*', statebus_server)
|
|
544
|
+
// }
|
|
545
|
+
// }
|
|
546
|
+
|
|
468
547
|
bus.net_automount()
|
|
469
548
|
|
|
470
549
|
// This /new/* code is deprecated
|
|
471
550
|
if (!clientjs_option('braid_mode')) {
|
|
472
|
-
bus('/new/*').
|
|
551
|
+
bus('/new/*').to_set = function (o) {
|
|
473
552
|
if (o.key.split('/').length > 3) return
|
|
474
553
|
|
|
475
554
|
var old_key = o.key
|
|
476
555
|
o.key = old_key + '/' + Math.random().toString(36).substring(2,12)
|
|
477
556
|
statebus.cache[o.key] = o
|
|
478
557
|
delete statebus.cache[old_key]
|
|
479
|
-
bus.
|
|
558
|
+
bus.set(o)
|
|
480
559
|
}
|
|
481
560
|
}
|
|
482
561
|
|
|
@@ -486,6 +565,17 @@
|
|
|
486
565
|
statebus.load_client_code = load_client_code
|
|
487
566
|
statebus.load_widgets = load_widgets
|
|
488
567
|
|
|
568
|
+
if (clientjs_option('globals')) {
|
|
569
|
+
// Setup globals
|
|
570
|
+
var globals = ['get', 'set', 'state']
|
|
571
|
+
|
|
572
|
+
for (var i=0; i<globals.length; i++) {
|
|
573
|
+
console.log('globalizing', globals[i], 'as',
|
|
574
|
+
eval('bus.' + globals[i]))
|
|
575
|
+
window[globals[i]] = eval('bus.' + globals[i])
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
489
579
|
document.addEventListener('DOMContentLoaded', function () {
|
|
490
580
|
if (window.statebus_ready)
|
|
491
581
|
for (var i=0; i<statebus_ready.length; i++)
|
|
@@ -605,7 +695,7 @@
|
|
|
605
695
|
for (var i=0; i<arguments.length; i++) {
|
|
606
696
|
args.push(arguments[i])
|
|
607
697
|
if (arguments[i].state)
|
|
608
|
-
args[i].src = 'data:;base64,' +
|
|
698
|
+
args[i].src = 'data:;base64,' + bus.get(args[i].state)._
|
|
609
699
|
}
|
|
610
700
|
return og_img.apply(this, args)
|
|
611
701
|
}
|
|
@@ -637,12 +727,38 @@
|
|
|
637
727
|
}
|
|
638
728
|
|
|
639
729
|
|
|
730
|
+
// This one is for react v17+
|
|
731
|
+
function make_better_input_17 () {
|
|
732
|
+
return createReactClass({
|
|
733
|
+
getInitialState: function() {
|
|
734
|
+
return {value: this.props.value}
|
|
735
|
+
},
|
|
736
|
+
UNSAVE_componentWillReceiveProps: function(new_props) {
|
|
737
|
+
this.setState({value: new_props.value})
|
|
738
|
+
},
|
|
739
|
+
onChange: function(e) {
|
|
740
|
+
this.props.onChange && this.props.onChange(e)
|
|
741
|
+
if (this.props.value)
|
|
742
|
+
this.setState({value: e.target.value})
|
|
743
|
+
},
|
|
744
|
+
render: function() {
|
|
745
|
+
var new_props = {}
|
|
746
|
+
for (var k in this.props)
|
|
747
|
+
if (this.props.hasOwnProperty(k))
|
|
748
|
+
new_props[k] = this.props[k]
|
|
749
|
+
if (this.state.value) new_props.value = this.state.value
|
|
750
|
+
new_props.onChange = this.onChange
|
|
751
|
+
return React.createElement('input', new_props)
|
|
752
|
+
}
|
|
753
|
+
})
|
|
754
|
+
}
|
|
755
|
+
|
|
640
756
|
// Load the components
|
|
641
757
|
var users_widgets = {}
|
|
642
758
|
function make_component(name, func) {
|
|
643
759
|
// Define the component
|
|
644
760
|
|
|
645
|
-
window[name] = users_widgets[name] =
|
|
761
|
+
window[name] = users_widgets[name] = statebus.create_react_class({
|
|
646
762
|
displayName: name,
|
|
647
763
|
render: function () {
|
|
648
764
|
var args = []
|