statebus 7.0.3 → 7.0.6
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/{clients.js → client-library.js} +310 -281
- package/extras/coffee.js +12 -0
- package/extras/sockjs.js +27 -0
- package/extras/tests.js +110 -106
- package/package.json +6 -4
- package/{servers.js → server-library.js} +338 -247
- package/statebus.js +140 -77
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
var websocket_prefix = (clientjs_option('websocket_path')
|
|
3
3
|
|| '_connect_to_statebus_')
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
})
|
|
5
|
+
var react_render = ReactDOM.render
|
|
6
|
+
// make_client_statebus_maker()
|
|
7
|
+
window.bus = window.statebus()
|
|
8
|
+
bus.label = 'bus'
|
|
9
|
+
|
|
10
|
+
bus.libs = {}
|
|
11
|
+
bus.libs.react12 = {}
|
|
12
|
+
bus.libs.react17 = {}
|
|
14
13
|
|
|
15
14
|
// ****************
|
|
16
15
|
// Connecting over the Network
|
|
@@ -43,37 +42,43 @@
|
|
|
43
42
|
// return new SockJS(url + '/' + websocket_prefix)
|
|
44
43
|
}
|
|
45
44
|
function client_creds (server_url) {
|
|
45
|
+
// This function is only used for websocket connections.
|
|
46
|
+
// http connections set the cookie on the server.
|
|
46
47
|
var me = bus.get('ls/me')
|
|
47
48
|
bus.log('connect: me is', me)
|
|
48
49
|
if (!me.client) {
|
|
49
50
|
// Create a client id if we have none yet.
|
|
50
51
|
// Either from a cookie set by server, or a new one from scratch.
|
|
51
|
-
var c = get_cookie('
|
|
52
|
+
var c = get_cookie('peer')
|
|
52
53
|
me.client = c || (Math.random().toString(36).substring(2)
|
|
53
54
|
+ Math.random().toString(36).substring(2)
|
|
54
55
|
+ Math.random().toString(36).substring(2))
|
|
55
56
|
bus.set(me)
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
set_cookie('
|
|
59
|
+
set_cookie('peer', me.client)
|
|
59
60
|
return {clientid: me.client}
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
bus.libs.http_out = (prefix, url) => {
|
|
63
64
|
var preprefix = prefix.slice(0,-1)
|
|
64
65
|
var has_prefix = new RegExp('^' + preprefix)
|
|
65
66
|
var is_absolute = /^https?:\/\//
|
|
66
67
|
var subscriptions = {}
|
|
67
68
|
var put_counter = 0
|
|
68
69
|
|
|
69
|
-
function add_prefix (
|
|
70
|
-
return is_absolute.test(
|
|
71
|
-
function rem_prefix (
|
|
72
|
-
return has_prefix.test(
|
|
70
|
+
function add_prefix (url) {
|
|
71
|
+
return is_absolute.test(url) ? url : preprefix + url }
|
|
72
|
+
function rem_prefix (url) {
|
|
73
|
+
return has_prefix.test(url) ? url.substr(preprefix.length) : url }
|
|
73
74
|
function add_prefixes (obj) {
|
|
74
|
-
|
|
75
|
+
var keyed = bus.translate_keys(bus.clone(obj), add_prefix)
|
|
76
|
+
return bus.translate_links(bus.clone(keyed), add_prefix)
|
|
77
|
+
}
|
|
75
78
|
function rem_prefixes (obj) {
|
|
76
|
-
|
|
79
|
+
var keyed = bus.translate_keys(bus.clone(obj), rem_prefix)
|
|
80
|
+
return bus.translate_links(bus.clone(keyed), rem_prefix)
|
|
81
|
+
}
|
|
77
82
|
|
|
78
83
|
var puts = new Map()
|
|
79
84
|
function enqueue_put (url, body) {
|
|
@@ -112,14 +117,15 @@
|
|
|
112
117
|
setTimeout(function () {send_put(id)}, 1000)
|
|
113
118
|
}
|
|
114
119
|
function send_all_puts () {
|
|
115
|
-
|
|
116
|
-
if (
|
|
120
|
+
puts.forEach(function (value, id) {
|
|
121
|
+
if (value.status === 'waiting') {
|
|
117
122
|
console.log('Sending waiting put', id)
|
|
118
123
|
send_put(id)
|
|
119
124
|
}
|
|
125
|
+
})
|
|
120
126
|
}
|
|
121
127
|
|
|
122
|
-
bus(prefix).
|
|
128
|
+
bus(prefix).setter = function (obj, t) {
|
|
123
129
|
bus.set.fire(obj)
|
|
124
130
|
|
|
125
131
|
var put = {
|
|
@@ -134,7 +140,7 @@
|
|
|
134
140
|
send_put(put_id)
|
|
135
141
|
}
|
|
136
142
|
|
|
137
|
-
bus(prefix).
|
|
143
|
+
bus(prefix).getter = function (key, t) {
|
|
138
144
|
// Subscription can be in states:
|
|
139
145
|
// - connecting
|
|
140
146
|
// - connected
|
|
@@ -212,16 +218,35 @@
|
|
|
212
218
|
}
|
|
213
219
|
}
|
|
214
220
|
}
|
|
215
|
-
bus(prefix).
|
|
221
|
+
bus(prefix).forgetter = function (key) {
|
|
216
222
|
subscriptions[key].status = 'aborted'
|
|
217
223
|
subscriptions[key].aborter.abort()
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
226
|
|
|
227
|
+
function http_automount () {
|
|
228
|
+
function get_domain (key) { // Returns e.g. "state://foo.com"
|
|
229
|
+
var m = key.match(/^https?\:\/\/(([^:\/?#]*)(?:\:([0-9]+))?)/)
|
|
230
|
+
return m && m[0]
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
var old_route = bus.route
|
|
234
|
+
var connections = {}
|
|
235
|
+
bus.route = function (key, method, arg, t) {
|
|
236
|
+
var d = get_domain(key)
|
|
237
|
+
if (d && !connections[d]) {
|
|
238
|
+
bus.libs.http_out(d + '/*', d + '/')
|
|
239
|
+
connections[d] = true
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return old_route(key, method, arg, t)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
221
246
|
|
|
222
247
|
// ****************
|
|
223
248
|
// Manipulate Localstorage
|
|
224
|
-
|
|
249
|
+
bus.libs.localstorage = (prefix) => {
|
|
225
250
|
try { localStorage } catch (e) { return }
|
|
226
251
|
|
|
227
252
|
// Sets are queued up, to store values with a delay, in batch
|
|
@@ -235,11 +260,11 @@
|
|
|
235
260
|
sets_are_pending = false
|
|
236
261
|
}
|
|
237
262
|
|
|
238
|
-
bus(prefix).
|
|
263
|
+
bus(prefix).getter = function (key) {
|
|
239
264
|
var result = localStorage.getItem(key)
|
|
240
265
|
return result ? JSON.parse(result) : {key: key}
|
|
241
266
|
}
|
|
242
|
-
bus(prefix).
|
|
267
|
+
bus(prefix).setter = function (obj) {
|
|
243
268
|
// Do I need to make this recurse into the object?
|
|
244
269
|
bus.log('localStore: on_set:', obj.key)
|
|
245
270
|
pending_sets[obj.key] = obj
|
|
@@ -250,7 +275,7 @@
|
|
|
250
275
|
bus.set.fire(obj)
|
|
251
276
|
return obj
|
|
252
277
|
}
|
|
253
|
-
bus(prefix).
|
|
278
|
+
bus(prefix).deleter = function (key) { localStorage.removeItem(key) }
|
|
254
279
|
|
|
255
280
|
|
|
256
281
|
// Hm... this update stuff doesn't seem to work on file:/// urls in chrome
|
|
@@ -283,7 +308,7 @@
|
|
|
283
308
|
// - Change the key prefix
|
|
284
309
|
// - Set this into the cache
|
|
285
310
|
|
|
286
|
-
bus(prefix).
|
|
311
|
+
bus(prefix).setter = function (obj) {
|
|
287
312
|
window.history.replaceState(
|
|
288
313
|
'',
|
|
289
314
|
'',
|
|
@@ -461,46 +486,19 @@
|
|
|
461
486
|
// ### Full-featured single-file app methods
|
|
462
487
|
// ###
|
|
463
488
|
|
|
464
|
-
function make_client_statebus_maker () {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
function load_scripts() {
|
|
480
|
-
// console.info('Loading scripts! if', !!!window.statebus)
|
|
481
|
-
if (!window.statebus) {
|
|
482
|
-
var statebus_dir = clientjs_option('src')
|
|
483
|
-
if (statebus_dir) statebus_dir = statebus_dir.match(/(.*)[\/\\]/)
|
|
484
|
-
if (statebus_dir) statebus_dir = statebus_dir[1] + '/'
|
|
485
|
-
else statebus_dir = ''
|
|
486
|
-
|
|
487
|
-
// var js_urls = {
|
|
488
|
-
// react: statebus_dir + 'extras/react.js',
|
|
489
|
-
// sockjs: statebus_dir + 'extras/sockjs.js',
|
|
490
|
-
// coffee: statebus_dir + 'extras/coffee.js',
|
|
491
|
-
// statebus: statebus_dir + 'statebus.js'
|
|
492
|
-
// }
|
|
493
|
-
// if (statebus_dir == 'https://stateb.us/')
|
|
494
|
-
// js_urls.statebus = statebus_dir + 'statebus4.js'
|
|
495
|
-
|
|
496
|
-
// for (var name in js_urls)
|
|
497
|
-
// document.write('<script src="' + js_urls[name] + '" charset="utf-8"></script>')
|
|
498
|
-
|
|
499
|
-
document.addEventListener('DOMContentLoaded', scripts_ready, false)
|
|
500
|
-
}
|
|
501
|
-
else
|
|
502
|
-
scripts_ready()
|
|
503
|
-
}
|
|
489
|
+
// function make_client_statebus_maker () {
|
|
490
|
+
// var extra_stuff = ['make_websocket client_creds',
|
|
491
|
+
// 'url_store components'].join(' ').split(' ')
|
|
492
|
+
// if (window.statebus) {
|
|
493
|
+
// var orig_statebus = statebus
|
|
494
|
+
// window.statebus = function make_client_bus () {
|
|
495
|
+
// var bus = orig_statebus()
|
|
496
|
+
// for (var i=0; i<extra_stuff.length; i++)
|
|
497
|
+
// bus[extra_stuff[i]] = eval(extra_stuff[i])
|
|
498
|
+
// return bus
|
|
499
|
+
// }
|
|
500
|
+
// }
|
|
501
|
+
// }
|
|
504
502
|
|
|
505
503
|
function clientjs_option (option_name) {
|
|
506
504
|
// This function must be copy/paste synchronized with statebus.js. Be
|
|
@@ -512,97 +510,35 @@
|
|
|
512
510
|
|
|
513
511
|
// Todo: remove this global
|
|
514
512
|
window.statebus_server = clientjs_option('server')
|
|
515
|
-
var react_render
|
|
516
|
-
function scripts_ready () {
|
|
517
|
-
react_render = ReactDOM.render
|
|
518
|
-
// make_client_statebus_maker()
|
|
519
|
-
window.bus = window.statebus()
|
|
520
|
-
bus.label = 'bus'
|
|
521
|
-
|
|
522
|
-
statebus.create_react_class = create_react_class
|
|
523
|
-
statebus.createReactClass = create_react_class
|
|
524
|
-
|
|
525
|
-
// improve_react()
|
|
526
|
-
statebus.ignore_flashbacks = false
|
|
527
|
-
bus.libs = {}
|
|
528
|
-
bus.libs.http_out = http_mount
|
|
529
|
-
bus.libs.react_class = create_react_class
|
|
530
|
-
bus.libs.input = make_better_input_17()
|
|
531
|
-
bus.libs.localstorage = localstorage_client
|
|
532
|
-
|
|
533
|
-
// if (statebus_server !== 'none') {
|
|
534
|
-
// if (clientjs_option('braid_mode')) {
|
|
535
|
-
// console.log('Using Braid-HTTP!')
|
|
536
|
-
// http_mount ('/*', statebus_server)
|
|
537
|
-
// } else {
|
|
538
|
-
// bus.ws_mount ('/*', statebus_server)
|
|
539
|
-
// }
|
|
540
|
-
// }
|
|
541
|
-
|
|
542
|
-
bus.net_automount()
|
|
543
513
|
|
|
544
|
-
|
|
545
|
-
if (!
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
var old_key = o.key
|
|
550
|
-
o.key = old_key + '/' + Math.random().toString(36).substring(2,12)
|
|
551
|
-
statebus.cache[o.key] = o
|
|
552
|
-
delete statebus.cache[old_key]
|
|
553
|
-
bus.set(o)
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
load_coffee()
|
|
514
|
+
function is_css_prop (name) {
|
|
515
|
+
if (!is_css_prop.memoized) {
|
|
516
|
+
// Precompute all the css props
|
|
517
|
+
is_css_prop.memoized = {}
|
|
558
518
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
519
|
+
// We used to get all_css_props like this:
|
|
520
|
+
//
|
|
521
|
+
// var all_css_props = Object.keys(document.body.style)
|
|
522
|
+
// if (all_css_props.length < 100) // Firefox
|
|
523
|
+
// all_css_props = Object.keys(document.body.style.__proto__)
|
|
524
|
+
//
|
|
525
|
+
// But now I've hard-coded them:
|
|
526
|
+
var all_css_props = ["alignContent","alignItems","alignSelf","alignmentBaseline","all","animation","animationDelay","animationDirection","animationDuration","animationFillMode","animationIterationCount","animationName","animationPlayState","animationTimingFunction","backfaceVisibility","background","backgroundAttachment","backgroundBlendMode","backgroundClip","backgroundColor","backgroundImage","backgroundOrigin","backgroundPosition","backgroundPositionX","backgroundPositionY","backgroundRepeat","backgroundRepeatX","backgroundRepeatY","backgroundSize","baselineShift","blockSize","border","borderBottom","borderBottomColor","borderBottomLeftRadius","borderBottomRightRadius","borderBottomStyle","borderBottomWidth","borderCollapse","borderColor","borderImage","borderImageOutset","borderImageRepeat","borderImageSlice","borderImageSource","borderImageWidth","borderLeft","borderLeftColor","borderLeftStyle","borderLeftWidth","borderRadius","borderRight","borderRightColor","borderRightStyle","borderRightWidth","borderSpacing","borderStyle","borderTop","borderTopColor","borderTopLeftRadius","borderTopRightRadius","borderTopStyle","borderTopWidth","borderWidth","bottom","boxShadow","boxSizing","breakAfter","breakBefore","breakInside","bufferedRendering","captionSide","caretColor","clear","clip","clipPath","clipRule","color","colorInterpolation","colorInterpolationFilters","colorRendering","columnCount","columnFill","columnGap","columnRule","columnRuleColor","columnRuleStyle","columnRuleWidth","columnSpan","columnWidth","columns","contain","content","counterIncrement","counterReset","cursor","cx","cy","d","direction","display","dominantBaseline","emptyCells","fill","fillOpacity","fillRule","filter","flex","flexBasis","flexDirection","flexFlow","flexGrow","flexShrink","flexWrap","float","floodColor","floodOpacity","font","fontDisplay","fontFamily","fontFeatureSettings","fontKerning","fontSize","fontStretch","fontStyle","fontVariant","fontVariantCaps","fontVariantEastAsian","fontVariantLigatures","fontVariantNumeric","fontVariationSettings","fontWeight","gap","grid","gridArea","gridAutoColumns","gridAutoFlow","gridAutoRows","gridColumn","gridColumnEnd","gridColumnGap","gridColumnStart","gridGap","gridRow","gridRowEnd","gridRowGap","gridRowStart","gridTemplate","gridTemplateAreas","gridTemplateColumns","gridTemplateRows","height","hyphens","imageRendering","inlineSize","isolation","justifyContent","justifyItems","justifySelf","left","letterSpacing","lightingColor","lineBreak","lineHeight","listStyle","listStyleImage","listStylePosition","listStyleType","margin","marginBottom","marginLeft","marginRight","marginTop","marker","markerEnd","markerMid","markerStart","mask","maskType","maxBlockSize","maxHeight","maxInlineSize","maxWidth","maxZoom","minBlockSize","minHeight","minInlineSize","minWidth","minZoom","mixBlendMode","objectFit","objectPosition","offset","offsetDistance","offsetPath","offsetRotate","opacity","order","orientation","orphans","outline","outlineColor","outlineOffset","outlineStyle","outlineWidth","overflow","overflowAnchor","overflowWrap","overflowX","overflowY","overscrollBehavior","overscrollBehaviorX","overscrollBehaviorY","padding","paddingBottom","paddingLeft","paddingRight","paddingTop","page","pageBreakAfter","pageBreakBefore","pageBreakInside","paintOrder","perspective","perspectiveOrigin","placeContent","placeItems","placeSelf","pointerEvents","position","quotes","r","resize","right","rowGap","rx","ry","scrollBehavior","shapeImageThreshold","shapeMargin","shapeOutside","shapeRendering","size","speak","src","stopColor","stopOpacity","stroke","strokeDasharray","strokeDashoffset","strokeLinecap","strokeLinejoin","strokeMiterlimit","strokeOpacity","strokeWidth","tabSize","tableLayout","textAlign","textAlignLast","textAnchor","textCombineUpright","textDecoration","textDecorationColor","textDecorationLine","textDecorationSkipInk","textDecorationStyle","textIndent","textOrientation","textOverflow","textRendering","textShadow","textSizeAdjust","textTransform","textUnderlinePosition","top","touchAction","transform","transformBox","transformOrigin","transformStyle","transition","transitionDelay","transitionDuration","transitionProperty","transitionTimingFunction","unicodeBidi","unicodeRange","userSelect","userZoom","vectorEffect","verticalAlign","visibility","webkitAlignContent","webkitAlignItems","webkitAlignSelf","webkitAnimation","webkitAnimationDelay","webkitAnimationDirection","webkitAnimationDuration","webkitAnimationFillMode","webkitAnimationIterationCount","webkitAnimationName","webkitAnimationPlayState","webkitAnimationTimingFunction","webkitAppRegion","webkitAppearance","webkitBackfaceVisibility","webkitBackgroundClip","webkitBackgroundOrigin","webkitBackgroundSize","webkitBorderAfter","webkitBorderAfterColor","webkitBorderAfterStyle","webkitBorderAfterWidth","webkitBorderBefore","webkitBorderBeforeColor","webkitBorderBeforeStyle","webkitBorderBeforeWidth","webkitBorderBottomLeftRadius","webkitBorderBottomRightRadius","webkitBorderEnd","webkitBorderEndColor","webkitBorderEndStyle","webkitBorderEndWidth","webkitBorderHorizontalSpacing","webkitBorderImage","webkitBorderRadius","webkitBorderStart","webkitBorderStartColor","webkitBorderStartStyle","webkitBorderStartWidth","webkitBorderTopLeftRadius","webkitBorderTopRightRadius","webkitBorderVerticalSpacing","webkitBoxAlign","webkitBoxDecorationBreak","webkitBoxDirection","webkitBoxFlex","webkitBoxOrdinalGroup","webkitBoxOrient","webkitBoxPack","webkitBoxReflect","webkitBoxShadow","webkitBoxSizing","webkitClipPath","webkitColumnBreakAfter","webkitColumnBreakBefore","webkitColumnBreakInside","webkitColumnCount","webkitColumnGap","webkitColumnRule","webkitColumnRuleColor","webkitColumnRuleStyle","webkitColumnRuleWidth","webkitColumnSpan","webkitColumnWidth","webkitColumns","webkitFilter","webkitFlex","webkitFlexBasis","webkitFlexDirection","webkitFlexFlow","webkitFlexGrow","webkitFlexShrink","webkitFlexWrap","webkitFontFeatureSettings","webkitFontSizeDelta","webkitFontSmoothing","webkitHighlight","webkitHyphenateCharacter","webkitJustifyContent","webkitLineBreak","webkitLineClamp","webkitLocale","webkitLogicalHeight","webkitLogicalWidth","webkitMarginAfter","webkitMarginAfterCollapse","webkitMarginBefore","webkitMarginBeforeCollapse","webkitMarginBottomCollapse","webkitMarginCollapse","webkitMarginEnd","webkitMarginStart","webkitMarginTopCollapse","webkitMask","webkitMaskBoxImage","webkitMaskBoxImageOutset","webkitMaskBoxImageRepeat","webkitMaskBoxImageSlice","webkitMaskBoxImageSource","webkitMaskBoxImageWidth","webkitMaskClip","webkitMaskComposite","webkitMaskImage","webkitMaskOrigin","webkitMaskPosition","webkitMaskPositionX","webkitMaskPositionY","webkitMaskRepeat","webkitMaskRepeatX","webkitMaskRepeatY","webkitMaskSize","webkitMaxLogicalHeight","webkitMaxLogicalWidth","webkitMinLogicalHeight","webkitMinLogicalWidth","webkitOpacity","webkitOrder","webkitPaddingAfter","webkitPaddingBefore","webkitPaddingEnd","webkitPaddingStart","webkitPerspective","webkitPerspectiveOrigin","webkitPerspectiveOriginX","webkitPerspectiveOriginY","webkitPrintColorAdjust","webkitRtlOrdering","webkitRubyPosition","webkitShapeImageThreshold","webkitShapeMargin","webkitShapeOutside","webkitTapHighlightColor","webkitTextCombine","webkitTextDecorationsInEffect","webkitTextEmphasis","webkitTextEmphasisColor","webkitTextEmphasisPosition","webkitTextEmphasisStyle","webkitTextFillColor","webkitTextOrientation","webkitTextSecurity","webkitTextSizeAdjust","webkitTextStroke","webkitTextStrokeColor","webkitTextStrokeWidth","webkitTransform","webkitTransformOrigin","webkitTransformOriginX","webkitTransformOriginY","webkitTransformOriginZ","webkitTransformStyle","webkitTransition","webkitTransitionDelay","webkitTransitionDuration","webkitTransitionProperty","webkitTransitionTimingFunction","webkitUserDrag","webkitUserModify","webkitUserSelect","webkitWritingMode","whiteSpace","widows","width","willChange","wordBreak","wordSpacing","wordWrap","writingMode","x","y","zIndex","zoom"]
|
|
562
527
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
var globals = ['get', 'set', 'state']
|
|
528
|
+
var ignore = {d:1, cx:1, cy:1, rx:1, ry:1, x:1, y:1,
|
|
529
|
+
content:1, fill:1, stroke:1, src:1}
|
|
566
530
|
|
|
567
|
-
for (var i=0; i<
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
window[globals[i]] = eval('bus.' + globals[i])
|
|
571
|
-
}
|
|
531
|
+
for (var i=0; i<all_css_props.length; i++)
|
|
532
|
+
if (!ignore[all_css_props[i]])
|
|
533
|
+
is_css_prop.memoized[all_css_props[i]] = true
|
|
572
534
|
}
|
|
573
|
-
|
|
574
|
-
document.addEventListener('DOMContentLoaded', function () {
|
|
575
|
-
if (window.statebus_ready)
|
|
576
|
-
for (var i=0; i<statebus_ready.length; i++)
|
|
577
|
-
statebus_ready[i]()
|
|
578
|
-
}, false)
|
|
579
|
-
|
|
580
|
-
document.addEventListener('DOMContentLoaded', load_widgets, false)
|
|
581
|
-
|
|
582
|
-
// if (dom.Body || dom.body || dom.BODY)
|
|
583
|
-
// react_render((window.Body || window.body || window.BODY)(), document.body)
|
|
535
|
+
return is_css_prop.memoized[name]
|
|
584
536
|
}
|
|
585
537
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
// We used to get all_css_props like this:
|
|
592
|
-
//
|
|
593
|
-
// var all_css_props = Object.keys(document.body.style)
|
|
594
|
-
// if (all_css_props.length < 100) // Firefox
|
|
595
|
-
// all_css_props = Object.keys(document.body.style.__proto__)
|
|
596
|
-
//
|
|
597
|
-
// But now I've hard-coded them:
|
|
598
|
-
var all_css_props = ["alignContent","alignItems","alignSelf","alignmentBaseline","all","animation","animationDelay","animationDirection","animationDuration","animationFillMode","animationIterationCount","animationName","animationPlayState","animationTimingFunction","backfaceVisibility","background","backgroundAttachment","backgroundBlendMode","backgroundClip","backgroundColor","backgroundImage","backgroundOrigin","backgroundPosition","backgroundPositionX","backgroundPositionY","backgroundRepeat","backgroundRepeatX","backgroundRepeatY","backgroundSize","baselineShift","blockSize","border","borderBottom","borderBottomColor","borderBottomLeftRadius","borderBottomRightRadius","borderBottomStyle","borderBottomWidth","borderCollapse","borderColor","borderImage","borderImageOutset","borderImageRepeat","borderImageSlice","borderImageSource","borderImageWidth","borderLeft","borderLeftColor","borderLeftStyle","borderLeftWidth","borderRadius","borderRight","borderRightColor","borderRightStyle","borderRightWidth","borderSpacing","borderStyle","borderTop","borderTopColor","borderTopLeftRadius","borderTopRightRadius","borderTopStyle","borderTopWidth","borderWidth","bottom","boxShadow","boxSizing","breakAfter","breakBefore","breakInside","bufferedRendering","captionSide","caretColor","clear","clip","clipPath","clipRule","color","colorInterpolation","colorInterpolationFilters","colorRendering","columnCount","columnFill","columnGap","columnRule","columnRuleColor","columnRuleStyle","columnRuleWidth","columnSpan","columnWidth","columns","contain","content","counterIncrement","counterReset","cursor","cx","cy","d","direction","display","dominantBaseline","emptyCells","fill","fillOpacity","fillRule","filter","flex","flexBasis","flexDirection","flexFlow","flexGrow","flexShrink","flexWrap","float","floodColor","floodOpacity","font","fontDisplay","fontFamily","fontFeatureSettings","fontKerning","fontSize","fontStretch","fontStyle","fontVariant","fontVariantCaps","fontVariantEastAsian","fontVariantLigatures","fontVariantNumeric","fontVariationSettings","fontWeight","gap","grid","gridArea","gridAutoColumns","gridAutoFlow","gridAutoRows","gridColumn","gridColumnEnd","gridColumnGap","gridColumnStart","gridGap","gridRow","gridRowEnd","gridRowGap","gridRowStart","gridTemplate","gridTemplateAreas","gridTemplateColumns","gridTemplateRows","height","hyphens","imageRendering","inlineSize","isolation","justifyContent","justifyItems","justifySelf","left","letterSpacing","lightingColor","lineBreak","lineHeight","listStyle","listStyleImage","listStylePosition","listStyleType","margin","marginBottom","marginLeft","marginRight","marginTop","marker","markerEnd","markerMid","markerStart","mask","maskType","maxBlockSize","maxHeight","maxInlineSize","maxWidth","maxZoom","minBlockSize","minHeight","minInlineSize","minWidth","minZoom","mixBlendMode","objectFit","objectPosition","offset","offsetDistance","offsetPath","offsetRotate","opacity","order","orientation","orphans","outline","outlineColor","outlineOffset","outlineStyle","outlineWidth","overflow","overflowAnchor","overflowWrap","overflowX","overflowY","overscrollBehavior","overscrollBehaviorX","overscrollBehaviorY","padding","paddingBottom","paddingLeft","paddingRight","paddingTop","page","pageBreakAfter","pageBreakBefore","pageBreakInside","paintOrder","perspective","perspectiveOrigin","placeContent","placeItems","placeSelf","pointerEvents","position","quotes","r","resize","right","rowGap","rx","ry","scrollBehavior","shapeImageThreshold","shapeMargin","shapeOutside","shapeRendering","size","speak","src","stopColor","stopOpacity","stroke","strokeDasharray","strokeDashoffset","strokeLinecap","strokeLinejoin","strokeMiterlimit","strokeOpacity","strokeWidth","tabSize","tableLayout","textAlign","textAlignLast","textAnchor","textCombineUpright","textDecoration","textDecorationColor","textDecorationLine","textDecorationSkipInk","textDecorationStyle","textIndent","textOrientation","textOverflow","textRendering","textShadow","textSizeAdjust","textTransform","textUnderlinePosition","top","touchAction","transform","transformBox","transformOrigin","transformStyle","transition","transitionDelay","transitionDuration","transitionProperty","transitionTimingFunction","unicodeBidi","unicodeRange","userSelect","userZoom","vectorEffect","verticalAlign","visibility","webkitAlignContent","webkitAlignItems","webkitAlignSelf","webkitAnimation","webkitAnimationDelay","webkitAnimationDirection","webkitAnimationDuration","webkitAnimationFillMode","webkitAnimationIterationCount","webkitAnimationName","webkitAnimationPlayState","webkitAnimationTimingFunction","webkitAppRegion","webkitAppearance","webkitBackfaceVisibility","webkitBackgroundClip","webkitBackgroundOrigin","webkitBackgroundSize","webkitBorderAfter","webkitBorderAfterColor","webkitBorderAfterStyle","webkitBorderAfterWidth","webkitBorderBefore","webkitBorderBeforeColor","webkitBorderBeforeStyle","webkitBorderBeforeWidth","webkitBorderBottomLeftRadius","webkitBorderBottomRightRadius","webkitBorderEnd","webkitBorderEndColor","webkitBorderEndStyle","webkitBorderEndWidth","webkitBorderHorizontalSpacing","webkitBorderImage","webkitBorderRadius","webkitBorderStart","webkitBorderStartColor","webkitBorderStartStyle","webkitBorderStartWidth","webkitBorderTopLeftRadius","webkitBorderTopRightRadius","webkitBorderVerticalSpacing","webkitBoxAlign","webkitBoxDecorationBreak","webkitBoxDirection","webkitBoxFlex","webkitBoxOrdinalGroup","webkitBoxOrient","webkitBoxPack","webkitBoxReflect","webkitBoxShadow","webkitBoxSizing","webkitClipPath","webkitColumnBreakAfter","webkitColumnBreakBefore","webkitColumnBreakInside","webkitColumnCount","webkitColumnGap","webkitColumnRule","webkitColumnRuleColor","webkitColumnRuleStyle","webkitColumnRuleWidth","webkitColumnSpan","webkitColumnWidth","webkitColumns","webkitFilter","webkitFlex","webkitFlexBasis","webkitFlexDirection","webkitFlexFlow","webkitFlexGrow","webkitFlexShrink","webkitFlexWrap","webkitFontFeatureSettings","webkitFontSizeDelta","webkitFontSmoothing","webkitHighlight","webkitHyphenateCharacter","webkitJustifyContent","webkitLineBreak","webkitLineClamp","webkitLocale","webkitLogicalHeight","webkitLogicalWidth","webkitMarginAfter","webkitMarginAfterCollapse","webkitMarginBefore","webkitMarginBeforeCollapse","webkitMarginBottomCollapse","webkitMarginCollapse","webkitMarginEnd","webkitMarginStart","webkitMarginTopCollapse","webkitMask","webkitMaskBoxImage","webkitMaskBoxImageOutset","webkitMaskBoxImageRepeat","webkitMaskBoxImageSlice","webkitMaskBoxImageSource","webkitMaskBoxImageWidth","webkitMaskClip","webkitMaskComposite","webkitMaskImage","webkitMaskOrigin","webkitMaskPosition","webkitMaskPositionX","webkitMaskPositionY","webkitMaskRepeat","webkitMaskRepeatX","webkitMaskRepeatY","webkitMaskSize","webkitMaxLogicalHeight","webkitMaxLogicalWidth","webkitMinLogicalHeight","webkitMinLogicalWidth","webkitOpacity","webkitOrder","webkitPaddingAfter","webkitPaddingBefore","webkitPaddingEnd","webkitPaddingStart","webkitPerspective","webkitPerspectiveOrigin","webkitPerspectiveOriginX","webkitPerspectiveOriginY","webkitPrintColorAdjust","webkitRtlOrdering","webkitRubyPosition","webkitShapeImageThreshold","webkitShapeMargin","webkitShapeOutside","webkitTapHighlightColor","webkitTextCombine","webkitTextDecorationsInEffect","webkitTextEmphasis","webkitTextEmphasisColor","webkitTextEmphasisPosition","webkitTextEmphasisStyle","webkitTextFillColor","webkitTextOrientation","webkitTextSecurity","webkitTextSizeAdjust","webkitTextStroke","webkitTextStrokeColor","webkitTextStrokeWidth","webkitTransform","webkitTransformOrigin","webkitTransformOriginX","webkitTransformOriginY","webkitTransformOriginZ","webkitTransformStyle","webkitTransition","webkitTransitionDelay","webkitTransitionDuration","webkitTransitionProperty","webkitTransitionTimingFunction","webkitUserDrag","webkitUserModify","webkitUserSelect","webkitWritingMode","whiteSpace","widows","width","willChange","wordBreak","wordSpacing","wordWrap","writingMode","x","y","zIndex","zoom"]
|
|
599
|
-
|
|
600
|
-
var ignore = {d:1, cx:1, cy:1, rx:1, ry:1, x:1, y:1,
|
|
601
|
-
content:1, fill:1, stroke:1, src:1}
|
|
602
|
-
var is_css_prop = {}
|
|
603
|
-
for (var i=0; i<all_css_props.length; i++)
|
|
604
|
-
if (!ignore[all_css_props[i]])
|
|
605
|
-
is_css_prop[all_css_props[i]] = true
|
|
538
|
+
// ================================================================
|
|
539
|
+
// React v12 Support
|
|
540
|
+
|
|
541
|
+
bus.libs.react12.improve_react = () => {
|
|
606
542
|
|
|
607
543
|
function better_element(el) {
|
|
608
544
|
// To do:
|
|
@@ -631,7 +567,7 @@
|
|
|
631
567
|
// Styles get redirected to the style field
|
|
632
568
|
else if (arg instanceof Object)
|
|
633
569
|
for (var k in arg)
|
|
634
|
-
if (is_css_prop
|
|
570
|
+
if (is_css_prop(k)
|
|
635
571
|
&& !(k in {width:1,height:1,size:1}
|
|
636
572
|
&& el in {canvas:1, input:1, embed:1, object:1}))
|
|
637
573
|
attrs.style[k] = arg[k] // Merge styles
|
|
@@ -654,6 +590,13 @@
|
|
|
654
590
|
for (var el in React.DOM)
|
|
655
591
|
window[el.toUpperCase()] = better_element(el)
|
|
656
592
|
|
|
593
|
+
// Fixes React controlled textarea widgets so they can work with state
|
|
594
|
+
// updates triggered by forceUpdate, rather than just setState(),
|
|
595
|
+
// because statebus keeps its own state outside of React's setState(),
|
|
596
|
+
// but react doesn't know how to preserve the cursor (and selection)
|
|
597
|
+
// position for updates unless they go through setState(). So this
|
|
598
|
+
// function just wraps input widgets with a component that uses
|
|
599
|
+
// setState().
|
|
657
600
|
function make_better_input (name, element) {
|
|
658
601
|
window[name] = React.createFactory(React.createClass({
|
|
659
602
|
getInitialState: function() {
|
|
@@ -711,24 +654,141 @@
|
|
|
711
654
|
}
|
|
712
655
|
}
|
|
713
656
|
|
|
714
|
-
|
|
715
|
-
|
|
657
|
+
bus.libs.react17.reactive_dom = () => {
|
|
658
|
+
// The window.dom object lets the user define new react components as
|
|
659
|
+
// functions
|
|
660
|
+
window.dom = window.dom || new Proxy({}, {
|
|
661
|
+
get: function (o, k) { return o[k] },
|
|
662
|
+
set: function (o, k, v) {
|
|
663
|
+
o[k] = v
|
|
664
|
+
make_component(k, v)
|
|
665
|
+
return true
|
|
666
|
+
}
|
|
667
|
+
})
|
|
716
668
|
|
|
717
|
-
//
|
|
718
|
-
var
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
669
|
+
// We'll define functions for all HTML tags...
|
|
670
|
+
var function_for_tag = (tag) =>
|
|
671
|
+
(...arguments) => {
|
|
672
|
+
var children = []
|
|
673
|
+
var attrs = {style: {}}
|
|
674
|
+
|
|
675
|
+
for (var i=0; i<arguments.length; i++) {
|
|
676
|
+
var arg = arguments[i]
|
|
677
|
+
|
|
678
|
+
if (arg === undefined)
|
|
679
|
+
continue
|
|
680
|
+
|
|
681
|
+
// Strings, DOM nodes, and arrays become children
|
|
682
|
+
else if (typeof arg === 'string' // For "foo"
|
|
683
|
+
|| arg instanceof String // For new String()
|
|
684
|
+
|| arg && React.isValidElement(arg)
|
|
685
|
+
|| arg instanceof Array)
|
|
686
|
+
children.push(arg)
|
|
687
|
+
|
|
688
|
+
// // Arrays append onto the children
|
|
689
|
+
// else if (arg instanceof Array)
|
|
690
|
+
// Array.prototype.push.apply(children, arg)
|
|
691
|
+
|
|
692
|
+
// Pure objects get merged into object city
|
|
693
|
+
// Styles get redirected to the style field
|
|
694
|
+
else if (arg instanceof Object)
|
|
695
|
+
for (var k in arg)
|
|
696
|
+
if (is_css_prop(k)
|
|
697
|
+
&& !(k in {width:1,height:1,size:1}
|
|
698
|
+
&& tag in {canvas:1, input:1, embed:1, object:1}))
|
|
699
|
+
attrs.style[k] = arg[k] // Merge styles
|
|
700
|
+
else if (k === 'style') // Merge insides of style tags
|
|
701
|
+
for (var k2 in arg[k])
|
|
702
|
+
attrs.style[k2] = arg[k][k2]
|
|
703
|
+
else
|
|
704
|
+
attrs[k] = arg[k] // Or be normal.
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// Now call React.createElement(tag, attrs, children...)
|
|
708
|
+
return React.createElement.apply(
|
|
709
|
+
null,
|
|
710
|
+
[tag, attrs].concat(children)
|
|
711
|
+
)
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// ... or at least most of them -- there are just a few missing from
|
|
715
|
+
// this list.
|
|
716
|
+
var all_tags = 'a,abbr,address,area,article,aside,audio,b,base,bdi,bdo,blockquote,body,br,button,canvas,caption,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dialog,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,i,iframe,img,ins,kbd,label,legend,li,link,main,map,mark,menu,meta,meter,nav,noscript,object,ol,optgroup,option,output,p,param,picture,pre,progress,q,s,samp,script,section,select,slot,small,source,span,strong,style,sub,summary,sup,table,tbody,td,template,tfoot,th,thead,title,tr,u,ul,video,input'.split(',')
|
|
717
|
+
all_tags.forEach((tagname) => {
|
|
718
|
+
window[tagname.toUpperCase()] = function_for_tag(tagname)
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
// We create special functions for INPUT and TEXTAREA, because they
|
|
722
|
+
// have to do extra work to maintain the cursor when we use statebus
|
|
723
|
+
// instead of React's setState() for state updates.
|
|
724
|
+
window.INPUT = function_for_tag(make_fixed_textbox('input'))
|
|
725
|
+
window.TEXTAREA = function_for_tag(make_fixed_textbox('textarea'))
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
// Improve the functions ^^^ put this above
|
|
729
|
+
function better_element(el) {
|
|
730
|
+
// To do:
|
|
731
|
+
// - Don't put all args into a children array, cause react thinks
|
|
732
|
+
// that means they need a key.
|
|
733
|
+
|
|
734
|
+
return function () {
|
|
735
|
+
var children = []
|
|
736
|
+
var attrs = {style: {}}
|
|
737
|
+
|
|
738
|
+
for (var i=0; i<arguments.length; i++) {
|
|
739
|
+
var arg = arguments[i]
|
|
740
|
+
|
|
741
|
+
// Strings and DOM nodes and undefined become children
|
|
742
|
+
if (typeof arg === 'string' // For "foo"
|
|
743
|
+
|| arg instanceof String // For new String()
|
|
744
|
+
|| arg && React.isValidElement(arg)
|
|
745
|
+
|| arg === undefined)
|
|
746
|
+
children.push(arg)
|
|
723
747
|
|
|
748
|
+
// Arrays append onto the children
|
|
749
|
+
else if (arg instanceof Array)
|
|
750
|
+
Array.prototype.push.apply(children, arg)
|
|
751
|
+
|
|
752
|
+
// Pure objects get merged into object city
|
|
753
|
+
// Styles get redirected to the style field
|
|
754
|
+
else if (arg instanceof Object)
|
|
755
|
+
for (var k in arg)
|
|
756
|
+
if (is_css_prop(k)
|
|
757
|
+
&& !(k in {width:1,height:1,size:1}
|
|
758
|
+
&& el in {canvas:1, input:1, embed:1, object:1}))
|
|
759
|
+
attrs.style[k] = arg[k] // Merge styles
|
|
760
|
+
else if (k === 'style') // Merge insides of style tags
|
|
761
|
+
for (var k2 in arg[k])
|
|
762
|
+
attrs.style[k2] = arg[k][k2]
|
|
763
|
+
else {
|
|
764
|
+
attrs[k] = arg[k] // Or be normal.
|
|
765
|
+
|
|
766
|
+
if (k === 'key')
|
|
767
|
+
attrs['data-key'] = arg[k]
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
if (children.length === 0) children = undefined
|
|
771
|
+
return React.DOM[el](attrs, children)
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
724
775
|
|
|
725
|
-
//
|
|
726
|
-
|
|
776
|
+
// Fixes React controlled textarea widgets so they can work with state
|
|
777
|
+
// updates triggered by forceUpdate, rather than just setState(),
|
|
778
|
+
// because statebus keeps its own state outside of React's setState(),
|
|
779
|
+
// but react doesn't know how to preserve the cursor (and selection)
|
|
780
|
+
// position for updates unless they go through setState(). So this
|
|
781
|
+
// function just wraps input widgets with a component that uses
|
|
782
|
+
// setState().
|
|
783
|
+
//
|
|
784
|
+
// This one is for react v17+.
|
|
785
|
+
function make_fixed_textbox (tagname) {
|
|
786
|
+
// `tagname` can be either "input" or "textarea"
|
|
727
787
|
return createReactClass({
|
|
728
788
|
getInitialState: function() {
|
|
729
789
|
return {value: this.props.value}
|
|
730
790
|
},
|
|
731
|
-
|
|
791
|
+
UNSAFE_componentWillReceiveProps: function(new_props) {
|
|
732
792
|
this.setState({value: new_props.value})
|
|
733
793
|
},
|
|
734
794
|
onChange: function(e) {
|
|
@@ -741,19 +801,30 @@
|
|
|
741
801
|
for (var k in this.props)
|
|
742
802
|
if (this.props.hasOwnProperty(k))
|
|
743
803
|
new_props[k] = this.props[k]
|
|
744
|
-
if (this.state.value)
|
|
804
|
+
if (this.state.hasOwnProperty('value'))
|
|
805
|
+
new_props.value = this.state.value
|
|
745
806
|
new_props.onChange = this.onChange
|
|
746
|
-
return React.createElement(
|
|
807
|
+
return React.createElement(tagname, new_props)
|
|
747
808
|
}
|
|
748
809
|
})
|
|
749
810
|
}
|
|
750
811
|
|
|
812
|
+
function autodetect_args (func) {
|
|
813
|
+
if (func.args) return
|
|
814
|
+
|
|
815
|
+
// Get an array of the func's params
|
|
816
|
+
var comments = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,
|
|
817
|
+
params = /([^\s,]+)/g,
|
|
818
|
+
s = func.toString().replace(comments, '')
|
|
819
|
+
func.args = s.slice(s.indexOf('(')+1, s.indexOf(')')).match(params) || []
|
|
820
|
+
}
|
|
821
|
+
|
|
751
822
|
// Load the components
|
|
752
823
|
var users_widgets = {}
|
|
753
824
|
function make_component(name, func) {
|
|
754
825
|
// Define the component
|
|
755
826
|
|
|
756
|
-
window[name] = users_widgets[name] =
|
|
827
|
+
window[name] = users_widgets[name] = create_react_class({
|
|
757
828
|
displayName: name,
|
|
758
829
|
render: function () {
|
|
759
830
|
var args = []
|
|
@@ -776,10 +847,10 @@
|
|
|
776
847
|
}
|
|
777
848
|
|
|
778
849
|
// Wrap plain JS values with SPAN, so react doesn't complain
|
|
779
|
-
if (!React.isValidElement(vdom))
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
850
|
+
// if (!React.isValidElement(vdom))
|
|
851
|
+
// // To do: should arrays be flattened into a SPAN's arguments?
|
|
852
|
+
// vdom = React.DOM.span(null, (typeof vdom === 'string')
|
|
853
|
+
// ? vdom : JSON.stringify(vdom))
|
|
783
854
|
return vdom
|
|
784
855
|
},
|
|
785
856
|
componentDidMount: function () {
|
|
@@ -803,103 +874,6 @@
|
|
|
803
874
|
})
|
|
804
875
|
}
|
|
805
876
|
|
|
806
|
-
function make_syncarea () {
|
|
807
|
-
// a textarea that syncs with other textareas via diffsync
|
|
808
|
-
// options:
|
|
809
|
-
// textarea_style : hashmap of styles to add to the textarea
|
|
810
|
-
// cursor_style : hashmap of styles to add to each peer's cursor
|
|
811
|
-
// autosize : true --> resizes the textarea vertically to fit the text inside it
|
|
812
|
-
// ws_url : websocket url for the diffsync server,
|
|
813
|
-
// e.g. 'wss://invisible.college:' + diffsync.port
|
|
814
|
-
// channel : 'diffsync_channel' --> diffsync channel to connect to
|
|
815
|
-
window['SYNCAREA'] = users_widgets['SYNCAREA'] = React.createClass({
|
|
816
|
-
getInitialState : function () {
|
|
817
|
-
return { cursor_positions : {} }
|
|
818
|
-
},
|
|
819
|
-
on_text_changed : function () {
|
|
820
|
-
if (this.props.autosize) {
|
|
821
|
-
var t = this.textarea_ref
|
|
822
|
-
t.style.height = null
|
|
823
|
-
while (t.rows > 1 && t.scrollHeight < t.offsetHeight) t.rows--
|
|
824
|
-
while (t.scrollHeight > t.offsetHeight) t.rows++
|
|
825
|
-
}
|
|
826
|
-
},
|
|
827
|
-
componentDidMount : function () {
|
|
828
|
-
var self = this
|
|
829
|
-
self.on_ranges = function (ranges) {
|
|
830
|
-
self.ranges = ranges
|
|
831
|
-
var cursor_positions = {}
|
|
832
|
-
Object.keys(ranges).forEach(function (k) {
|
|
833
|
-
var r = ranges[k]
|
|
834
|
-
var xy = getCaretCoordinates(self.textarea_ref, r[0])
|
|
835
|
-
var x = self.textarea_ref.offsetLeft - self.textarea_ref.scrollLeft + xy.left + 'px'
|
|
836
|
-
var y = self.textarea_ref.offsetTop - self.textarea_ref.scrollTop + xy.top + 'px'
|
|
837
|
-
cursor_positions[k] = [x, y]
|
|
838
|
-
})
|
|
839
|
-
self.setState({ cursor_positions : cursor_positions })
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
this.ds = diffsync.create_client({
|
|
843
|
-
ws_url : this.props.ws_url,
|
|
844
|
-
channel : this.props.channel,
|
|
845
|
-
get_text : function () {
|
|
846
|
-
return self.textarea_ref.value
|
|
847
|
-
},
|
|
848
|
-
get_range : function () {
|
|
849
|
-
var t = self.textarea_ref
|
|
850
|
-
return [t.selectionStart, t.selectionEnd]
|
|
851
|
-
},
|
|
852
|
-
on_text : function (s, range) {
|
|
853
|
-
self.textarea_ref.value = s
|
|
854
|
-
self.textarea_ref.setSelectionRange(range[0], range[1])
|
|
855
|
-
self.on_text_changed()
|
|
856
|
-
},
|
|
857
|
-
on_ranges : this.on_ranges
|
|
858
|
-
})
|
|
859
|
-
},
|
|
860
|
-
render : function () {
|
|
861
|
-
var self = this
|
|
862
|
-
var cursors = []
|
|
863
|
-
Object.keys(this.state.cursor_positions).forEach(function (k) {
|
|
864
|
-
var p = self.state.cursor_positions[k]
|
|
865
|
-
var style = {
|
|
866
|
-
position : 'absolute',
|
|
867
|
-
left : p[0],
|
|
868
|
-
top : p[1]
|
|
869
|
-
}
|
|
870
|
-
Object.keys(self.props.cursor_style).forEach(function (k) {
|
|
871
|
-
style[k] = self.props.cursor_style[k]
|
|
872
|
-
})
|
|
873
|
-
cursors.push(React.createElement('div', {
|
|
874
|
-
key : k,
|
|
875
|
-
style : style
|
|
876
|
-
}))
|
|
877
|
-
})
|
|
878
|
-
return React.createElement('div', {
|
|
879
|
-
style : {
|
|
880
|
-
clipPath : 'inset(0px 0px 0px 0px)'
|
|
881
|
-
},
|
|
882
|
-
}, React.createElement('textarea', {
|
|
883
|
-
ref : function (t) { self.textarea_ref = t },
|
|
884
|
-
style : this.props.textarea_style,
|
|
885
|
-
onChange : function (e) {
|
|
886
|
-
self.ds.on_change()
|
|
887
|
-
self.on_text_changed()
|
|
888
|
-
},
|
|
889
|
-
onMouseDown : function () {
|
|
890
|
-
setTimeout(function () { self.ds.on_change() }, 0)
|
|
891
|
-
},
|
|
892
|
-
onKeyDown : function () {
|
|
893
|
-
setTimeout(function () { self.ds.on_change() }, 0)
|
|
894
|
-
},
|
|
895
|
-
onScroll : function () {
|
|
896
|
-
self.on_ranges(self.ranges)
|
|
897
|
-
}
|
|
898
|
-
}), cursors)
|
|
899
|
-
}
|
|
900
|
-
})
|
|
901
|
-
}
|
|
902
|
-
|
|
903
877
|
function compile_coffee (coffee, filename) {
|
|
904
878
|
var compiled
|
|
905
879
|
try {
|
|
@@ -930,10 +904,12 @@
|
|
|
930
904
|
return compiled
|
|
931
905
|
}
|
|
932
906
|
function load_client_code (code) {
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
907
|
+
// What is this function for?
|
|
908
|
+
var dom = {}
|
|
909
|
+
if (code)
|
|
910
|
+
eval(code)
|
|
911
|
+
else
|
|
912
|
+
dom = window.dom
|
|
937
913
|
for (var widget_name in dom)
|
|
938
914
|
window.dom[widget_name] = dom[widget_name]
|
|
939
915
|
}
|
|
@@ -945,6 +921,11 @@
|
|
|
945
921
|
if (scripts[i].getAttribute('type')
|
|
946
922
|
in {'statebus':1, 'coffeedom':1,'statebus-js':1,
|
|
947
923
|
'coffee':1, 'coffeescript':1}) {
|
|
924
|
+
|
|
925
|
+
if (!window.CoffeeScript) {
|
|
926
|
+
console.error('Cannot load <script type="coffee"> because coffeescript library isn\'t present')
|
|
927
|
+
return
|
|
928
|
+
}
|
|
948
929
|
// Compile coffeescript to javascript
|
|
949
930
|
var compiled = scripts[i].text
|
|
950
931
|
if (scripts[i].getAttribute('type') !== 'statebus-js')
|
|
@@ -976,15 +957,63 @@
|
|
|
976
957
|
return widge(props, children)
|
|
977
958
|
}
|
|
978
959
|
|
|
979
|
-
window.users_widgets = users_widgets
|
|
980
|
-
function load_widgets () {
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
960
|
+
// window.users_widgets = users_widgets
|
|
961
|
+
// function load_widgets () {
|
|
962
|
+
// for (var w in users_widgets) {
|
|
963
|
+
// var nodes = document.getElementsByTagName(w)
|
|
964
|
+
// for (var i=0; i<nodes.length; i++)
|
|
965
|
+
// if (!nodes[i].seen)
|
|
966
|
+
// react_render(dom_to_widget(nodes[i]), nodes[i])
|
|
967
|
+
// }
|
|
968
|
+
// }
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
bus.libs.react17.react_class = create_react_class
|
|
972
|
+
bus.libs.react17.coffreact = () => {
|
|
973
|
+
bus.libs.react17.reactive_dom()
|
|
974
|
+
load_coffee()
|
|
975
|
+
if (dom.BODY)
|
|
976
|
+
document.addEventListener(
|
|
977
|
+
'DOMContentLoaded',
|
|
978
|
+
() => {
|
|
979
|
+
var root = document.createElement('root')
|
|
980
|
+
document.body.appendChild(root)
|
|
981
|
+
ReactDOM.render(BODY(), root)
|
|
982
|
+
},
|
|
983
|
+
false
|
|
984
|
+
)
|
|
987
985
|
}
|
|
988
986
|
|
|
989
|
-
|
|
987
|
+
// if (statebus_server !== 'none') {
|
|
988
|
+
// if (clientjs_option('braid_mode')) {
|
|
989
|
+
// console.log('Using Braid-HTTP!')
|
|
990
|
+
// bus.libs.http_out ('/*', statebus_server)
|
|
991
|
+
// } else {
|
|
992
|
+
// bus.ws_mount ('/*', statebus_server)
|
|
993
|
+
// }
|
|
994
|
+
// }
|
|
995
|
+
|
|
996
|
+
http_automount()
|
|
997
|
+
|
|
998
|
+
statebus.compile_coffee = compile_coffee
|
|
999
|
+
statebus.load_client_code = load_client_code
|
|
1000
|
+
|
|
1001
|
+
// if (clientjs_option('globals')) {
|
|
1002
|
+
// // Setup globals
|
|
1003
|
+
// var globals = ['get', 'set', 'state']
|
|
1004
|
+
|
|
1005
|
+
// for (var i=0; i<globals.length; i++) {
|
|
1006
|
+
// console.log('globalizing', globals[i], 'as',
|
|
1007
|
+
// eval('bus.' + globals[i]))
|
|
1008
|
+
// window[globals[i]] = eval('bus.' + globals[i])
|
|
1009
|
+
// }
|
|
1010
|
+
// }
|
|
1011
|
+
|
|
1012
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
1013
|
+
if (window.statebus_ready)
|
|
1014
|
+
for (var i=0; i<statebus_ready.length; i++)
|
|
1015
|
+
statebus_ready[i]()
|
|
1016
|
+
}, false)
|
|
1017
|
+
|
|
1018
|
+
// document.addEventListener('DOMContentLoaded', load_widgets, false)
|
|
990
1019
|
})()
|