Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 04/27/2019 in all areas

  1. 4 points
    lynkfs

    Responsive Design

    Responsive design in essence consists of 2 measures : style all components as best as possible depending on screen size (larger buttons on mobile, proportional font sizing etc) tweak the layout of forms so that it works best on any given screen size 1) Screen size dependent styling can be done in code and/or is done as other frameworks do by including media queries in the stylesheet. Media queries basically activate different parts of a stylesheet depending on the actual screen size. Smart doesn't implement this in its shipped stylesheets, but there is no reason it can't be done. Just a bit of work. 2) Tweaking the form layout in Smart is possible by doing it in code depending on screensize and orientation - a bit of a pain really using the Layout Manager using some css grid framework or ui kit. For website development I've used the Frow framework quite a bit, but there are many others. using anchors and the CSS grid (which is basically the topic of this post) The new anchors are fantastic, but don't really help in responsive design. Browser window resizing doesn't proportionally resize anchored components. That is unless they are dimensioned depending on screen size beforehand : var W3Panel0 : TW3Panel := TW3Panel.Create(self); W3Panel0.Left := trunc(browserapi.window.innerWidth*0.05); W3Panel0.Top := trunc(browserapi.window.innerHeight*0.05); W3Panel0.Width := trunc(browserapi.window.innerWidth*0.9); W3Panel0.Height := trunc(browserapi.window.innerHeight*0.10); W3Panel0.Anchors := [akLeft, akRight, akTop]; // var W3Panel1 : TW3Panel := TW3Panel.Create(self); W3Panel1.Left := trunc(browserapi.window.innerWidth*0.05); W3Panel1.Top := trunc(browserapi.window.innerHeight*0.15); W3Panel1.Width := trunc(browserapi.window.innerWidth*0.9); W3Panel1.Height := trunc(browserapi.window.innerHeight*0.70); W3Panel1.Anchors := [akLeft, akRight, akTop, akBottom]; W3Panel1.NativeScrolling := true; // var W3Panel2 : TW3Panel := TW3Panel.Create(self); W3Panel2.Left := trunc(browserapi.window.innerWidth*0.05); W3Panel2.Top := trunc(browserapi.window.innerHeight*0.85); W3Panel2.Width := trunc(browserapi.window.innerWidth*0.9); W3Panel2.Height := trunc(browserapi.window.innerHeight*0.10); W3Panel2.Anchors := [akLeft, akRight, akBottom]; As an example the code above produces a header (always on top), a footer (always on the bottom) and a scrollable body inbetween with some proportional margins. The good thing is it works well on all screen sizes, and even on orientation changes, without having to code anything else. Instead of using a grid system with media queries, or doing it in code, it is also possible to use the built-in css grid to get a responsive design. Much easier, see article. If I just plonk the css and html of the first example in that article into the structure above, this is how it ends up looking : Demo Resize browser window to see this in effect (or see it in the responsinator) Not the end-all of all possible responsive design options, but it may fit the bill sometimes. Note : the built-in chrome browser doesn't understand the css grid, so execute from file or server.
  2. 3 points
    lynkfs

    window component

    Just in case anyone has a need for a window component. (multiple windows, movable, resizable, bringtofront, minimise, close, maximise) project
  3. 2 points
    DavidRM

    Node.JS Game Loop

    Here is my Smart Mobile Studio adaptation of the Node.JS "node-gameloop" module. My primary modification was some code to make the *next* interval line up with the desired number of ms per tick. I also tightened the window for choosing SetTimeout vs SetImmediate. I needed this to provide the beating heart of Paintball Net's simulation engine. Which, sure, only beats 10 times per second, but I wanted it to be as accurate as possible. 🙂 -David unit UPBNGameGameLoop; interface uses System.Types, System.Types.Convert, System.Time, System.Streams, System.Reader, System.Writer, System.Device.Storage, SmartNJ.System, SmartNJ.Streams, SmartNJ.Device.Storage, SmartNJ.Application, NodeJS.Core; var GameLoopActive: boolean; type TGameLoopCallback = procedure(delta: float); procedure StartGameLoop(update: TGameLoopCallback; msInterval: integer); procedure StopGameLoop; implementation procedure SetImmediate(const Entrypoint: TProcedureRef); external 'setImmediate'; const Seconds2Nano = 1e9; Nano2Seconds = 1 / Seconds2Nano; MS2Nano = 1e6; Nano2MS = 1 / MS2Nano; var _loopProc: TGameLoopCallback; _loopLengthHR: float; _loopPrevHR, _loopTargetHR: float; function GetHRTime: float; var hrTime: Variant; begin // I need a more up-to-date node to use the bigint() function. // asm // @Result = process.hrtime.bigint(); // end; asm @hrTime = process.hrtime(); end; Result := (hrTime[0] * Seconds2Nano) + hrtime[1]; end; procedure DoGameLoop; var now, delta: float; remaining: integer; begin if GameLoopActive then begin now := GetHRTime; if now >= _loopTargetHR then begin delta := now - _loopPrevHR; _loopPrevHR := now; _loopTargetHR := now + _loopLengthHR; if delta > _loopLengthHR then begin _loopTargetHR -= (delta - _loopLengthHR); end; _loopProc(delta * Nano2Seconds); end; if GameLoopActive then begin remaining := Trunc((_loopTargetHR - GetHRTime) * Nano2MS); if remaining >= 4 {16} then SetTimeout(DoGameLoop, remaining) else SetImmediate(DoGameLoop); end; end; end; procedure StartGameLoop(update: TGameLoopCallback; msInterval: integer); begin if not GameLoopActive then begin GameLoopActive := True; _loopLengthHR := msInterval * MS2Nano; _loopProc := update; _loopPrevHR := GetHRTime; _loopTargetHR := _loopPrevHR; SetImmediate(DoGameLoop); end; end; procedure StopGameLoop; begin GameLoopActive := False; _loopProc := nil; end; end.
  4. 2 points
    Henry

    My SMS Project: Paintball Net Revival

    I was eleven years old and had just mailed off a crinkly ten dollar bill folded inside a handwritten message explaining my love for this game. A few days would pass until there it was, my first level up. Huge fan, no game has ever come close to the caliber of paintball net. I’m — we — are much older now but the game hasn’t aged a day. Thank you David for resurrecting the legend !
  5. 2 points
    lynkfs

    php

    A web application ends up being encoded in html, js and css. php is a language which can be used to create these components, but more importantly can also be used within all 3 of these types of files. That gives some interesting possibilities. To make that happen, php needs to be activated serverside. Many server hosting environments come with php pre-installed. Activating php so that it can be used at the time of serving regular .html, .js or .css files by the browser depends on the type of server. Regular unix based servers make use of a .htaccess file which needs a line like AddHandler application/x-httpd-php5 .html .htm Windows servers have another mechanism 1 - Using php within Smart Php can be invoked like this, where the php statements are inclosed in a <?php block. asm var i = 0; i = <?php echo 35; ?>; alert(i); end; A practical use would be to include server side scripts normally accessed through a POST request (which eliminates a server round trip as well). The below code reads a MySqL database at form init procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components var response : variant := new JObject; asm @response = <?php $link = mysql_pconnect("...domain...", "...user...", "...password...") or die("Could not connect"); mysql_select_db("...database...") or die("Could not select database"); $sql_statement = 'Select * from FishFacts'; $arr = array(); $rs = mysql_query($sql_statement); while($obj = mysql_fetch_object($rs)) { $arr[] = $obj; } echo '{"rows":'.json_encode($arr).'}'; mysql_close($link); ?>; end; writeln(response.rows[0].Common_Name); //Clown Triggerfish 2 - Using php within Html files A (possibly) usefull example scenario would be to separate web-pages into a header.html, a regular Smart index.html and a footer file. php has an include mechanism, which can be used like so <body> <?php include "header.html" ?> <script type="text/javascript"> /* This prevents the window being moved by touches, to give the impression of a native app */ document.ontouchmove = function(e) { e.preventDefault(); } </script> <script type="text/javascript" src="main.js.php"></script> </body> 3 - Using php within css files Similarly stylesheets can be scripted, something like this snippet where, within the stylesheet, the current date is checked which sets an image url <?php $month = date('m'); $day = date('d'); if($month=='12' && $day=='25') { $logoSrc = 'images/holidayLogo.png'; } else { $logoSrc = 'images/logo.png'; } ?> h1 { background: url(<?=$logoSrc?>) no-repeat; } Demo (of 1 and 2)
  6. 2 points
    warleyalex

    window component

    OFF TOPIC - "SMS Component design" Just things that crosses my mind, and I want to discuss. Please don’t see that as an attack to someones's work. I really like SMS and the new possibilities. We all want the best possible development experience result. While the visual widgets/UI in SMS still is customizable (by user and developer). I often spend more time on UI parts to realize the look and feel i want to have. I have to say here, one think that is very frustating for me is the SMS form designer I've spent a few minutes reflecting on this RAD approach and its form designer to create web app. Just drop components onto a form and set up at the objector inspector, the events and the properties. All of the above is great and it will no doubt give us the same benefits as Delphi developers currently enjoy. The compiler will auto generate the components for you, such as: var btn1: TButton; btn1 := TButton.Create(Self); btn1.Width := 121; btn1.Top := 16; btn1.Left := 536; btn1.Height := 25; btn1.Name := 'btn1'; btn1.OnClick := Self.btn1Click; The UI part could be implemented on top of TCustomComponent, both visual or non-visual components could be used. "the window component" - it's great candidate hein! ...but what I really don't like this approach is when i.e. you drop "a visual component" onto form, you see "rectangule" drawing which represents the component itself you dropped. I can't seem to find anyway how to get the "live preview" on the SMS designer on those components I've created. other thing is the "objector inspector" support for some custom properties. For instance, if the user choose 'Material' from the list, the Material CSS style should be applied to the component. type TCustomStyle = array[1..3] of string; const CustomStyle : TCustomStyle = ('iOS','Android','Material'); type TMystyle = (cssIOS, cssAndroid, cssMaterial); TToggleComponent = class(TW3CustomControl) private fMyStyle: TMystyle; fCustomStyle : TCustomStyle; published property Mystyle: TMystyle Read fMyStyle Write fMyStyle default cssAndroid; property CustomStyle: TCustomStyle Read fCustomStyle Write fCustomStyle; ...when I see at Object Inspector the property MyStyle : 0 (set to zero?). For the boolean type it shows the dropdown list. How can I create a property of type String that will show a combo box in the object inspector with a predefined set of values the user could choose? This is very frustating for me It seems there's just a bit too much work involved to meet even baseline expectations.
  7. 2 points
    lynkfs

    css grid

    The CSS Grid is pretty fast. However the current major browsers have a hard-coded limit of 1000 rows (Chromium) or 10,000 rows (Firefox). See reference issue here Edited project here (better stylesheet handling)
  8. 1 point
    jarto

    Radiogroup - change items text

    With the current designer, having the items as a TStrArray is the only way we can define items at design time.
  9. 1 point
    IElite

    Radiogroup - change items text

    W3RadioGroup1.RadioButtons[0].Label.Caption:= 'it does not work';
  10. 1 point
    lynkfs

    css grid

    Started to do some experiments with CSS Grid Basically CSS Grid is a grid component built into all modern browsers, including mobile. The good thing about it is it can be used as a simple grid, as a layout mechanism for forms or other components and can be used to be responsive to screen sizes. 1) A simple grid. Since this is based on css, it can only be teased into life by manipulating the stylesheet. Either by just adding css to it manually or doing it in code : //add some styles in code var s1 := #' .TGrid { display: grid; grid-template-columns: repeat(3, auto); grid-gap: 0.8em; }'; document.styleSheets[document.styleSheets.length-1].insertRule(s1, 0); // s1 := #' .afirst { grid-column: 1; }'; document.styleSheets[document.styleSheets.length-1].insertRule(s1, 0); This snippet adds a grid class to the stylesheet and a class for the first column in this grid Fill up the grid, in plain html here, by adding cells as children : var s := '<div class="TGrid" id="mygrid">'; for var i := 0 to 100 do begin s := s + '<div class="afirst">row ' + inttostr(i+1) + '</div>''; end; s := s + '</div>'; This can be made into a regular component : var MyCSSGrid : TCSSGrid := TCSSGrid.Create(self); MyCSSGrid.SetBounds(50,50,500,200); MyCSSGrid.NrofColumns := 4; For var i := 1 to 1000-1 do begin MyCSSGrid.AddCell('row ' + inttostr(i), 1); //column 1 For var j := 2 to 4 do begin MyCSSGrid.AddCell('cell[' + inttostr(i) + ',' + inttostr(j) + ']', j); //column 2-4 end; end; MyCSSGrid.Show; A demo of such a component with 4 columns and 1000 rows
  11. 1 point
    lynkfs

    css grid

    2) using css grid to make a responsive 'form' The below component does some simple layouting of controls and also reacts to screen-sizing, both using the css grid : procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components var ResponsiveForm : TResponsiveForm := TResponsiveForm.Create(self); ResponsiveForm.SetBounds(40,40,500,220); ResponsiveForm.AutoHeight := true; ResponsiveForm.Add('Name',TW3EditBox); ResponsiveForm.Add('Email',TW3EditBox); ResponsiveForm.Add('Township',TW3EditBox); ResponsiveForm.Add('Comments',TW3Memo); ResponsiveForm.Add('Submit',TW3Button,2); end; Demo here It is not really 100% responsive, as the labels should shift above the controls when screen size becomes small. It doesn't however look too bad and the tediousness of aligning labels and controls is taken care of by the css grid. (Adapted from this article). It's probably as easy though to use anchors creating the same result
  12. 1 point
    jarto

    window component

    Cool, you found the new events like OnAllMovement. That makes the code a lot easier. The jitteryness may come from MoveTo. Forgot one thing: You need to call Ctrl.SetCapture when MouseDown happens and Ctrl.ReleaseCapture during MouseUp.
  13. 1 point
    jarto

    window component

    @warleyalex Yeah, well, the problem you experience is because the current Object Inspector lacks features. We're in the process of replacing it with a better component, which should let you edit more properties. For example sets. The Object Inspector also needs a lot of work. The current design was based on the idea that we'd get the Chromium to render us a live preview that we could use to make the controls look realistic. However, there was some changes in Chromium that broke that feature. So we're currently thinking about what'd be the best way to proceed. Basically: Should we try to improve the current one or replace it with something better.
  14. 1 point
    jarto

    window component

    Something like this: var saveX, saveY: Integer; Header.OnMouseDown:=procedure(Sender: TObject; Button: TMouseButton; shiftState: TShiftState; x, y: integer) begin var Ctrl:=TW3CustomControl(Sender); Ctrl.Cursor:=crMove; saveX:=x; saveY:=y; end; Header.OnMouseMove:=procedure(Sender: TObject; ShiftState: TShiftState; x, y: integer) begin var Ctrl:=TW3CustomControl(Sender); if Ctrl.Cursor=crMove then begin Ctrl.MoveTo(Ctrl.Left-(saveX-x),Ctrl.Top-(saveY-y)); PrevSize:=Ctrl.BoundsRect; saveX:=x; saveY:=y; end; end; Header.OnMouseUp:=procedure(Sender: TObject; Button: TMouseButton; shiftState: TShiftState; x, y: integer) begin var Ctrl:=TW3CustomControl(Sender); Ctrl.Cursor:=crDefault; end;
  15. 1 point
    lynkfs

    window component

    demo works ok here The javascriptisch events used are //Move window Header.handle.onmousedown := procedure(e: variant) begin Header.handle.style.cursor := 'move'; var saveX := e.clientX; var saveY := e.clientY; Header.handle.onmousemove := procedure(e: variant) begin self.left := self.Left - (saveX - e.clientX); self.top := self.top - (saveY - e.clientY); PrevSize := TRect.CreateSized(left, top, width, height); saveX := e.clientX; saveY := e.clientY; end; end; // Header.handle.onmouseup := procedure(e: variant) begin Header.handle.onmousemove := null; //nullify mousemove Header.handle.style.cursor := 'default'; end; // Header.handle.onmouseleave := procedure(e: variant) begin self.Parent.handle.onmousemove := header.handle.onmousemove; self.Parent.handle.onmouseup := procedure(e: variant) begin self.parent.Handle.onmousemove := null; end; end; will be interesting to compare using eventmanager. I agree that will probably be a better solution
  16. 1 point
    jarto

    window component

    @lynkfs SetCapture/ReleaseCapture takes care of those dragging problems that @Czar mentioned. Edit: However, to be able to use SetCapture and ReleaseCapture, you need to listen to MouseDown, MouseUp and MouseMove using the normal Delphi-like events instead of using the raw JS events. Edit2: When you use normal events, the EventManager takes care of a boatload of the complexity. For example, SetCapture locks on to the control meaning that all move events go that one. (See the Scrollbars code in the RTL as an example) The EventManager also notices situations where you click on control to drag it, move the mouse outside of the whole browser window and release the button there. If you try to listen to events through JS, these kinds of special situations are a pain to handle correctly.
  17. 1 point
    jarto

    RoadMap 2019

    @IElite What you're asking for depends a lot on the design of your app and the server api. If you write both, then you yourself get to design how the server and the mobile app talk to each other. A1. Your app makes a https get to your server to retrieve the latest JSON data. To see an example, have a look at how the StringGrid demo reads a local file. The difference between reading data from local or a remote address depends only on the url used. To make this very smooth, you can do this: App starts Make the https get to the remote server Make a call with TW3Dispatch with a 2 second delay to read the local json When you start receiving data from the remote server, cancel the local read (set a boolean or something) Which ever get-command received data, update the GUI based on the data A2. Requesting a value from the server is a simple GET to your server software. You decide what the parameters are that the server needs to identify what data you're requesting. Modifying is a POST command. Again, you decide the parameters. Make sure to verify the parameters so that you're not creating a security hole. B. I'd do this so that your server app is the only one that talks to the database. You just create a simple API for the discussion between your mobile app and the server. So in the end it's basically just your mobile app doing get- and post-calls.
  18. 1 point
    Czar

    reCaptcha

    I am trying to implement a "i am not a robot" into my website Basic HTML/JS looks like the following with a second step required to validate it server side. <script src="https://www.google.com/recaptcha/api.js"></script> HTML: <div class="g-recaptcha" data-sitekey="YOUR_KEY" data-callback="correctCaptcha"></div> JS: var correctCaptcha = function(response) { alert(response); }; I thought I could manage getting it to wok in SMS but I got very lost. I couldn't find examples that seemed to be a parallel challenge. It would be great to have some clear tutorial or case study to show how it is possible to integrate JS and or it would be good to a have google recaptcha component info link: https://stackoverflow.com/questions/27902539/how-can-i-validate-google-recaptcha-v2-using-javascript-jquery https://developers.google.com/recaptcha/intro
  19. 1 point
    lynkfs

    reCaptcha

    Its actually simpler than I thought - the Google documentation is esoteric at best the reCaptcha widget produces some sort of response when the user clicks the checkbox (g-rechapta-response). This response is POST-sent (either by form or by xmlhttprequest) to a back-end server side script. this script queries the "https://www.google.com/recaptcha/api/siteverify" url, which gives a response either ok or not ok This server-side script can be f.i. node.js or php based In php something like this (recaptchajax.php) <?php $secret="6Lf8I....secret key.....BrulLk"; $response=$_POST["captcha"]; $verify=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$response}"); $captcha_success=json_decode($verify); if ($captcha_success->success==false) { //This user was not verified by recaptcha. echo 'false'; } else if ($captcha_success->success==true) { //This user is verified by recaptcha echo 'true'; } ?> and the invocation, with a proper POST xmlhttprequest : unit Form1; interface uses System.Types, System.Types.Convert, System.Objects, System.Time, System.IOUtils, System.Device.Storage, SmartCL.System, SmartCL.Time, SmartCL.Graphics, SmartCL.Components, SmartCL.FileUtils, SmartCL.Device.Storage, SmartCL.Forms, SmartCL.Fonts, SmartCL.Theme, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.Panel, SmartCL.Net.Http, ECMA.Json, SmartCL.Controls.Button; type TForm1 = class(TW3Form) private {$I 'Form1:intf'} protected procedure InitializeForm; override; procedure InitializeObject; override; procedure Resize; override; procedure RetrieveCaptcha(Sender: TW3HttpRequest); Button1 : TW3Button; end; var grecaptcha external 'grecaptcha': Variant; implementation { TForm1 } procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components Var Captcha : TW3Panel := TW3Panel.Create(self); Captcha.SetBounds(50, 100, 304+4, 78+4); Button1 := TW3Button.Create(self); Button1.SetBounds(50, 200, 100, 30); Button1.Caption := 'submit'; var Script := browserapi.document.createElement('script'); Script.src := 'https://www.google.com/recaptcha/api.js'; browserapi.document.head.appendChild(Script); Script.onload := procedure begin Captcha.innerHTML := '<div class="g-recaptcha" data-sitekey="6Lf8I6....site key.....WY5hq"></div>'; Button1.onclick := procedure(sender:TObject) begin var FHttp := TW3HttpRequest.Create; FHttp.OnDataReady := RetrieveCaptcha; FHttp.open("POST","https://www.lynkfs.com/Experiments/reCaptcha/www/lib/recaptchajax.php"); FHttp.RequestHeaders.Add("Content-type","application/x-www-form-urlencoded"); var mycaptcha := "captcha=" +grecaptcha.getResponse(); FHttp.send(mycaptcha); end; end; end; procedure TForm1.RetrieveCaptcha(Sender: TW3HttpRequest); begin writeln(JSON.parse(Sender.ResponseText)); //console : either 'true' or 'false' If JSON.parse(Sender.ResponseText) = true then Button1.Caption := 'OK'; If JSON.parse(Sender.ResponseText) = false then Button1.Caption := 'Spam'; end; procedure TForm1.InitializeObject; begin inherited; {$I 'Form1:impl'} end; procedure TForm1.Resize; begin inherited; end; initialization Forms.RegisterForm({$I %FILE%}, TForm1); end. Demo url as before
  20. 1 point
    IgorSavkic

    reCaptcha

    What I did (for a reset pass form) was to include gogle recapcha js to html, it auto displays/shows a small recaptcha logo on lower right and shows challenge only when my SMS ResetPass button is pressed: var grecaptcha external 'grecaptcha': Variant; grecaptcha.execute(GoogleRecaptchaKey, InitObject(['action', 'pwdreset'])).then( lambda (token: Variant) // We received result from Google recaptcha, pass it along with other entered values to the server // Server will perform final validation of received token (is it valid value or not). WriteLn(Token); glbApp.ResetPass(Trim(edtUserName.value), Trim(edtCust.value), lambda (AClient, AStatus) ShowMessage('If entered details match registered user, password reset details will be sent to your eMail address.'); end ); end );
  21. 1 point
    lynkfs

    reCaptcha

    this is a finnicky api, which needs multiple steps to figure this out. Step1 : display the captcha widget It is not just the case of adding the 'https://www.google.com/recaptcha/api.js' file to the index/template file, as it clashes with a standard smart project. Don't know why, something to do with timing So workaround #1 : read the api file in code (maximum control) and set up a TPanel as the widget control procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components Var Captcha : TW3Panel := TW3Panel.Create(self); Captcha.SetBounds(50, 100, 304+4, 78+4); var Script := browserapi.document.createElement('script'); Script.src := 'https://www.google.com/recaptcha/api.js'; browserapi.document.head.appendChild(Script); Script.onload := procedure begin writeln('loaded'); Captcha.innerHTML := #' <form action="?" method="POST"> <div class="g-recaptcha" data-sitekey="6Lf8I...site key ...WY5hq" data-callback="mycallback"></div> <br/> <input type="submit" value="Submit"> </form> '; end; end; The captcha widget is 304 * 78, so we'll embed it in a standard T(W3)Panel. The innerHtml solution is not very elegant (but works). I'll see if this can be changed to a normal post xmlhttprequest later. Demo so far
  22. 1 point
    lynkfs

    Responsive Design

    css here, project here Nothing fancy, just used the css and html of the example as-is. Could be simplified The CSS grid is implemented in these lines in the stylesheet : display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); grid-gap: 1rem; "give me as many columns as fit on the available width where each column is at least 320px wide, or maximum 1 fraction" The CSS grid is pretty powerful and is available in all modern browsers, including mobile. Time permitting, I'll dig into it a bit deeper.
  23. 1 point
    As far as I understand Node, for a simple http server the action is in the handlerequest proc. This procedure has a request and a response object, and the latter can be used to send data back to the client. Request.Handle.on('end', procedure(data: variant) begin Response.&End('Headers: '+request.Headers.ToString()+#13#10+ 'Content: '+Variant('this is the response from my server')); //<============= //These are not automatically freed after HandleRequest as that would //prevent reading of content data using async functions. Request.Free; Response.Free; end); This should be able to be picked up in the responseText of the calling httprequest (There are some examples on the forum doing something similar using sockets, but your approach should work too)
  24. 1 point
    Czar

    UI layout

    Loving the update. Only had a little play but it seems to be working as expected
  25. 1 point
    warleyalex

    async / await keywords

    look this following procedure: procedure main; begin Sleep(5000); console.log('A'); Sleep(3000); console.log('B'); end; when we run this code, it will immediately output 'A' and 'B' - JS the asyncronous nature. ...but I want our program to log 'A' after 5 seconds then log 'B' after 3 seconds... that why we, we need the async / await native keywords in SMS. In a "synchronous" manner. Await and Async are just syntactic sugar for working with promises. It would be cool if we can declare a method like: procedure main; async; The compiler can check whether the encompassing function has async() in then and emit expectd JS, for instance: (async function(){ })(); Yeah, we need to to wrap it inside an async function and add "await" before the method "Sleep" to work in synchrounous manner.ther await keyword native in SMS would be nice. await Sleep(5000); I found out an ugly workaround for the "Immediately Invoked Function Expression (IIFE) - async function" to work at SMS. { global functions } procedure async(fn: Variant = nil); external '(async function(){' ; procedure &end; external '})'; function await(promise: Variant): JPromise; external 'await '; function Sleep(ms: Integer): JPromise; begin Result := JPromise.Create( procedure(resolve,reject : TCallBack) begin window.setTimeout( procedure() begin console.log('Done waiting'); resolve(ms); end, ms); end); procedure main; begin async; await( Sleep(5000) ); console.log('A after 5s'); await (Sleep(3000)); console.log('B after 3s'); &end; end; end; the compiler will emit expected JS at least: function main() { (async function(){(null); await (Sleep$1(5000)); console.log("A after 5s"); await (Sleep$1(3000)); console.log("B after 3s"); })(); }; but it would super awesome if we could // define procedure as async function procedure main: async; procedure main; begin await Sleep(5000); console.log('A after 5s'); await Sleep(3000); console.log('B after 3s'); end;
×