guindilla_gui 0.1.1

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.
@@ -0,0 +1,614 @@
1
+ #------------------------------------------------------------------------------#
2
+ # Copyleft 2022
3
+ # This file is part of GuindillaGUI.
4
+ # GuindillaGUI is free software: you can redistribute it and/or modify it under
5
+ # the terms of the GNU General Public License as published by the Free Software
6
+ # Foundation, either version 3 of the License, or (at your option) any later
7
+ # version.
8
+ # GuindillaGUI is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11
+ # You should have received a copy of the GNU General Public License along with
12
+ # GuindillaGUI. If not, see <https://www.gnu.org/licenses/>.
13
+ #------------------------------------------------------------------------------#
14
+
15
+ module GuindillaGUI
16
+ class Guindilla
17
+ ##
18
+ # JavaScript `setTimeout` Timer
19
+ def after(seconds, &block)
20
+ Timer.new("timeout", seconds, &block)
21
+ end
22
+
23
+ def alert(message)
24
+ send_js(%Q~ alert("#{message}") ~)
25
+ end
26
+
27
+ def append(element)
28
+ id = caller_id(self)
29
+ send_js(%Q~ $("##{self.id}").append($("##{element.id}")); ~)
30
+ end
31
+
32
+ ##
33
+ # attributes may include `controls: true`
34
+ def audio_out(attributes={})
35
+ AudioVideo.new("audio", attributes)
36
+ end
37
+
38
+ def bullet_list(list_array, attributes={})
39
+ ul = Element.new("ul")
40
+ list_array.each do |li|
41
+ send_js(%Q~ $("##{ul.id}").append($("<li>").html("#{li}")); ~)
42
+ end
43
+ return ul
44
+ end
45
+
46
+ ##
47
+ # `button(text="", attributes={}, &block)`
48
+ def button(*args, &block)
49
+ args.unshift("") unless args[0].is_a?(String)
50
+ txt = args[0]
51
+ args[1] ? attributes = args[1] : attributes = {}
52
+ btn = Element.new("button", attributes)
53
+ send_js(%Q~ #{btn.id}.innerHTML = "#{txt}"; ~)
54
+ send_js(%Q~
55
+ #{btn.id}.onclick = function(event){
56
+ socket.send("#{btn.id}:!!:");
57
+ event.stopPropagation();
58
+ };
59
+ ~)
60
+ @@gui.blocks[:"#{btn.id}"] = block if block_given?
61
+ return btn
62
+ end
63
+
64
+ def canvas(attributes={}, &block)
65
+ attributes[:width] = "50%" unless attributes[:width]
66
+ attributes[:height] = "33%" unless attributes[:height]
67
+ Canvas.new(attributes, &block)
68
+ end
69
+
70
+ ##
71
+ # `chart(type: 'scatter', title: "", attributes={}, &block)`
72
+ def chart(attributes={}, &block)
73
+ # OPTIMIZE: use Hash#merge!
74
+ Chart.new(attributes, &block)
75
+ end
76
+
77
+ ##
78
+ # `checkbox(label="", attributes={}, &block |boolean|)`
79
+ def checkbox(*args, &block)
80
+ args.unshift("") unless args[0].is_a?(String)
81
+ label = args[0]
82
+ args[1] ? attributes = args[1] : attributes = {}
83
+ Input.new("checkbox", label, attributes, &block)
84
+ end
85
+
86
+ def circle(radius, attributes={})
87
+ attributes[:cx] = radius
88
+ attributes[:cy] = radius
89
+ attributes[:r] = radius
90
+ Svg.new("circle", attributes)
91
+ end
92
+
93
+ ##
94
+ # `color_input(label="", attributes={}, &block |color|)`
95
+ def color_input(*args, &block)
96
+ args.unshift("") unless args[0].is_a?(String)
97
+ label = args[0]
98
+ args[1] ? attributes = args[1] : attributes = {}
99
+ Input.new("color", label, attributes, &block)
100
+ end
101
+
102
+ def container(attributes={}, &block)
103
+ Box.new(nil, attributes, &block)
104
+ end
105
+
106
+ ##
107
+ # JavaScript `setInterval` Timer
108
+ def every(seconds, &block)
109
+ Timer.new("interval", seconds, &block)
110
+ end
111
+
112
+ ##
113
+ # `file_input(label="", attributes={}, &block |file|)`
114
+ def file_input(*args, &block)
115
+ args.unshift("") unless args[0].is_a?(String)
116
+ label = args[0]
117
+ args[1] ? attributes = args[1] : attributes = {}
118
+ Input.new("file", label, attributes, &block)
119
+ end
120
+
121
+ def h_box(attributes={}, &block)
122
+ Box.new("row", attributes, &block)
123
+ end
124
+
125
+ def h_rule(attributes={})
126
+ attributes[:width] = "100%" unless attributes[:width]
127
+ Element.new("hr", attributes)
128
+ end
129
+
130
+ ##
131
+ # `heading(level=1, string, attributes={})`
132
+ def heading(*args)
133
+ args.unshift(1) unless args[0].is_a?(Integer)
134
+ level = args[0]
135
+ string = args[1]
136
+ args[2] ? attributes = args[2] : attributes = {}
137
+ h = Element.new("#{'h' + level.to_s}", attributes)
138
+ send_js(%Q~ #{h.id}.innerHTML = "#{string}"; ~)
139
+ return h
140
+ end
141
+
142
+ def hide
143
+ id = caller_id(self)
144
+ send_js(%Q~ $("##{id}").hide(); ~)
145
+ end
146
+
147
+ def image(source, attributes={})
148
+ img = Element.new("img", attributes)
149
+ send_js(%Q~ #{img.id}.src = "#{source}"; ~)
150
+ send_js(%Q~ #{img.id}.onerror = function(){
151
+ #{img.id}.src = "resources/guindilla_gui.png"
152
+ };
153
+ ~)
154
+ return img
155
+ end
156
+
157
+ def line_break
158
+ para("")
159
+ end
160
+
161
+ def link(url, attributes={})
162
+ lnk = Element.new("a", attributes)
163
+ if self.is_a?(GuindillaGUI::Element)
164
+ lnk.append(self)
165
+ else
166
+ attributes[:text] ? txt = attributes[:text] : txt = url
167
+ send_js(%Q~ #{lnk.id}.textContent = "#{txt}"; ~)
168
+ end
169
+ send_js(%Q~ #{lnk.id}.href = "#{url}"; ~)
170
+ send_js(%Q~ #{lnk.id}.target = "_blank"; ~)
171
+ return lnk
172
+ end
173
+
174
+ ##
175
+ # `number_input(label="", attributes={}, &block |input|)`
176
+ def number_input(*args, &block)
177
+ args.unshift("") unless args[0].is_a?(String)
178
+ label = args[0]
179
+ args[1] ? attributes = args[1] : attributes = {}
180
+ Input.new("number", label, attributes, &block)
181
+ end
182
+
183
+ def on_click(&block)
184
+ id = caller_id(self)
185
+ send_js(%Q~
186
+ #{id}.onclick = function(event){
187
+ socket.send("#{id}_click:!!:");
188
+ event.stopPropagation();
189
+ };
190
+ ~)
191
+ @@gui.blocks[:"#{id}_click"] = block if block_given?
192
+ return @@gui.elements[:"#{id}"]
193
+ end
194
+
195
+ def on_hover(&block)
196
+ id = caller_id(self)
197
+ send_js(%Q~
198
+ #{id}.onmouseover = function(event){
199
+ socket.send("#{id}_hover:!!:");
200
+ event.stopPropagation();
201
+ };
202
+ ~)
203
+ @@gui.blocks[:"#{id}_hover"] = block if block_given?
204
+ return @@gui.elements[:"#{id}"]
205
+ end
206
+
207
+ def on_leave(&block)
208
+ id = caller_id(self)
209
+ send_js(%Q~
210
+ #{id}.onmouseout = function(event){
211
+ socket.send("#{id}_leave:!!:");
212
+ event.stopPropagation();
213
+ };
214
+ ~)
215
+ @@gui.blocks[:"#{id}_leave"] = block if block_given?
216
+ return @@gui.elements[:"#{id}"]
217
+ end
218
+
219
+ def on_mouse_move(&block)
220
+ id = caller_id(self)
221
+ send_js(%Q~
222
+ #{id}.onmousemove = function(event){
223
+ socket.send("#{id}:!!:mousemove:!!:" + event.pageX + ',' + event.pageY);
224
+ event.stopPropagation();
225
+ };
226
+ ~)
227
+ @@gui.blocks[:"#{id}_move"] = block if block_given?
228
+ return @@gui.elements[:"#{id}"]
229
+ end
230
+
231
+ def ordered_list(list_array, attributes={})
232
+ ol = Element.new("ol")
233
+ list_array.each do |li|
234
+ send_js(%Q~ $("##{ol.id}").append($("<li>").html("#{li}")); ~)
235
+ end
236
+ return ol
237
+ end
238
+
239
+ def para(string, attributes={})
240
+ p = Element.new("p", attributes)
241
+ send_js(%Q~ #{p.id}.innerHTML = "#{string}"; ~)
242
+ return p
243
+ end
244
+
245
+ ##
246
+ # `polygon` takes a nested array of x, y coordinates, e.g.:
247
+ # `polygon([[2, 0], [0, 3], [3, 3], [2, 0]])`
248
+ def polygon(points_array, attributes={})
249
+ points = ""
250
+ points_array.each do |arr|
251
+ points += arr.join(",")
252
+ points += " "
253
+ end
254
+ attributes[:points] = points
255
+ width = 0
256
+ height = 0
257
+ points.split(" ").each do |xy|
258
+ pair = xy.split(",")
259
+ width = pair[0].to_i if pair[0].to_i > width
260
+ height = pair[1].to_i if pair[1].to_i > height
261
+ end
262
+ attributes[:width] = width unless attributes[:width]
263
+ attributes[:height] = height unless attributes[:height]
264
+ Svg.new("polygon", attributes)
265
+ end
266
+
267
+ ##
268
+ # `radio_button(label="", attributes={}, &block |boolean|)`
269
+ # attributes may include a +group:+ key to group buttons
270
+ def radio_button(*args, &block)
271
+ args.unshift("") unless args[0].is_a?(String)
272
+ label = args[0]
273
+ args[1] ? attributes = args[1] : attributes = {}
274
+ attributes[:group] = "no_group" unless attributes[:group]
275
+ Input.new("radio", label, attributes, &block)
276
+ end
277
+
278
+ ##
279
+ # `range_slider(label="", {min: 0, max: 1.0, step: 0.05, value: 0.5}, &block |value|)`
280
+ def range_slider(*args, &block)
281
+ args.unshift("") unless args[0].is_a?(String)
282
+ label = args[0]
283
+ args[1] ? attributes = args[1] : attributes = {}
284
+ attributes[:min] = 0 unless attributes[:min]
285
+ attributes[:max] = 1.0 unless attributes[:max]
286
+ attributes[:step] = 0.05 unless attributes[:step]
287
+ attributes[:value] = (attributes[:max] - attributes[:min]) / 2 unless attributes[:value]
288
+ Input.new("range", label, attributes, &block)
289
+ end
290
+
291
+ def rectangle(width_integer, height_integer, attributes={})
292
+ attributes[:width] = width_integer
293
+ attributes[:height] = height_integer
294
+ Svg.new("rect", attributes)
295
+ end
296
+
297
+ def show
298
+ id = caller_id(self)
299
+ send_js(%Q~ $("##{id}").show(); ~)
300
+ end
301
+
302
+ def source(path_string)
303
+ id = caller_id(self)
304
+ send_js(%Q~ #{id}.src = "#{path_string}"; ~)
305
+ end
306
+ alias_method :source=, :source
307
+
308
+ def square(size_integer, attributes={})
309
+ rectangle(size_integer, size_integer, attributes)
310
+ end
311
+
312
+ def sub_script(string, attributes={})
313
+ ## FIXME: displays superscript, huh???
314
+ sub = Element.new("p", attributes)
315
+ send_js(%Q~ #{sub.id}.innerHTML = "#{string}"; ~)
316
+ sub.style(vertical_align: "sub", font_size: "small")
317
+ return sub
318
+ end
319
+
320
+ def sup_script(string, attributes={})
321
+ sup = Element.new("p", attributes)
322
+ send_js(%Q~ #{sup.id}.innerHTML = "#{string}"; ~)
323
+ sup.style(vertical_align: "super", font_size: "small")
324
+ return sup
325
+ end
326
+
327
+ ##
328
+ # set element text
329
+ def text(string)
330
+ id = caller_id(self)
331
+ send_js(%Q~ #{id}.innerHTML = "#{string}"; ~)
332
+ end
333
+ alias_method :text=, :text
334
+
335
+ ##
336
+ # `text_input(label="", attributes={}, &block |input|)`
337
+ def text_input(*args, &block)
338
+ args.unshift("") unless args[0].is_a?(String)
339
+ label = args[0]
340
+ args[1] ? attributes = args[1] : attributes = {}
341
+ Input.new("text", label, attributes, &block)
342
+ end
343
+
344
+ ##
345
+ # show/hide element
346
+ def toggle
347
+ id = caller_id(self)
348
+ send_js(%Q~ $("##{id}").toggle(); ~)
349
+ end
350
+
351
+ def triangle(size_integer, attributes={})
352
+ polygon(
353
+ [
354
+ [0, size_integer * 0.866],
355
+ [size_integer / 2, 0],
356
+ [size_integer, size_integer * 0.866]
357
+ ],
358
+ attributes
359
+ )
360
+ end
361
+
362
+ ##
363
+ # `url_input(label="", attributes={}, &block |input|)`
364
+ def url_input(*args, &block)
365
+ args.unshift("") unless args[0].is_a?(String)
366
+ label = args[0]
367
+ args[1] ? attributes = args[1] : attributes = {}
368
+ Input.new("url", label, attributes, &block)
369
+ end
370
+
371
+ def v_box(attributes={}, &block)
372
+ Box.new("column", attributes, &block)
373
+ end
374
+
375
+ ##
376
+ # attributes may include `controls: true`
377
+ def video_out(attributes={})
378
+ attributes[:width] = 500 unless attributes[:width]
379
+ attributes[:height] = 300 unless attributes[:height]
380
+ AudioVideo.new("video", attributes)
381
+ end
382
+
383
+ def web_frame(attributes={})
384
+ attributes[:height] = "500px" unless attributes[:height]
385
+ Element.new("iframe", attributes)
386
+ end
387
+
388
+
389
+ ##############################################################################
390
+ #----------------------------------------------------------------------------#
391
+ # style methods #
392
+ #----------------------------------------------------------------------------#
393
+ ##############################################################################
394
+ ##
395
+ # CSS properties key/value pairs with underscores `_` rather than dashes `-`
396
+ # e.g. `style(color: 'blue', text_align: 'center')`
397
+ ##
398
+
399
+ def style(hash)
400
+ id = caller_id(self)
401
+ hash.each do |key, value|
402
+ send_js(%Q~
403
+ $("##{id}").css("#{key.to_s.gsub("_","-")}", "#{value}");
404
+ ~)
405
+ @@gui.elements[:"#{id}"].attributes[:"#{key}"] = "#{value}"
406
+ end
407
+ return self
408
+ end
409
+ alias_method :style=, :style
410
+
411
+ ##
412
+ # Vertical alignment within a box.
413
+ # Position may be `'stretch'`(default), `'center'`, `'start'`, `'end'`, or `'baseline'`.
414
+ # See 'align-items': https://css-tricks.com/snippets/css/a-guide-to-flexbox/
415
+ def align(position) # vertical
416
+ position = "flex-start" if position == "start"
417
+ position = "flex-end" if position == "end"
418
+ self.style(align_items: "#{position}")
419
+ return self
420
+ end
421
+ alias_method :align=, :align
422
+
423
+ ##
424
+ # `color_string` may be rgb, rgba, hex, or CSS color
425
+ def background(color_string)
426
+ self.style(background: "#{color_string}")
427
+ return self
428
+ end
429
+ alias_method :background=, :background
430
+
431
+ ##
432
+ # https://www.w3schools.com/css/css_border.asp
433
+ # e.g. `border('2px solid blue')`
434
+ def border(border_string)
435
+ self.style(border: "#{border_string}")
436
+ return self
437
+ end
438
+ alias_method :border=, :border
439
+
440
+ ##
441
+ # `color_string` may be rgb, rgba, hex, or CSS color
442
+ def border_color(color_string)
443
+ if self.class.to_s == "GuindillaGUI::Svg"
444
+ self.style(stroke: "#{color_string}")
445
+ else
446
+ self.style(border_color: "#{color_string}")
447
+ end
448
+ return self
449
+ end
450
+ alias_method :border_color=, :border_color
451
+
452
+ ##
453
+ # https://www.w3schools.com/cssref/css3_pr_border-radius.asp
454
+ def border_radius(pixels)
455
+ self.style(border_radius: "#{pixels}")
456
+ return self
457
+ end
458
+ alias_method :border_radius=, :border_radius
459
+
460
+ def border_width(width)
461
+ self.style(border_width: "#{width_integer}")
462
+ return self
463
+
464
+ end
465
+ alias_method :border_width=, :border_width
466
+
467
+ ##
468
+ # `color_string` may be rgb, rgba, hex, or CSS color
469
+ def color(color_string)
470
+ if self.class.to_s == "GuindillaGUI::Svg"
471
+ self.style(fill: "#{color_string}")
472
+ else
473
+ self.style(color: "#{color_string}")
474
+ end
475
+ return self
476
+ end
477
+ alias_method :color=, :color
478
+
479
+ ##
480
+ # CSS display property.
481
+ # https://www.w3schools.com/CSSref/pr_class_display.asp
482
+ def display(property)
483
+ self.style(display: "#{property}")
484
+ return self
485
+ end
486
+ alias_method :display=, :display
487
+
488
+ ##
489
+ # https://www.w3schools.com/css/css_font.asp
490
+ def font(family_string, size_integer)
491
+ id = caller_id(self)
492
+ self.style(font_family: "#{family_string}", font_size: "#{size_integer}")
493
+ return self
494
+ end
495
+ alias_method :font=, :font
496
+
497
+ ##
498
+ # https://www.w3schools.com/Css/css_font.asp
499
+ def font_family(family_string)
500
+ self.style(font_family: "#{family_string}")
501
+ return self
502
+ end
503
+ alias_method :font_family=, :font_family
504
+
505
+ ##
506
+ # https://www.w3schools.com/cssref/pr_font_font-size.asp
507
+ def font_size(size)
508
+ self.style(font_size: "#{size}")
509
+ return self
510
+ end
511
+ alias_method :font_size=, :font_size
512
+
513
+ ##
514
+ # https://www.w3schools.com/cssref/pr_dim_height.asp
515
+ def height(h)
516
+ self.style(height: "#{h}")
517
+ return self
518
+ end
519
+ alias_method :height=, :height
520
+
521
+ ##
522
+ # Horizontal justification within a box.
523
+ # https://www.w3schools.com/csSref/css3_pr_justify-content.asp
524
+ def justify(position)
525
+ position = "flex-start" if position == "start"
526
+ position = "flex-end" if position == "end"
527
+ self.style(justify_content: "#{position}")
528
+ return self
529
+ end
530
+ alias_method :justify=, :justify
531
+
532
+ ##
533
+ # margin in pixels, or `'auto'` to center
534
+ def margin(size)
535
+ self.style(margin: "#{size}")
536
+ return self
537
+ end
538
+ alias_method :margin=, :margin
539
+
540
+ ##
541
+ # 0.0 to 1.0
542
+ def opacity(value)
543
+ if self.class.to_s == "GuindillaGUI::Svg"
544
+ self.style(fill_opacity: "#{value}")
545
+ else
546
+ self.style(opacity: "#{value}")
547
+ end
548
+ return self
549
+ end
550
+ alias_method :opacity=, :opacity
551
+
552
+ ##
553
+ # padding in pixels
554
+ def padding(size)
555
+ self.style(padding: "#{size}")
556
+ return self
557
+ end
558
+ alias_method :padding=, :padding
559
+
560
+ ##
561
+ # position by x and y pixel coordinates
562
+ def position(x, y)
563
+ self.style(position: 'absolute')
564
+ self.style(left: "#{x}px", top: "#{y}px")
565
+ end
566
+ alias_method :position=, :position
567
+
568
+ def rotate(degrees)
569
+ rotation = self.attributes[:rotate].to_i + degrees
570
+ self.style(rotate: "#{rotation}deg")
571
+ return self
572
+ end
573
+
574
+ def size(width, height)
575
+ self.style(width: "#{width}", height: "#{height}")
576
+ return self
577
+ end
578
+ alias_method :size=, :size
579
+
580
+ ##
581
+ # position may be `'left'`, `'right'`, `'center'`, or `'justify'`
582
+ def text_align(position)
583
+ self.style(text_align: "#{position}")
584
+ return self
585
+ end
586
+ alias_method :text_align=, :text_align
587
+
588
+ ##
589
+ # `transition(property, duration, delay=0, type="ease")`
590
+ # https://www.w3schools.com/css/css3_transitions.asp
591
+ def transition(property, duration, *args)
592
+ self.style(transition: "#{property} #{duration}s")
593
+ unless args.empty?
594
+ args.each do |arg|
595
+ if arg.is_a?(String)
596
+ self.style(transition_timing_function: "#{arg}")
597
+ elsif arg.is_a?(Integer)
598
+ self.style(transition_delay: "#{arg}s")
599
+ end
600
+ end
601
+ end
602
+ end
603
+ alias_method :transition=, :transition
604
+
605
+ ##
606
+ # https://www.w3schools.com/cssref/pr_dim_width.asp
607
+ def width(w)
608
+ self.style(width: "#{w}")
609
+ return self
610
+ end
611
+ alias_method :width=, :width
612
+
613
+ end #class Guindilla
614
+ end #module
@@ -0,0 +1,35 @@
1
+ <!--
2
+ #------------------------------------------------------------------------------#
3
+ # Copyleft 2022
4
+ # This file is part of GuindillaGUI.
5
+ # GuindillaGUI is free software: you can redistribute it and/or modify it under
6
+ # the terms of the GNU General Public License as published by the Free Software
7
+ # Foundation, either version 3 of the License, or (at your option) any later
8
+ # version.
9
+ # GuindillaGUI is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
+ # You should have received a copy of the GNU General Public License along with
13
+ # GuindillaGUI. If not, see <https://www.gnu.org/licenses/>.
14
+ #------------------------------------------------------------------------------#
15
+ -->
16
+
17
+ <!doctype html>
18
+
19
+ <html lang="en">
20
+ <head>
21
+ <meta charset="utf-8">
22
+ <meta name="viewport" content="width=device-width, initial-scale=1">
23
+ <title>GuindillaGUI</title>
24
+ <meta name="description" content="GuindillaGUI generated html">
25
+ <meta name="author" content="lljk">
26
+ <link rel="icon" href="guindilla_gui.png">
27
+
28
+ <script src="jquery/jquery-3.6.0.min.js"></script>
29
+ <script src="plotly/plotly-2.9.0.min.js"></script>
30
+ <script src="guindilla.js"></script>
31
+ </head>
32
+
33
+ <body id="body">
34
+ </body>
35
+ </html>
@@ -0,0 +1,46 @@
1
+ /*
2
+ #------------------------------------------------------------------------------#
3
+ # Copyleft 2022
4
+ # This file is part of GuindillaGUI.
5
+ # GuindillaGUI is free software: you can redistribute it and/or modify it under
6
+ # the terms of the GNU General Public License as published by the Free Software
7
+ # Foundation, either version 3 of the License, or (at your option) any later
8
+ # version.
9
+ # GuindillaGUI is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
+ # You should have received a copy of the GNU General Public License along with
13
+ # GuindillaGUI. If not, see <https://www.gnu.org/licenses/>.
14
+ #------------------------------------------------------------------------------#
15
+ */
16
+
17
+ let socket = null
18
+
19
+ $(document).ready(function(){
20
+
21
+ socket = new WebSocket('ws://localhost:8181/');
22
+
23
+ socket.onopen = function(event) {
24
+ console.log("[open] Connection with GuindillaGUI established");
25
+ };
26
+ socket.onmessage = function(event) {
27
+ console.log(`[message] Data received from server: ${event.data}`);
28
+ $(document.body).append(event.data);
29
+ };
30
+ socket.onclose = function(event) {
31
+ if (event.wasClean) {
32
+ console.log(`[close] Connection with GuindillaGUI closed, code=${event.code} reason=${event.reason}`);
33
+ } else {
34
+ alert('[close] Connection with GuindillaGUI died');
35
+ }
36
+ };
37
+ socket.onerror = function(error) {
38
+ alert(`[error] ${error.message}`);
39
+ };
40
+
41
+ window.addEventListener('beforeunload', function (e) {
42
+ socket.send("UI closed.")
43
+ socket.close();
44
+ });
45
+
46
+ });