-
Notifications
You must be signed in to change notification settings - Fork 25
/
ready.js
1443 lines (1288 loc) · 67.6 KB
/
ready.js
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
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
dde_version = "not inited"
dde_release_date = "not inited"
var myCodeMirror //inited inside of ready
var js_cmds_array = []
var js_cmds_index = -1
var previous_active_element = null
var selected_text_when_eval_button_clicked = ""
operating_system = "not inited" //on MAC this is "mac", on windows its "win". bound in both ui and sandbox by ready
dde_apps_folder = null
function set_menu_string(elt, label, key){
let modifier
let max_spaces
if(operating_system === "win") {
modifier = "Ctrl "
max_spaces = 14
}
else { //Mac
modifier = "⌘"
max_spaces = 18 //more because we don't need the "Ctrl " of WinOS, just one char
}
let needed_spaces = Math.max(max_spaces - label.length, 1)
elt.innerHTML = label + " ".repeat(needed_spaces) + modifier + key
}
//called by both the eval button and the step button
function eval_button_action(step=false){ //used by both clicking on the eval button and Cmd-e
if(step instanceof CodeMirror) { step = false } //means Cmd E was typed in the editor and we don't want to step in this case
if((Editor.current_file_path != "new buffer") && (save_on_eval_id.checked)) { Editor.save_current_file() }
eval_js_part1(step)
//if (Editor.view == "Blocks") {
eval_id.blur()
//} //to get rid of the Eval button being "selected" when we're evaling in blocks view
}
function play_simulation_demo(){
sim.enable_rendering = true;
render_demo();
//out("Demo just moves Dexter randomly.")
}
//call this on startup after peristent loaded AND after user clicks the menu item checkbox
function adjust_animation(){
let animate_dur = (persistent_get("animate_ui") ? 300 : 0)
$('#js_menubar_id').jqxMenu({ animationShowDuration: animate_dur })
$('#js_menubar_id').jqxMenu({ animationHideDuration: animate_dur })
}
//from https://stackoverflow.com/questions/6562727/is-there-a-function-to-deselect-all-text-using-javascript
//pretty useless as doesn't clear selection in cmd input.
function clearSelection(){
if (window.getSelection) {window.getSelection().removeAllRanges();}
else if (document.selection) {document.selection.empty();}
}
// document.body.addEventListener('onload', on_ready)
function on_ready() {
const os = require('os');
operating_system = os.platform().toLowerCase() //for Ubuntu, ths returns "linux"
if (operating_system == "darwin") { operating_system = "mac" }
else if (operating_system.startsWith("win")) { operating_system = "win" }
const remote = require("electron").remote
window.dde_apps_folder = convert_backslashes_to_slashes(remote.getGlobal("dde_apps_folder"))
console.log("In renderer dde_apps_folder: " + window.dde_apps_folder)
console.log("In renderer appPath: " + remote.app.getAppPath())
console.log("In renderer __dirname: " + __dirname)
//require('fs-lock')({
// 'file_accessdir': [__dirname, dde_apps_folder], //for readFile, etc. but must include __dirname since Electron needs it.
// 'open_basedir': [__dirname ] //__direname is the folder this app is installed in. //valid folders to get require's from. /usr/local/share/node_modules',
//}) //restrict file access
//window.fs = require('fs')
//dde_version = remote.getGlobal("get_app_version")
var pckg = require('./package.json');
dde_version = pckg.version
dde_release_date = pckg.release_date
platform = "dde" //"node" is the other possibility, which happens when we're in the job_engine
serial_port_init()
//window.Root = Root //should work but doesn't jan 13, 2019
Coor.init()
//see also ./core/index.js that has this same code
Dexter.calibrate_build_tables = calibrate_build_tables
window.calibrate_build_tables = undefined
Dexter.prototype.calibrate_build_tables = function() {
let result = Dexter.calibrate_build_tables()
for(let oplet_array of result){
if(Array.isArray(oplet_array)){
oplet_array.push(this)
}
}
return result
}
Job.class_init()
Dexter.class_init()
setTimeout(function(){
window.document.title = "Dexter Development Environment " + dde_version
dde_version_id.innerHTML = dde_version
dde_release_date_id.innerHTML = dde_release_date
}, 1000)
// window.$ = require('jquery'); //Now done in index.html after doing npm install --save jquery, we still need this
//onload_fn()
Dexter.draw_dxf = DXF.dxf_to_instructions //see Robot.js
Dexter.prototype.draw_dxf = function({robot = null}={}) {
let obj_args
if (arguments.length == 0) { obj_args = {} } //when no args are passed, I must do this
else { obj_args = arguments[0] }
obj_args.robot = this
return Dexter.draw_dxf(obj_args)
}
$('#outer_splitter').jqxSplitter({
width: '98%', height: '97%', //was 93%
orientation: 'vertical',
panels: [ { size: "70%", min: "0%", collapsible: false },
{ size: '30%', min: "0%"}]
})
$('#outer_splitter').on('resize',
function (event) {
let new_size = event.args.panels[0].size
persistent_set("left_panel_width", new_size)
event.stopPropagation()
})
$('#left_splitter').jqxSplitter({orientation: 'horizontal', width: "100%", height: "100%",
panels: [{ size: "60%", min: "5%", collapsible: false },
{ size: '40%', min: "5%"}]
})
$('#left_splitter').on('resize',
function (event) {
let new_size = event.args.panels[0].size
persistent_set("top_left_panel_height", new_size)
event.stopPropagation() //must have or outer_splitter on resize is called
})
$('#right_splitter').jqxSplitter({ orientation: 'horizontal', width: "100%", height: "100%",
panels: [{ size: "50%"}, { size: "50%"}]
})
$('#right_splitter').on('resize',
function (event) {
let new_size = event.args.panels[0].size
persistent_set("top_right_panel_height", new_size)
event.stopPropagation() //must have or outer_splitter on resize is called
})
//TestSuite.make_suites_menu_items() //doesn't work
//see near bottom for animation.
$("#js_menubar_id").jqxMenu({autoOpen: false, clickToOpen: false, height: '25px' }) //autoOpen: false, clickToOpen: true,
//to open a menu, click. Once it is open, if you slide to another menu, it DOESN'T open it. oh well.
//$("#js_edit_menu").jqxMenu( { width: '50px', height: '25px' });
//$("#js_learn_js_menu").jqxMenu({ width: '90px', height: '25px' });
//$("#js_insert_menu").jqxMenu( { width: '65px', height: '25px' });
//$("#js_jobs_menu").jqxMenu( { width: '55px', height: '25px' });
// $("#ros_menu_id").jqxMenu({ width: '50px', height: '25px', animationHideDelay: 1000, animationShowDelay: 1000, autoCloseInterval: 1000 });
$("#cmd_menu_id").jqxMenu({ width: '50px', height: '25px', animationHideDelay: 1000, animationShowDelay: 1000, autoCloseInterval: 1000 });
//$("#jqxwindow").jqxWindow({ height:400, width:400, showCloseButton: true});
//$('#jqxwindow').jqxWindow('hide');
$("#cmd_input_id").keyup(function(event){ //output pane type in
if(event.keyCode == 13){ //ENTER key
let src = Editor.get_cmd_selection() //will return "" if no selection
if(src.length == 0) { src = cmd_input_id.value} //get full src if no selection
src = src.trim()
if (src.length == 0) { warning("no code to eval.")}
else if(cmd_lang_id.value == "JS"){
js_cmds_array.push(src)
js_cmds_index = js_cmds_array.length - 1
eval_js_part2(src)
}
else if (cmd_lang_id.value == "SSH"){
cmd_input_id.placeholder = "Type in a shell 'bash' command & hit the Enter key to run."
//but the above probably never get's seen because the src of the actual default cmd gets shown instead
SSH.run_command({command: src}) //use defaults which makes formatted dir listing
//call_cmd_service_custom(src) /ROS selected
}
//else if (cmd_lang_id.value == "ROS"){
// /call_cmd_service_custom(src) /ROS selected
//}
}
else if(event.keyCode == 38){ //up arrow
if (js_cmds_index == -1 ) { out("No JavaScript commands in history") }
else if (js_cmds_index == 0 ) { out("No more JavaScript command history.") }
else {
js_cmds_index = js_cmds_index - 1
var new_src = js_cmds_array[js_cmds_index]
cmd_input_id.value = new_src
}
}
else if(event.keyCode == 40){ //down arrow
if (js_cmds_index == -1 ) { out("No JavaScript commands in history") }
else if (js_cmds_index == js_cmds_array.length - 1) {
if(cmd_input_id.value == "") {
out("No more JavaScript command history.")
}
else { cmd_input_id.value = "" }
}
else {
js_cmds_index = js_cmds_index + 1
var new_src = js_cmds_array[js_cmds_index]
cmd_input_id.value = new_src
}
}
cmd_input_id.focus()
})
//cmd_input_id.onblur = function(){
// window.getSelection().collapse(cmd_input_id)
//}
//cmd_input_clicked_on_last = false //global var. Also set below and by Editor.init_editor
cmd_input_id.onclick = function(event) {
var full_src = event.target.value
if (full_src) {
if(full_src.length > 0){
let pos = event.target.selectionStart
if(pos < (full_src.length - 1)){
onclick_for_click_help(event)
}
//else don't give help if clicking at very end.
//because often that is to edit the cmd and if
//we're in SSH, printout out a long man page is
//disruptive
}
}
}
//js_radio_button_id.onclick = function() { ros_menu_id.style.display = "none"}
//ros_radio_button_id.onclick = function() { ros_menu_id.style.display = "inline-block"}
cmd_lang_id.onchange = function(){
if(cmd_lang_id.value == "JS"){
SSH.close_connection() //if no connection. that's ok
cmd_menu_id.style.display = "none"
cmd_input_id.placeholder = "Type in JS & hit the Enter key to eval"
}
else if(cmd_lang_id.value == "SSH"){
open_doc(ssh_doc_id)
SSH.show_config_dialog()
//cmd_menu_id.style.display = "inline-block"
//cmd_input_id.value = SSH.show_dir_cmd
//SSH.init_maybe_and_write("cd /srv/samba/share;" + SSH.show_dir_cmd, false)
}
}
//init_simulation() now in video.js misc_pane_menu_changed
init_doc()
dde_version_id.innerHTML = dde_version
dde_release_date_id.innerHTML = dde_release_date
Series.init_series()
Gcode.init() //must be after init_series which calls init_units()
$('#js_textarea_id').focus() //same as myCodeMirror.focus() but myCodeMerror not inited yet
doc_prev_id.onclick = open_doc_prev
doc_next_id.onclick = open_doc_next
find_doc_button_id.onmousedown = function() {
previous_active_element = document.activeElement
selected_text_when_eval_button_clicked = Editor.get_any_selection()
};
find_doc_button_id.onclick = function(event) {
find_doc()
event.target.blur()
}
find_doc_input_id.onchange = find_doc
$("#find_doc_input_id").jqxComboBox({ source: [], width: '150px', height: '25px',}); //create
//eval_doc_button_id.onclick = function(){
// let sel = window.getSelection().toString().trim()
// if (sel.length == 0) {out("There is no selection in the Doc pane to eval.", "orange", true) }
// else { eval_js_part2(sel) }
// } obsolete now that Out pane Eval button evals selection in any pane.
//doc_pane_content_id.onclick = //doesn't get called when I click in doc pane, so do the below.
//click help for all text inside the code tag (white).
$('code').click(function(event) {
const full_src = window.getSelection().focusNode.data
const pos = window.getSelection().focusOffset
Editor.show_identifier_info(full_src, pos)
})
//for results of code examples.
$('samp').click(function(event) {
const full_src = window.getSelection().focusNode.data
const pos = window.getSelection().focusOffset
Editor.show_identifier_info(full_src, pos)
})
/*catches all clicks, but then if you click on an input elt it defocuses it so
//you can't type in it.
document.addEventListener("click",
function(event){
out(document.activeElement.id)
clearSelection()
onclick_for_click_help(event)
setTimeout(function(){ out(document.activeElement.id), event.target.focus(), out(document.activeElement.id)}, 1000)
}
)*/
/* does not get called when user clicks on an input when those inputs are dynamically
generated AFTER onready is called.
$('input').click(function(event) {
const full_src = window.getSelection().focusNode.data
const pos = window.getSelection().focusOffset
Editor.show_identifier_info(full_src, pos)
}) */
/* does not get called when user clicks on an input
$('textarea').click(function(event) {
const full_src = window.getSelection().focusNode.data
const pos = window.getSelection().focusOffset
Editor.show_identifier_info(full_src, pos)
})
*/
output_div_id.onclick = onclick_for_click_help
//handles the button clicks and menu selects that chrome Apps prevent in HTML where they belong
eval_id.onmousedown = function() {
previous_active_element = document.activeElement
selected_text_when_eval_button_clicked = Editor.get_any_selection()
};
eval_id.onclick = function(event){
event.stopPropagation()
eval_button_action()
}
step_button_id.onclick = function(event){
event.stopPropagation()
let dde_ipc = require('electron').ipcRenderer
dde_ipc.sendSync('open_dev_tools')
setTimeout(function(){
eval_button_action(true) //cause stepping
}, 500)
step_button_id.blur()
}
step_button_id.onmousedown = function() {
previous_active_element = document.activeElement
selected_text_when_eval_button_clicked = Editor.get_any_selection()
};
email_bug_report_id.onclick=email_bug_report
//File Menu
new_id.onclick = Editor.edit_new_file
set_menu_string(new_id, "New", "n")
file_name_id.onchange = function(e){ //similar to open
const inner_path = e.target.value //could be "new buffer" or an actual file
const path = Editor.files_menu_path_to_path(inner_path)
Editor.edit_file(path)
}
open_id.onclick = Editor.open_on_dde_computer //Editor.open
set_menu_string(open_id, "Open...", "o")
open_from_dexter_id.onclick = Editor.open_from_dexter_computer
open_system_file_id.onclick = Editor.open_system_file
load_file_id.onclick=function(e) {
const path = choose_file({title: "Choose a file to load"})
if (path){
out(load_files(path))
}
}
insert_file_content_id.onclick=function(e) {
const path = choose_file({title: "Choose a file to insert into DDE's editor"})
if (path){
const content = read_file(path)
Editor.insert(content)
}
}
insert_file_path_into_editor_id.onclick=function(e){
const path = choose_file({title: "Choose a file to insert into DDE's editor"})
if (path){
Editor.insert('"' + path + '"')
}
}
insert_file_path_into_cmd_input_id.onclick=function(e){
const path = choose_file({title: "Choose a file to insert into DDE's editor"})
if (path){
Editor.insert_into_cmd_input('"' + path + '"')
}
}
save_id.onclick = Editor.save
set_menu_string(save_id, "Save", "s")
save_as_id.onclick = Editor.save_on_dde_computer //only for saving on dde computer was: Editor.save_as
save_to_dexter_as_id.onclick = Editor.save_to_dexter_as
remove_id.onclick = function(){ Editor.remove() } //don't simply use Editor.remove as ther value for onclick because we want to default its arg as the Editor.remove method does
update_id.onclick = function(){ check_for_latest_release() }
//Edit menu (see editor.js for the Edit menu items
Editor.init_editor()
//Insert menu
js_example_1_id.onclick=function(){Editor.insert(
`//Click the Eval button to define and call the function 'foo'.
function foo(a, b){ //define function foo with 2 args
out("foo called with a=" + a) //print 1st arg to Output pane.
for(var item of b){ //loop over items in array b
if (item > 9.9){
out("got a big one: " + item)
}
}
return b.length //foo returns the length of its 2nd arg.
//After Evaling, observe '4' in the Output pane.
}
foo("hello", [7, 10, 20, -3.2]) //call function foo with 2 args
//a string and an array of numbers.
`)}
alert_id.onclick = function(){Editor.wrap_around_selection("alert(", ')', '"Hi."')}
confirm_id.onclick = function(){Editor.wrap_around_selection("confirm(", ')', '"Do it?"')}
<!--prompt_id.onclick = function(){Editor.wrap_around_selection("prompt(", ', "$1")', '"Price?"')} -->
out_black_id.onclick =function(){Editor.wrap_around_selection("out(", ')', '"Hello"')}
out_purple_id.onclick=function(){Editor.wrap_around_selection("out(", ', "blue")', '"Hello"')}
out_brown_id.onclick =function(){Editor.wrap_around_selection("out(", ', "rgb(255, 100, 0)")', '"Hello"')}
editor_insert_id.onclick = function(){Editor.insert(
`Editor.insert(
"text to insert",
"replace_selection", //insertion_pos. "replace_selection" is the default. Other options: "start", "end", "selection_start", "selection_end", "whole", an integer
false) //select_new_text. false is the default.
`)}
show_window_help_id.onclick = function(){open_doc(show_window_doc_id)}
window_simple_message_id.onclick=function(){Editor.insert(
`//show_window simple message
//Pop up a window with content of the given HTML.
show_window("hi <i style='font-size:100px;'>wizard</i>")
`
)}
insert_color_id.onclick = insert_color
window_options_id.onclick=function(){Editor.insert('//show_window Window Options\n' +
'show_window({\n' +
' content: "hi", // Any HTML OK here.\n' +
' title: "Greetings", // Appears above the content. Any HTML OK.\n' +
' width: 150, // 100 to window.outerWidth\n' +
' height: 70, // 50 to window.outerHeight\n' +
" x: 0, // Distance from left of DDE window to this window's left\n" +
" y: 100, // Distance from top of DDE window to this window's top\n" +
' is_modal: false, // If true, prevents you from interacting with other windows. Default false.\n' +
' show_close_button: true, // Default true.\n' +
' show_collapse_button: true, // Allow quick shrink of window. Default true.\n' +
' trim_strings: true, // Remove whitespace from beginning and end of values from inputs of type text and texareas. Default true.\n' +
' background_color: "ivory" // Default is "rgb(238, 238, 238)" (light gray). White is "rgb(255, 255, 255)"\n' +
'})\n')}
window_buttons_id.onclick=function(){Editor.insert(
`//show_window Buttons
//Called when a button is clicked in the shown window.
function count_up(vals){ //vals contains name-value pairs for each
//html elt in show_window's content with a name.
if(vals.clicked_button_value == "Count"){ // Clicked button value holds the name of the clicked button.
if(window.demo_counter == undefined) {
window.demo_counter = 6 // Initialize the demo_counter global variable.
}
window.demo_counter = window.demo_counter + 1 // Increment demo_counter upon each button click.
dex.set_in_window(vals.window_index, "count_display", "innerHTML", window.demo_counter + "") // Display counter. Doesn't need count_id
dex.set_in_window(vals.window_index, "count_display", "style.font-size", window.demo_counter + "px") // Increments font size.
//Below, a more general alterative to the above line. Uses id, not name
//set_in_ui("count_id.style.font-size", window.demo_counter + "px")
}
else if (vals.clicked_button_value == "Done"){ // When a 'submit' button is clicked, its 'value' is used as its name.
out("outta here at: " + window.demo_counter) // Last thing printed to the Output pane.
}
}\n` +
'show_window({\n' +
' content:\n' +
'`<input type="button" value="Count"/> <!-- Regular button. Does not close window.-->\n' +
' <span name="count_display" id="count_id">6</span><br/><br/>\n' +
' <input type="submit" value="Done"/>`, // submit button closes window\n' +
' callback: count_up}) // This function called when either button is clicked.\n'
)}
let show_window_menu_body =
`Choose:
<div class="menu" style="display:inline-block;">
<ul>
<li>TopMenu▼
<ul>
<li title="this is a tooltip">item1</li>
<li data-name="ITEM two">item2</li> <!-- if there's a data-name, use it, otherwise use the innerHTML-->
<li>SubMenu
<ul>
<li>sub1</li>
<li>sub2</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<span name="menu_choice">pick menu item</span><br/><br/>
<input type="submit" value="Done"/>`
window_menu_id.onclick=function(){Editor.insert(
`//show_winow Menu example
//Called whenever user chooses a menu item or clicks a button.
function menu_choice_cb(vals){
if (vals.clicked_button_value != "Done"){ // True when menu item chosen.
var clicked_item = vals.clicked_button_value
dex.set_in_window(vals.window_index, "menu_choice", "innerHTML", clicked_item) // Display menu choice
}
}
show_window({content: ` + "`" + show_window_menu_body + "`," +
` // submit closes window
callback: menu_choice_cb // Called when menu item or button is clicked
})
`)}
window_many_inputs_id.onclick=function(){Editor.insert(
`//show_window Many Inputs
//Called only when a button is clicked.
function show_vals(vals){ inspect(vals) }
show_window(
{content:\n` +
"`" +
`text: <input type="text" name="my_text" value="Dexter"><br/><br/>
textarea: <textarea name="my_textarea">Hi Rez</textarea><br/><br/>
checkbox: <input name="my_checkbox" type="checkbox" checked="checked"/>heated bed?<br/><br/>
<!-- you can add the checked="checked" attribute to make it initially checked. -->
radio:
<input type="radio" name="my_radio_group" value="abs" />ABS
<input type="radio" name="my_radio_group" value="carbon"/>Carbon Fiber
<input type="radio" name="my_radio_group" value="pla" checked="checked"/>PLA<br/><br/>
<!-- At most, only 1 radio button can be checked. If none are checked,
the return value for the group will be undefined . -->
number: <input type="number" name="my_number" value="0.4" min="0" max="1" step="0.2"/><br/>
range: <input type="range" name="my_range" value="33" min="0" max="100"/><br/>
color: <input type="color" name="my_color" value="#00FF88"/><br/>
date: <input type="date" name="my_date" value="2017-01-20"/><br/>
select: <select name="size">
<option>Gihugeic</option>
<option selected="selected">Ginormace</option> <!--the inital value-->
<option>Gilossal</option>
</select><br/>
combo_box: <div name="my_combo_box" class="combo_box" style="display:inline-block;vertical-align:middle;">
<option>one</option>
<option selected="selected">two</option>
</div><br/>
file: <input type="file" name="my_file"/><br/><br/>
button: <input type="button" value="Show settings"/><br/><br/>
submit: <input type="submit" value="OK"/>` + "`" +
',\n width:380, height:450, title:"Printer Config", x:100, y:100,\n callback: show_vals})\n')}
//______window_onchange_____________________
var window_onchange_top_comments =
`/* show_window onchange calls
In most uses of show_window, its callback is called only
when an input of type 'submit' or 'button' is clicked.
But you CAN have the callback called whenever the value
of an input element changes.
An HTML property of data-onchange='true' will cause the
callback method to be called for an element when
you change its value and select another elememt.
An HTML property of data-oninput='true' causes the
callback to be called as soon as a new value is entered.
For input type="text" this is upon each character entered.
For input type="radio" this is when any radio button in
the group is clicked on.
For select menus, this is when the value is changed.
For input type="range" (sliders) this is upon every
little move of the slider.
The value of the "clicked_button_value" property of the
object passed to the callback will be the 'name' of the
changed input element, even though "clicked_button_value"
implies the 'value' of a 'button'.
To see all this behavior, click the Eval button and play
with the controls in the window that pops up.
Carefully observe the values printed in the output pane.
*/
`
var window_onchange_content =
`Text input with <samp>data-onchange='true'</samp>
calls the callback when user clicks on another input.<br/>
<input type="text" name="my_onchange_text" value="33" min="0" max="100"
data-onchange='true'/>
<hr/>
Text input with <samp>data-oninput='true'</samp>
calls the callback after each keystroke entering text.<br/>
<input type="text" name="my_oninput_text" value="33" min="0" max="100"
data-oninput='true'/>
<hr/>
Range "slider" with <samp>data-onchange='true'</samp>
calls the callback after user stops moving the slider.<br/>
<input type="range" name="my_onchange_range" value="33" min="0" max="100"
data-onchange='true'/><br/>
<hr/>
Range "slider" with <samp>data-oninput='true'</samp>
calls the callback often as user moves the slider.<br/>
<input type="range" name="my_oninput_range" value="33" min="0" max="100"
data-oninput='true'/>
<hr/>
Radio button group input with each input having <samp>data-onchange='true'</samp>
calls the callback once whenever one radio button is clicked.<br/>
<input type="radio" name="my_radio_group" value="abs" data-onchange="true"/>ABS
<input type="radio" name="my_radio_group" value="carbon" data-onchange="true"/>Carbon Fiber
<input type="radio" name="my_radio_group" value="pla" data-onchange="true" checked="checked"/>PLA
`
window_onchange_id.onclick = function(){Editor.insert(
window_onchange_top_comments +
`function the_cb(vals){ //vals contains name-value pairs for each input
out(vals.clicked_button_value + " = " +
vals[vals.clicked_button_value])
}
show_window({content:
` + "`" +
window_onchange_content + "`" +
`, title: "show_window onchange & oninput",
height: 440, x: 500, y: 100, callback: the_cb})
` )}
window_svg_id.onclick=function(){Editor.insert(
`//SVG Example 1: lots of shapes
function handle1(arg) {
if((arg.clicked_button_value === "background_id") ||
(arg.clicked_button_value === "svg_id")) {
append_in_ui("svg_id", svg_circle({cx: arg.offsetX, cy: arg.offsetY, r: 7}))
}
else if (arg.clicked_button_value === "circ_id") {
out("clicked on circ_id")
}
else if (arg.clicked_button_value === "ellip_id") {
out("The user clicked on ellip_id")
}
}
show_window({
title: "SVG Example 1: Lots of shapes. Click to interact",
content: svg_svg({id: "svg_id", height: 500, width: 500, html_class: "clickable", child_elements:
[//svg_rect({id: "background_id", html_class: "clickable", style:"position: relative; top: 0; right: 0; x: 0, y: 0, width: 500, height: 500, color: "white", border_width: 3, border_color: "yellow"}),
svg_circle({id: "circ_id", html_class: "clickable", cx: 20, cy: 20, r: 30, color: "purple"}),
svg_ellipse({id: "ellip_id", html_class: "clickable", cx: 270, cy: 50, rx: 60, ry: 30, color: "orange"}),
svg_line({x1: 30, y1: 30, x2: 100, y2: 200, color: "blue", width: 5}),
svg_rect({x: 50, y: 50, width: 40, height: 100, color: "green", border_width: 3, border_color: "yellow", rx: 20, ry: 5}),
svg_polygon({points: [[400, 10], [500, 10], [450, 100]], color: "lime", border_width: 3, border_color: "yellow"}),
svg_polyline({points: [[400, 100], [480, 100], [450, 200], [480, 250]], color: "brown", width: 10}),
svg_text({text: "this is a really long string", x: 50, y: 50, size: 30, color: "red", border_width: 2, border_color: "black", style: 'font-weight:bold;'}),
svg_html({html: "<i style='font-size:30px;'>yikes</i>", x: 60, y: 100})
]}),
width: 600, // window width
height: 200, // window height
x: 0, // Distance from left of DDE window to this window's left
y: 100, // Distance from top of DDE window to this window's top
callback: handle1
})
//SVG Example 2: draw circle then move it to clicked position.
function handle2 (vals){
if(window.c_id) {
set_in_ui("c_id.cx", vals.offsetX)
set_in_ui("c_id.cy", vals.offsetY)
}
else {
append_in_ui(
"s2_id",
svg_circle({id: "c_id", cx: vals.offsetX, cy: vals.offsetY,
r: 15, color: "blue"}))
}
}
show_window({
title: "SVG Example 2: Click to draw and move circle",
content: svg_svg({id: "s2_id", width: 600, height: 200, html_class: "clickable"}),
x: 0,
y: 330,
width: 600,
height: 200,
callback: handle2
})
//SVG Example 3: draw line segments
var linex = null
var liney = null
function handle3 (vals){
if(linex) {
append_in_ui(
"s3_id",
svg_line({x1: linex, y1: liney, x2: vals.offsetX, y2: vals.offsetY}))
}
else {
append_in_ui(
"s3_id",
svg_circle({cx: vals.offsetX, cy: vals.offsetY,
r: 5, color: "blue"}))
}
linex = vals.offsetX
liney = vals.offsetY
}
show_window({
title: "SVG Example 3: Click to draw lines",
content: svg_svg({id: "s3_id", width: 400, height: 400, html_class: "clickable",
child_elements: [
svg_rect({x: 100, y: 100, width: 200, height: 50, color: "yellow"})
]}),
x: 620,
y: 100,
callback: handle3
})
`)}
build_window_id.onclick=ab.launch
opencv_gray_id.onclick=function(){
const code = read_file(__dirname + "/examples/opencv_gray.js")
Editor.insert(code)
}
opencv_blur_id.onclick=function(){
const code = read_file(__dirname + "/examples/opencv_blur.js")
Editor.insert(code)
}
opencv_in_range_id.onclick=function(){
const code = read_file(__dirname + "/examples/opencv_in_range.js")
Editor.insert(code)
}
opencv_blob_detector_id.onclick=function(){
const code = read_file(__dirname + "/examples/opencv_blob_detector.js")
Editor.insert(code)
open_doc("Picture.detect_blobs_doc_id")
}
opencv_process_webcam_id.onclick=function(){
const code = read_file(__dirname + "/examples/opencv_process_webcam.js")
Editor.insert(code)
}
opencv_face_reco_id.onclick=function(){
const code = read_file(__dirname + "/examples/opencv_face_reco.js")
Editor.insert(code)
}
opencv_locate_object_id.onclick=function(){
const code = read_file(__dirname + "/examples/opencv_locate_object.js")
Editor.insert(code)
open_doc("Picture.locate_object_doc_id")
}
opencv_picture_similarity_id.onclick=function(){
const code = read_file(__dirname + "/examples/opencv_picture_similarity.js")
Editor.insert(code)
open_doc("Picture.mats_similarity_by_color_doc_id")
}
window_close_all_id.onclick=close_all_show_windows
machine_vision_help_id.onclick = function(){open_doc(machine_vision_doc_id)}
show_page_id.onclick=function(){Editor.wrap_around_selection('show_page(', ')\n', '"hdrobotic.com"')}
get_page_id.onclick=function(){Editor.insert(
`//Return the content of the given URL.
//Scripts on the page will not be run, forms and links
//generally won't work, CSS styles won't be applied.
get_page("http://www.ibm.com")
//get_page is also useful for getting data on the web.
//Most such date requires passwords or keys.
//A couple that don't
get_page("http://jsonip.com") //returns your IP address
get_page("http://www.nactem.ac.uk/software/acromine/dictionary.py?sf=BMI") //Medical acronym defs. Takes 15 seconds or so.
//If you're getting a string representing JSON, pass that string
//as the first argument to the function JSON.parse to get an object.
//Retrieve the html text of a url and pass it as
//the first argument to a callback
get_page_async("http://www.ibm.com", function(err, response, body){ out(body.length) })
//The default for the 2nd arg is the DDE function 'out'.
//out redenders its html string argument in the output pane
//so you will see much of the actual text and markup
//of a page, but not its images or other media.
`)}
beep_id.onclick = function(){Editor.insert("beep()\n")}
beep_options_id.onclick = function(){Editor.insert(
`beep({
dur: 0.5, //the default,,
frequency: 440, //the default, in Hertz. This is A above middle C.
volume: 1, //the default, 0 to 1
waveform: "triangle", //the default, other choices: "sine", "square", "sawtooth"
callback: function(){beep({frequency: 493.88})} //default=null, run at end of the beep
})
`
)}
beeps_id.onclick = function(){Editor.insert(
`beeps(3, //default=1. number of times to beep using the default beep.
function(){speak({speak_data: "Third Floor, home robots"})}) //default=null. callback when done
`)}
speak_id.onclick=function(){Editor.wrap_around_selection(
"speak({speak_data: ", "})\n", '"Hello Dexter"')}
speak_options_id.onclick=function(){Editor.wrap_around_selection(
`speak({
speak_data: ` , //default="hello" can be a string, number, boolean, date, array, etc.
`,\n volume: 1.0, //default=1.0 0 to 1.0,
rate: 1.0, //default=1.0 0.1 to 10,
pitch: 1.0, //default=1.0 0 to 2,
lang: "en-US", //default="en-US"
voice: 0, //default=0 0, 1, 2, or 3
callback: function(event) {out('Dur in nsecs: ' + event.elapsedTime)} //default=null called when speech is done.
})\n`, '[true, "It is", new Date()]')}
/*recognize_speech_id.onclick = function(){Editor.insert(
`recognize_speech(
{prompt: "Say something funny.", //Instructions shown to the speaker. Default "".
click_to_talk: false, //If false, speech recognition starts immediately. Default true.
only_once: false, //If false, more than one phrase (after pauses) can be recognized. Default true.
phrase_callback: undefined, //Passed text and confidence score when user pauses. Default (undefined) prints text and confidence. If only_once=true, only this callback is called.
finish_phrase: "finish", //Say this to end speech reco when only_once=false.
finish_callback: out}) //Passed array of arrays of text and confidence when user says "finish". Default null.
`)}*/
music_help_id.onclick=function(){ open_doc(music_with_midi_doc_id) }
phrase_examples_id.onclick=function(){
const code = read_file(__dirname + "/music/phrase_examples.js")
Editor.insert(code)
}
midi_init_id.onclick = Midi.init
//eval_and_start_button_id.onclick = eval_and_start
make_dictionary_id.onclick=function(){
const code = read_file(__dirname + "/examples/make_dictionary.js")
Editor.insert(code)
}
nat_lang_reasoning_id.onclick=function(){
const code = read_file(__dirname + "/examples/nat_lang_reasoning.js")
Editor.insert(code)
}
ez_teach_id.onclick=function(){
Editor.edit_new_file()
Editor.insert(read_file(__dirname + "/user_tools/ezTeach_template.js"))
open_doc(ez_teach_doc_id)
}
jobs_help_id.onclick = function(){ open_doc(Job_doc_id) }
//start_job_id.onclick = Job.start_job_menu_item_action
//start_job_help_id.onclick = function(){ open_doc(start_job_help_doc_id) } //nw help is simply under theh Output pane help, and users see it by clicking on the "Output" pane title.
test_suites_help_id.onclick = function(){ open_doc(TestSuite_doc_id) }
insert_all_test_suites_id.onclick = function(){TestSuite.insert_all()}
run_all_test_suites_id.onclick = function(){TestSuite.run_all()}
// show_all_test_suites_id.onclick = function(){TestSuite.show_all()} //functionality obtained with Find and no selection
run_test_suite_file_id.onclick = TestSuite.run_ts_in_file_ui
//obsoleted by increased functionality in doc pane Find button. find_test_suites_id.onclick = function(){TestSuite.find_test_suites(Editor.get_any_selection())}
selection_to_test_id.onclick=function(){
TestSuite.selection_to_test(Editor.get_javascript(true), Editor.get_javascript(), Editor.selection_start())
}
show_suite_statistics_id.onclick=TestSuite.statistics
insert_test_suite_example_id.onclick=function(){
Editor.insert( //below the same as the first test suite in the main test suites except that
//its name is different so that the "summary" doesn't subtract the
//usual 2 unknown failures and thus the summary of runnign this
//will be consistent with the errors it shows.
`new TestSuite(
"example_test_suite",
["2 + 3", "5", "1st elt (source) evals to same as 2nd elt (expected) and the test passes."],
['similar(2.05, 2, 0.1)', "true", "tolerance of 0.1 permits 2.05 and 2 to be similar"],
["var foo = 4 + 1"],
["foo", "5", "The side effect of the above 'set up' test, sets foo. Foo's value is tested here."],
['"hi" + " dexter"', '"hi dex"', "known failures are declared with this description string starting with 'known'."],
['foo961', '123', "This is an 'unknown failure' for demo purposes"],
['foo723', 'TestSuite.error', 'Tests with expected of TestSuite.error pass if the source errors.'],
['out(TestSuite.run("similarX"))', 'TestSuite.dont_care', "Run another test suite. This one errors because its not defined."]
)
`, null, true)}
//TestSuite.make_suites_menu_items() //because the ones that are defined from TestSuite.js can't make their menu items until dom is ready
//Learn Javascript menu
learn_js_help_id.onclick = function (){open_doc(learning_js_doc_id)}
// Debugging menu
dev_tools_id.onclick = function(){show_window({content:
"To see the output of <code>console.log</code> calls,<br/>" +
"and for using the <code>debugger</code> breakpoint,<br/>" +
"you must first open <i>Chrome Dev Tools</i> by:<br/>" +
"clicking right anywhere and choosing <b>Inspect</b>.<p/>" +
"Note: The <b>out</b> call is more useful in most cases than <code>console.log</code>. " +
"It doesn't require <i>Chrome Dev Tools</i>.<br/>See <button>Insert▼</button> <i>Print to output</i>.<br/><br/>" +
"There's more help in the Documentation pane under <b>Debugging</b>.",
title: "Debugging Help", width:430, height:270});
open_doc(debugging_id)
//WORKS! 800 is milliseconds for the animation to take.
//$('#doc_contents_id').animate({scrollTop: $('#d ebugging_id').offset().top}, 800); //jquery solution that fails.
//d ebugging_id.scrollIntoView(true) //does so instantaneously but it at least works.
//However, it causes the DDE header to scroll off the top of the window
//and a user can't get it back. If the user has not expanded any triangles
//in the doc pane, then NOT calling scrollIntoView is fine, but if they have.
//they likely won't see the Debugging content. Probably an interaction between
//this new HTML5 stuff and jqwidgets
// the below fail.
//poitions the top of the elt at the top of the pane, which is good.
//d ebugging_id.scrollIntoView({behavior:"smooth"});//doesn't smooth scroll in chrome
//$("#d ebugging_id").parent().animate({scrollTop: $("#debugging_id").offset().top}, 1000) //doesn't work
} //fails: window.open("chrome://inspect/#apps")
console_log_id.onclick = function(){Editor.wrap_around_selection("console.log(", ")", '"Hello"')}
debugger_id.onclick = function(){Editor.insert("debugger;nnll")}
debugger_instruction_id.onclick = function(){
let cursor_pos = Editor.selection_start()
let src = Editor.get_javascript()
let prev_char = ((cursor_pos == 0) ? null : src[cursor_pos - 1])
let prefix
if (Editor.selection_start() == 0) {prefix = ""}
else if ("[, \n]".includes(prev_char)) {prefix = ""}
else {prefix = ","}
Editor.insert(prefix + 'Control.debugger(),nnll') //ok if have comma after last list item in new JS.
}
comment_out_id.onclick = function(){Editor.wrap_around_selection("/*", "*/")}
comment_eol_id.onclick = function(){Editor.insert("//")}
//true & false menu
true_id.onclick = function(){Editor.insert(" true ")}
false_id.onclick = function(){Editor.insert(" false ")}
and_id.onclick = function(){Editor.insert(" && ")}
or_id.onclick = function(){Editor.insert(" || ")}
not_id.onclick = function(){Editor.insert("!")}
//Math menu
math_example_id.onclick = function(){Editor.insert("(-1.75 + 3) * 2\n")}
plus_id.onclick = function(){Editor.insert("+")}
minus_id.onclick = function(){Editor.insert("-")}
times_id.onclick = function(){Editor.insert("*")}
divide_id.onclick = function(){Editor.insert("/")}
pi_id.onclick = function(){Editor.insert("Math.PI")}
parens_id.onclick = function(){Editor.wrap_around_selection("(", ")")}
//Compare Numbers menu
compare_example_id.onclick = function(){Editor.insert("Math.PI >= 3\n")}
less_id.onclick = function(){Editor.insert("<")}
less_or_equal_id.onclick = function(){Editor.insert("<=")}
equal_id.onclick = function(){Editor.insert("==")}
more_or_equal_id.onclick = function(){Editor.insert(">=")}
more_id.onclick = function(){Editor.insert(">")}
not_equal_id.onclick = function(){Editor.insert("!=")}
//Strings menu
double_quote_id.onclick = function(){Editor.wrap_around_selection('"', '"')}
single_quote_id.onclick = function(){Editor.wrap_around_selection("'", "'")}
back_quote_id.onclick = function(){Editor.wrap_around_selection('`', '`')}
add_strings_id.onclick = function(){Editor.insert("+")}
string_length_id.onclick = function(){Editor.insert(".length")}
get_char_id.onclick = function(){Editor.insert("[0]")}
slice_id.onclick = function(){Editor.insert(".slice(0, 3)")}
split_id.onclick = function(){Editor.insert('.split(" ")')}
string_equal_id.onclick = function(){Editor.insert('==')}
starts_with_id.onclick = function(){Editor.insert('.startsWith("ab")')}
ends_with_id.onclick = function(){Editor.insert('.endsWith("yz")')}
replace_string_id.onclick = function(){Editor.insert('.replace(/ab/g, "AB")')}
//Arrays menu
make_array_id.onclick = function(){Editor.insert('[5, "ab", 2 + 2]')}
array_length_id.onclick = function(){Editor.insert('.length')}
get_array_element_id.onclick = function(){Editor.insert('[0]')}
set_array_element_id.onclick = function(){Editor.insert('[0] = 42')}
push_array_element_id.onclick = function(){Editor.insert('.push(9)')}
//DATE
new_date_day_id.onclick = function(){Editor.insert('new Date("' + new Date().toString().slice(4, 15) + '")')}
new_date_time_id.onclick = function(){Editor.insert('new Date("' + new Date().toString().slice(4, 24) + '")')}
new_date_ms_id.onclick = function(){Editor.insert('new Date(3000)')}
date_now_id.onclick = function(){Editor.insert('Date.now()')}
date_valueOf_id.onclick = function(){Editor.insert('new Date().valueOf()')}
date_toString_id.onclick = function(){Editor.insert('new Date().toString()')}