Author Topic: QBJS - QBasic for the Web  (Read 40592 times)

0 Members and 1 Guest are viewing this topic.

FellippeHeitor

  • Guest
Re: QBJS - QBasic for the Web
« Reply #75 on: March 16, 2022, 01:06:14 pm »
Man, this is just so amazing. Galleon intended to bring QB64 into the web with a javascript core one day™️, you just went ahead and did it yourself. The integration blows my mind, with parameters going back and forth between basic code and javascript. You are on fire, man. 🔥

Offline dbox

  • Newbie
  • Posts: 80
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #76 on: March 16, 2022, 03:15:58 pm »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #77 on: March 16, 2022, 04:38:13 pm »
@dbox yeah so recursive does work, fantastic!
Code: QB64: [Select]
  1. _Title "Basic Tree from branch"
  2. 'Randomize Timer
  3. Screen _NewImage(800, 600, 32)
  4. '_ScreenMove 300, 20
  5. Color _RGB32(0, 255, 0)
  6.  
  7. 'just test call to sub
  8. '       x,   y,  270, .2*height, 1  start a tree with 270 degrees to point up, and about 1/5 the height you want to grow the tree
  9. branch 400, 500, 270, 100, 1
  10. Print "press any to see the forest..."
  11.  
  12. Dim horizon, i, y
  13. horizon = .35 * _Height
  14. For i = 0 To horizon
  15.     Line (0, i)-(_Width, i), _RGB(0, 0, .25 * i + 100)
  16. For i = horizon To _Height
  17.     Line (0, i)-(_Width, i), _RGB(0, 255 - .25 * i - 50, 0)
  18. For i = 1 To 250
  19.     y = randWeight(horizon, _Height, 3)
  20.     branch _Width * Rnd, y, 270, (.015 * Rnd + .027) * y, 1
  21.  
  22. Sub branch (x, y, angD, lngth, lev)
  23.     Dim x2, y2, l
  24.     x2 = x + Cos(_D2R(angD)) * lngth
  25.     y2 = y + Sin(_D2R(angD)) * lngth
  26.     Line (x, y)-(x2, y2), _RGB32(Rnd * 100, Rnd * 170 + 80, Rnd * 50)
  27.     If lev > 6 Or lngth < 2 Then Exit Sub
  28.     l = lev + 1
  29.     branch x2, y2, angD + 10 + 30 * Rnd, .7 * lngth + .2 * Rnd * lngth, l
  30.     branch x2, y2, angD - 10 - 30 * Rnd, .7 * lngth + .2 * Rnd * lngth, l
  31.     If Rnd < .65 Then branch x2, y2, angD + 20 * Rnd - 10, .7 * lngth + .2 * Rnd * lngth, l
  32.  
  33. Function randWeight (manyValue, fewValue, power)
  34.     randWeight = manyValue + Rnd ^ power * (fewValue - manyValue)
  35.  
  36.     _D2R = d * _Pi / 180
  37.  
QBJS tries a recursive!.PNG

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #78 on: March 16, 2022, 04:56:50 pm »
Here's another little tidbit for you.  I put together a simple POC to work out some ideas around allowing the QBJS canvas to interact with other elements on the page.  In this example you can create html elements, add them to a page and even assign events to your QB Subs:
qbjs-dom.png

Code: QB64: [Select]
  1. DomInit
  2. DomAdd "div", "button-panel"
  3. DomAdd "button", "circle-button", "Draw Circle", "button-panel"
  4. DomAdd "button", "rect-button", "Draw Rectangle", "button-panel"
  5. DomAdd "input", "myinput", "", "button-panel"
  6. DomAdd "button", "text-button", "Draw Text", "button-panel"
  7. DomAdd "button", "clear-button", "Clear Screen", "button-panel"
  8.  
  9. Dim panel
  10. panel = DomGet("button-panel")
  11. panel.style.border = "1px solid green"
  12. panel.style.backgroundColor = "#333"
  13. panel.style.padding = "6px"
  14.  
  15. Dim btn
  16. btn = DomGet("circle-button")
  17. btn.onclick = sub_OnBtnCircleClick
  18. btn = DomGet("rect-button")
  19. btn.onclick = sub_OnBtnRectClick
  20. btn = DomGet("text-button")
  21. btn.onclick = sub_OnBtnTextClick
  22. btn = DomGet("clear-button")
  23. btn.onclick = sub_OnBtnClearClick
  24. btn.style.marginLeft = "15px"
  25.  
  26. Dim myinput
  27. myinput = DomGet("myinput")
  28. myinput.style.marginLeft = "15px"
  29.  
  30. Sub OnBtnCircleClick
  31.     Circle (Rnd * 600, Rnd * 380), 10 + Rnd * 90, Rnd * 14 + 1
  32.  
  33. Sub OnBtnRectClick
  34.     Dim As Integer x, y, w, h
  35.     x = Rnd * 600
  36.     y = Rnd * 380
  37.     w = Rnd * 90 + 10
  38.     h = Rnd * 90 + 10
  39.     Line (x, y)-(x + w, y + h), Rnd * 14 + 1, B
  40.  
  41. Sub OnBtnTextClick
  42.     If myinput.value <> "" Then
  43.         Color Rnd * 14 + 1
  44.         _PrintString (Rnd * 600, Rnd * 380), myinput.value
  45.     End If
  46.  
  47. Sub OnBtnClearClick
  48.     Cls
  49.  
  50. ' ------------------------------------------------------------------
  51. ' HTML DOM API Methods
  52. ' ------------------------------------------------------------------
  53. Sub DomAdd (etype As String, eid as String, content As String, parentId As String)
  54. $If Javascript
  55.     if (document.getElementById(eid)) { return; }
  56.     var e = document.createElement(etype);
  57.     e.id = eid;
  58.     e.className = "qbjs";
  59.     if (content != undefined) {
  60.         e.innerHTML = content;
  61.     }
  62.     if (parentId == undefined || parentId == "") {
  63.         parentId = "gx-container";    
  64.     }
  65.     document.getElementById(parentId).appendChild(e);
  66.        
  67. Function DomGet (eid as String)
  68.     $If Javascript
  69.         return document.getElementById(eid);
  70.     $End IF
  71.            
  72. Sub DomInit
  73. $If Javascript
  74.     var elements = document.getElementsByClassName("qbjs");
  75.     for (var i=0; i < elements.length; i++) {
  76.         elements[i].remove();
  77.     }

View in QBJS

Assuming this approach is useful I may look at building in the DOM API methods as new QBJS Keywords.

Holy cow, getting JS and Basic both if I understand!?

Offline dbox

  • Newbie
  • Posts: 80
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #79 on: March 16, 2022, 05:44:10 pm »
Here are a couple more quick web examples:

Copy Cat
This one copies the text to the QBJS canvas as well as another HTML element as the user types into a textarea control:
Code: QB64: [Select]
  1. Screen _NewImage(640, 200)
  2. DomInit
  3. DomAdd "div", "content-panel"
  4. DomAdd "textarea", "text-src", "", "content-panel"
  5. DomAdd "div", "text-div", "", "content-panel"
  6.  
  7. Dim Shared textArea
  8. textArea = DomGet("text-src")
  9. textArea.style.width = "640px"
  10. textArea.style.height = "100px"
  11. textArea.onkeyup = sub_OnTextChange
  12.  
  13. Dim Shared copyDiv
  14. copyDiv = DomGet("text-div")
  15. copyDiv.style.width = "640px"
  16. copyDiv.style.margin = "0 auto"
  17. copyDiv.style.padding = "10px"
  18. copyDiv.style.border = "1px solid green"
  19. copyDiv.style.textAlign = "left"
  20. copyDiv.style.backgroundColor = "#333"
  21. copyDiv.style.fontFamily = "arial, helvetica, sans-serif"
  22. copyDiv.style.whiteSpace = "pre"
  23.  
  24. Sub OnTextChange
  25.     Cls
  26.     Locate 1, 1
  27.     Print textArea.value
  28.     copyDiv.innerHTML = textArea.value
  29.  
  30.  
  31. ' ------------------------------------------------------------------
  32. ' HTML DOM API Methods
  33. ' ------------------------------------------------------------------
  34. Sub DomAdd (etype As String, eid as String, content As String, parentId As String)
  35. $If Javascript
  36.     if (document.getElementById(eid)) { return; }
  37.     var e = document.createElement(etype);
  38.     e.id = eid;
  39.     e.className = "qbjs";
  40.     if (content != undefined) {
  41.         e.innerHTML = content;
  42.     }
  43.     if (parentId == undefined || parentId == "") {
  44.         parentId = "gx-container";    
  45.     }
  46.     document.getElementById(parentId).appendChild(e);
  47.        
  48. Function DomGet (eid as String)
  49.     $If Javascript
  50.         return document.getElementById(eid);
  51.     $End IF
  52.            
  53. Sub DomInit
  54. $If Javascript
  55.     var elements = document.getElementsByClassName("qbjs");
  56.     for (var i=0; i < elements.length; i++) {
  57.         elements[i].remove();
  58.     }

View in QBJS

QBJS Paint
This one extends the first simple drawing program example that was added to the QBJS site by adding an HTML5 color picker that is used to change the current drawing color:
Code: QB64: [Select]
  1. Screen _NewImage(640, 200)
  2. DomInit
  3. DomAdd "div", "content-panel"
  4. DomAdd "textarea", "text-src", "", "content-panel"
  5. DomAdd "div", "text-div", "", "content-panel"
  6.  
  7. Dim Shared textArea
  8. textArea = DomGet("text-src")
  9. textArea.style.width = "640px"
  10. textArea.style.height = "100px"
  11. textArea.onkeyup = sub_OnTextChange
  12.  
  13. Dim Shared copyDiv
  14. copyDiv = DomGet("text-div")
  15. copyDiv.style.width = "640px"
  16. copyDiv.style.margin = "0 auto"
  17. copyDiv.style.padding = "10px"
  18. copyDiv.style.border = "1px solid green"
  19. copyDiv.style.textAlign = "left"
  20. copyDiv.style.backgroundColor = "#333"
  21. copyDiv.style.fontFamily = "arial, helvetica, sans-serif"
  22. copyDiv.style.whiteSpace = "pre"
  23.  
  24. Sub OnTextChange
  25.     Cls
  26.     Locate 1, 1
  27.     Print textArea.value
  28.     copyDiv.innerHTML = textArea.value
  29.  
  30.  
  31. ' ------------------------------------------------------------------
  32. ' HTML DOM API Methods
  33. ' ------------------------------------------------------------------
  34. Sub DomAdd (etype As String, eid as String, content As String, parentId As String)
  35. $If Javascript
  36.     if (document.getElementById(eid)) { return; }
  37.     var e = document.createElement(etype);
  38.     e.id = eid;
  39.     e.className = "qbjs";
  40.     if (content != undefined) {
  41.         e.innerHTML = content;
  42.     }
  43.     if (parentId == undefined || parentId == "") {
  44.         parentId = "gx-container";    
  45.     }
  46.     document.getElementById(parentId).appendChild(e);
  47.        
  48. Function DomGet (eid as String)
  49.     $If Javascript
  50.         return document.getElementById(eid);
  51.     $End IF
  52.            
  53. Sub DomInit
  54. $If Javascript
  55.     var elements = document.getElementsByClassName("qbjs");
  56.     for (var i=0; i < elements.length; i++) {
  57.         elements[i].remove();
  58.     }

View in QBJS

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #80 on: March 16, 2022, 10:19:23 pm »
Man, this is just so amazing. Galleon intended to bring QB64 into the web with a javascript core one day™️, you just went ahead and did it yourself. The integration blows my mind, with parameters going back and forth between basic code and javascript. You are on fire, man. 🔥

Yep. one down, one to go on that wish list of his, JAVA. Rob wanted to redo QB64 in JAVA, so it could be used to make mobile apps for Android devices. Honestly for the time, circa 2007, C/C++ seemed to be the most stable choice, and PCs and laptops were in the user majority. JAVA would have satisfied both, and can be run on Apple and Linux too, but I guess a couple JAVA versions were blocked by Apple in the past.

Oh, and a post for history sake: https://www.tapatalk.com/groups/qbasic/welcome-to-the-qb64-forum-t36432.html#p158976 
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #81 on: March 16, 2022, 10:25:03 pm »
@dbox   This is game I wanted to try tonight. The arrow keys work great! Miss a little noise maker when yellow square, our hero, hits a circle, now I just pause action so you can read your hits.

Actually a couple people here have posted similar game. While playing tonight I came up with new idea for scoring, TBA, say tuned!


Code: QB64: [Select]
  1. Dim As Long HX, HY, i, hits, score, Stars, nEnemies, Height
  2. HX = 320: HY = 400: nStars = 1000: nEnemies = 50: Height = 480
  3. Dim EX(nEnemies), EY(nEnemies), EC(nEnemies) As _Unsigned Long ' enemy stuff
  4. Screen _NewImage(640, Height, 32)
  5. Stars = _NewImage(640, Height, 32)
  6. For i = 1 To nStars
  7.     PSet (Int(Rnd * 640), Int(Rnd * 480)), _RGB32(55 + Rnd * 200, 55 + Rnd * 200, 55 + Rnd * 200)
  8. _PutImage , 0, Stars
  9. For i = 1 To nEnemies
  10.     EX(i) = Int(Rnd * 600 + 20): EY(i) = -2 * Height * Rnd + Height: EC(i) = _RGB32(55 + Rnd * 200, 55 + Rnd * 200, 55 + Rnd * 200)
  11.     Cls
  12.     _PutImage , Stars, 0
  13.     Print "Hits:"; hits, "Score:"; score
  14.     Line (HX - 10, HY - 10)-Step(20, 20), _RGB32(255, 255, 0), BF
  15.     For i = 1 To nEnemies ' the enemies
  16.         Circle (EX(i), EY(i)), 10, EC(i)
  17.         If Sqr((EX(i) - HX) ^ 2 + (EY(i) - HY) ^ 2) < 20 Then 'collision
  18.             _Delay .5
  19.             hits = hits + 1
  20.             EX(i) = Int(Rnd * 600 + 20): EY(i) = -Height * Rnd ' move that bad boy!
  21.             If hits = 10 Then Print "Too many hits, goodbye!": End
  22.         End If
  23.         EY(i) = EY(i) + Int(Rnd * 5)
  24.         If EY(i) > 470 Then EX(i) = Int(Rnd * 600 + 20): EY(i) = -Height * Rnd: score = score + 1
  25.     Next
  26.     If _KeyDown(20480) Then HY = HY + 3
  27.     If _KeyDown(18432) Then HY = HY - 3
  28.     If _KeyDown(19200) Then HX = HX - 3
  29.     If _KeyDown(19712) Then HX = HX + 3
  30.     If HX < 10 Then HX = 10
  31.     If HX > 630 Then HX = 630
  32.     If HY < 10 Then HY = 10
  33.     If HY > 470 Then HY = 470
  34.     _Display
  35.     _Limit 100
  36.  
  37.  

There is some flicker and odd where it is printing.

share:
https://v6p9d9t4.ssl.hwcdn.net/html/5429488/index.html?qbcode=JEaW0BACgufDTG9uZ2CkLEAWOCkLOsA01A2hpdHP5Ec2NvcmVwIpujC5OduO3IrcytrSyudsKkMrSztDooAVLgA9yAMxAMkAMLgHXTXkAaFlPzFblN0YXJzw6AGLua7mfEA1Kd+/SMA4ND2gFFWLQCiAACm+kFFWa9Kv3QKKh782u1qAvnjqrc5tLO3MrJAWQBPYCMrcytrzJiObo6szMN4VTY3JlZW7iujpzK7pLaws7K1UA2DYyDdOq62XXcYtYT0Mw11lJYCRm9ylF+YxQKo37qH+GGoKbK6b3YSS3OkxAlJuZOSAVZZ4fXb3te87L14y62/BKSOhYMh+YrGAV3y73DvsvlLWVlJDvOVHC4NnS9STDDTmV4dEvHR1B1dEltYWdl6xXCbDbPTxt26pf7NEuOva2v78uqztFRe2UFKb9gAWo7dzLi0uCXSgmvx4F9ZglLv5M+6ZbWvhyat8026HXp1cbuqkFhkFEb3/6OEhtjnL/fM9d4vdP8QIoOTS3OnWAESGGkNLo5wwJ0RJoB3iDYKAEU2NvcmUBteCX/7UNMaW5l5BMA0VNiOw4tSM2Iam6MrhN9NwqT8VWdCcGtfBrX7k+mgoSM3/a9fRmbXqbO2YJ0aGXdBmVuZW1pZXOf//lYqG0uTG2MvN7u5ZuCFywNnS2xDcFv//WgUlmyMJTcXIRMFcG2xIa4AvddjIOl4dPPBjL1LOwDztPcw1RoZW7ZVAhjb2xsaXNpb26v///7UfERGVsYXnRgC6Ff///2PD0vHo1/wDt3hpmxN0LnjEJ1I1jde8tOF/AuVLhZQ21vdmVgg3RoYXRYQmJhZHACYm95lYBDUADuXMzcoc+6J3tsEqN7evQbawtzyk+d+Mzt7eyMTyy7LsASI6W4JFbmSgB/a2tAD+zhhunaywmcerFr7FQCeXNY5YUA+TvzAN4ZR+c301fvKVqREJn8bssHfON1mytV3l7eM+qbqBlKBfs98GS2V5RG93bt//rZT+0szHrwVJlAgPMLeeISzOjtYILxMXVaYQHuvc9V8A5l/+3Mv3jLZ2aYR3vv89d61/DHbudrxCTOkwqKSoknkNffJPTDI1qRdvXyO6PETr6walVFkvmJheq/2Dm4OxYIv9ncnrNxf3DzTRkRpc3BsYXm4ee+ETGltaXRX/9+JDTG9vcEYEVW50aWx7p9eR2rTLxFNsZWVwvAg=


I've got another I hope I can get working tomorrow.
« Last Edit: March 16, 2022, 10:30:54 pm by bplus »

Offline dbox

  • Newbie
  • Posts: 80
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #82 on: March 16, 2022, 11:35:03 pm »
Nice one @bplus!  Looks like the flicker is related to the screen scrolling that happens when you print a newline on the last viewable line of the page.  I found that if you replace the Print call on line 16 with this...
Code: QB64: [Select]
  1.     Locate 30, 1
  2.     Print "Hits:"; hits, "Score:"; score;
... the display is nice and smooth.

View Mod in QBJS

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #83 on: March 17, 2022, 07:02:33 am »
Ah! in QB64 a CLS restarts Print line at top, line 1, so CLS in QBJS is not doing that! Thus the need for Locate.

That score should always be at the top.
« Last Edit: March 17, 2022, 07:14:08 am by bplus »

Offline dbox

  • Newbie
  • Posts: 80
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #84 on: March 17, 2022, 09:16:39 am »
Aha, good catch @bplus!  I've added that to the Known Issues page as well as the fix list for the next release on the Roadmap page.

Offline dbox

  • Newbie
  • Posts: 80
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #85 on: March 17, 2022, 12:42:12 pm »
Played around a bit more with the QBJS Paint program.  Here's a version that will allow you to select different drawing tools and has 1 level of undo:
Code: QB64: [Select]
  1. CreateToolbar
  2. Dim fimage, cimage
  3. fimage = _NewImage(640, 400)
  4. cimage = _NewImage(640, 400)
  5.  
  6. Dim drawing, lastX, lastY, startX, startY, tool, radius
  7.         If Not drawing Then
  8.             _PutImage , cimage, fimage
  9.             '_FreeImage cimage
  10.             cimage = _NewImage(640, 400)
  11.             lastX = _MouseX
  12.             lastY = _MouseY
  13.             startX = lastX
  14.             startY = lastY
  15.             drawing = -1
  16.             DomGet("btn-undo").disabled = false
  17.         Else
  18.             tool = DomGet("tool").value
  19.            
  20.             If tool = "Freehand" Then
  21.                 _Dest cimage
  22.                 Line (lastX, lastY)-(_MouseX, _MouseY), SelectedColor
  23.                 lastX = _MouseX
  24.                 lastY = _MouseY
  25.                 _Dest 0
  26.                
  27.             ElseIf tool = "Line" Then
  28.                 '_FreeImage cimage
  29.                 cimage = _NewImage(640, 400)
  30.                 _Dest cimage
  31.                 Line (startX, startY)-(_MouseX, _MouseY), SelectedColor
  32.                 _Dest 0
  33.  
  34.             ElseIf tool = "Rectangle" Then
  35.                 '_FreeImage cimage
  36.                 cimage = _NewImage(640, 400)
  37.                 _Dest cimage
  38.                 Line (startX, startY)-(_MouseX, _MouseY), SelectedColor, B
  39.                 _Dest 0
  40.  
  41.             ElseIf tool = "Filled Rectangle" Then
  42.                 '_FreeImage cimage
  43.                 cimage = _NewImage(640, 400)
  44.                 _Dest cimage
  45.                 Line (startX, startY)-(_MouseX, _MouseY), SelectedColor, BF
  46.                 _Dest 0
  47.  
  48.             ElseIf tool = "Circle" Then
  49.                 '_FreeImage cimage
  50.                 cimage = _NewImage(640, 400)
  51.                 If Abs(_MouseX - startX) > Abs(_MouseY - startY) Then
  52.                     radius = Abs(_MouseX - startX)
  53.                 Else
  54.                     radius = Abs(_MouseY - startY)
  55.                 End If
  56.                 _Dest cimage
  57.                 Circle (startX, startY), radius, SelectedColor
  58.                 _Dest 0
  59.  
  60.             ElseIf tool = "Filled Circle" Then
  61.                 '_FreeImage cimage
  62.                 cimage = _NewImage(640, 400)
  63.                 If Abs(_MouseX - startX) > Abs(_MouseY - startY) Then
  64.                     radius = Abs(_MouseX - startX)
  65.                 Else
  66.                     radius = Abs(_MouseY - startY)
  67.                 End If
  68.                 _Dest cimage
  69.                 Dim r
  70.                 For r = 0 To radius Step .3
  71.                     Circle (startX, startY), r, SelectedColor
  72.                 Next r
  73.                 _Dest 0
  74.  
  75.             End If
  76.        
  77.         End If
  78.     Else
  79.         drawing = 0
  80.     End If
  81.     Cls
  82.     _PutImage , fimage
  83.     _PutImage , cimage
  84.     _Limit 30
  85. Loop    
  86.  
  87. Sub OnBtnUndo
  88.     '_FreeImage cimage
  89.     cimage = _NewImage(640, 400)
  90.     DomGet("btn-undo").disabled = true
  91.  
  92. Sub CreateToolbar
  93.     DomInit
  94.     DomAdd "div", "control-panel"
  95.     DomAdd "span", "label1", "Tool: ", "control-panel"
  96.     DomAdd "select", "tool", "", "control-panel"
  97.     DomAdd "span", "label2", "Color: ", "control-panel"
  98.     DomAdd "input", "color-picker", "", "control-panel"
  99.    
  100.     Dim btnUndo
  101.     btnUndo = DomAdd("button", "btn-undo", "Undo", "control-panel")
  102.     'btnUndo.style.marginLeft = "15px"
  103.     btnUndo.style.float = "right"
  104.     btnUndo.style.padding = "5px 10px"
  105.     btnUndo.disabled = true
  106.     btnUndo.onclick = sub_OnBtnUndo
  107.  
  108.     Dim panel
  109.     panel = DomGet("control-panel")
  110.     panel.style.textAlign = "left"
  111.     panel.style.width = "640px"
  112.     panel.style.margin = "0 auto"
  113.     panel.style.padding = "5px"
  114.     panel.style.fontFamily = "Arial, helvetica, sans-serif"
  115.     panel.style.fontSize = ".85em"
  116.     panel.style.border = "1px solid #666"
  117.     panel.style.backgroundColor = "#333"
  118.     panel.style.verticalAlign = "middle"
  119.  
  120.     Dim cp
  121.     cp = DomGet("color-picker")
  122.     cp.type = "color"
  123.     cp.value = "#ffffff"
  124.        
  125.     InitToolList
  126.    
  127. Sub InitToolList
  128.     Dim ts, topt
  129.     ts = DomGet("tool")
  130.     ts.style.marginRight = "15px"
  131.     ts.style.padding = "5px"
  132.     ts.style.verticalAlign = "top"
  133.     topt = DomAdd("option", "", "Freehand", "tool"): topt.value = "Freehand"
  134.     topt = DomAdd("option", "", "Line", "tool"): topt.value = "Line"
  135.     topt = DomAdd("option", "", "Rectangle", "tool"): topt.value = "Rectangle"
  136.     topt = DomAdd("option", "", "Filled Rectangle", "tool"): topt.value = "Filled Rectangle"
  137.     topt = DomAdd("option", "", "Circle", "tool"): topt.value = "Circle"
  138.     topt = DomAdd("option", "", "Filled Circle", "tool"): topt.value = "Filled Circle"
  139.    
  140. Function SelectedColor    
  141.     Dim r, g, b, c, cp
  142.     cp = DomGet("color-picker")
  143.     c = cp.value
  144.  
  145.     $If Javascript
  146.         r = parseInt(c.substr(1,2), 16)
  147.         g = parseInt(c.substr(3,2), 16)
  148.         b = parseInt(c.substr(5,2), 16)
  149.     $End If
  150.        
  151.     SelectedColor = _RGB(r, g, b)
  152.  
  153.    
  154. ' ------------------------------------------------------------------
  155. ' HTML DOM API Methods
  156. ' ------------------------------------------------------------------
  157. Function DomAdd (etype As String, eid as String, content As String, parentId As String)
  158. $If Javascript
  159.     if (document.getElementById(eid)) { return; }
  160.     var e = document.createElement(etype);
  161.     if (eid != undefined && eid != "") {
  162.         e.id = eid;
  163.     }
  164.     e.className = "qbjs";
  165.     if (content != undefined) {
  166.         e.innerHTML = content;
  167.     }
  168.     if (parentId == undefined || parentId == "") {
  169.         parentId = "gx-container";    
  170.     }
  171.     document.getElementById(parentId).appendChild(e);
  172.     return e;
  173.  
  174. Sub DomAdd (etype As String, eid as String, content As String, parentId As String)
  175.     Dim e: e = DomAdd(etype, eid, content, parentId)
  176.        
  177. Function DomGet (eid as String)
  178. $If Javascript
  179.     return document.getElementById(eid);
  180.            
  181. Sub DomInit
  182. $If Javascript
  183.     var elements = document.getElementsByClassName("qbjs");
  184.     for (var i=0; i < elements.length; i++) {
  185.         elements[i].remove();
  186.     }

View in QBJS

(I also realized in the process that the _FreeImage keyword is not registered correctly, so it's been added to the fix list for the next release.)

Offline dbox

  • Newbie
  • Posts: 80
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #86 on: March 18, 2022, 12:31:47 pm »
Hi All,

As I'm working on planning the next beta release of QBJS I'd love to hear from the community what you'd like to see included next.  Here is my current list for v.0.3.0:

Fixes
* Cls is not resetting the text location to the top left of the screen.
* _FreeImage is being reported as an unrecognized method
* Using the "Call" keyword to call a sub with no arguments causes an error 
  Workaround: Remove the "Call" keyword
* Function calls prefixed with the negative operator (e.g. -_WIDTH) are not converting properly. 
  Workaround: Wrap function call in extra parenthesis (e.g. -(_WIDTH) )

Enhancements
* Add parameter to launch QBJS in "Play" mode with no IDE (mode=play)~~
  * Add checkbox on the share dialog to automatically add this parameter to the generated URL
* Add support for additional string keywords ( @FellippeHeitor let me know if you found some more from your examples ):
  * String$, Space$, Mkl$
* Add support for basic sound keywords:
  * _SndOpen, _SndClose, _SndPlay, _SndLoop, _SndVol, _SndPause, _SndStop
* Add Keywords to interact with HTML DOM (e.g. DomAdd, DomGet)
* Scale canvas to screen size when in fullscreen mode
  * Add support for _FullScreen keyword
* Add support for touch events on mobile
* Show runtime errors traced back to line in basic source in console window


The most up-to-date list is maintained on the QBJS project Roadmap page.

Offline dbox

  • Newbie
  • Posts: 80
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #87 on: March 30, 2022, 11:58:13 pm »
The QBJS v0.3.0 release is out!  You can now go beyond the screen!

Check out the latest here: https://boxgm.itch.io/qbjs.
The full list of fixes and enhancements are in the Release Notes.

This release added more QB/QB64 keywords:
* More string keywords:  String$, Space$, Cvi, Cvl, Mki$, Mkl$
* Sound keywords: _SndOpen, _SndClose, _SndPlay, _SndLoop, _SndVol, _SndPause, _SndStop
* Resize keywords: _Resize, _ResizeWidth, _ResizeHeight

The most major addition to this release is the addition of new QBJS-specific keywords that allow access to create and manipulate HTML page elements and respond to DOM events.  Now rich HTML controls can be used in conjunction with your QBasic application.  Here are several examples:
* Input Controls
* HTML Content
* Web Dialogs
* Multiple Image Canvases
* Simple Drawing (Event-based Version)
* Zoom Tool
   * Event-based Version
* QBJS Paint
   * Event-based Version
* Resize Example
   * Event-based Version
* Sound Keywords

As always I'm very interested in any and all feedback from the community!
« Last Edit: March 31, 2022, 09:31:25 am by dbox »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #88 on: March 31, 2022, 06:48:08 am »
@dbox  You've found a way to load sound files? image files?

Offline dbox

  • Newbie
  • Posts: 80
    • View Profile
Re: QBJS - QBasic for the Web
« Reply #89 on: March 31, 2022, 08:03:29 am »
@bplus - Yes, loading images and sounds are now supported.  In my most recent post there are examples of loading images and sounds from URLs: (Zoom Tool, Sound Keywords).

If you run QBJS on your local machine (by downloading and extracting the qbjs.zip) you can load files from the local filesystem:
Code: QB64: [Select]
  1. Dim img
  2. img = _LoadImage("play.png")
  3. _PutImage (100, 100), img

To load files that are outside of your QBJS folder you can use the file URL format: "file://C:/mypath/myfile.png"