Jump to content


Popular Content

Showing content with the highest reputation since 01/23/2019 in Posts

  1. 3 points
    to match/map the JSON fieldname, you have to declare the record definition is type TFishRecord = record Category: String; external 'Category'; Common_Name: String; external 'Common_Name'; Length_Cm: String; external 'Length_Cm'; Length_In: String; external 'Length_In'; Notes: String; external 'Notes'; Species_Name: String; external 'Species_Name'; Species_No: String; external 'Species_No'; end; to emit this JS Object, for instance: { Category : "Snapper", Common_Name : "Red Emperor", Length_Cm : "60", Length_In : "23.6220472440945", Notes : "Called seaperch in Australia.", Species_Name : "Lutjanus sebae", Species_No : "90030" }
  2. 3 points

    SMS 3 + mORMot = Error

    I download the mORMot_and_Open_Source_friends_234301_06b24ae728 today and patched some needed SynCrossPlatform units and mORMotWrappers (generate mORMot cross-platform clients code from the server). and some changes at the project 27 and 29, Now, it compiles and works in both SMS (lastest WinXP compatible) and SMS (development version)! download link: mORMot with SMS 2x and 3x
  3. 2 points
    Hi Tim, I assume you are trying to log in with your email address. Try using your screen name instead, ie "Tim Koscielski" without the quotes. It's a known issue
  4. 1 point

    My SMS Project: Paintball Net Revival

    I played all the clones through the years infrequently and paintball-net will always be my favorite. Hvpb took it in a interesting route but the no class system is the best route imo. Excited to get back to splatting and maybe play some tournaments down the road! Thanks for bringing it back online and glad you had fun compiling it DavidRM! formerly KevDog. Currently Beezooka
  5. 1 point
    Back in the mid-90's, my brother created what he called an "action MUD". He called it "Paintball Net". PBN used ANSI text terminal commands to create a combined roll-and-scroll and animated text experience. ! (exclamation points) were trees, _ (underscores) were grass, ^ (up carets) were mountains, and more. Your "avatar" was a "Y" (uppercase y) and enemies were * (asterisks). You used MUD-like commands to move around the world and target your paintball gun and buy and sell and more. I wish I had a screenshot of what the first version looked like, but you'll just have to imagine. šŸ˜ƒ He asked me to create the GUI for the game. That was 1996, and I had just purchased Delphi 2 and wrapped up my first "learn Delphi" project. This sounded like a good next step, and "PBTerm" was born. I *do* have screenshots of that. Oh, yeah. Love those 16-color Windows graphics. šŸ˜ƒ During the years it was online, the game evolved and upgraded to look more like this: We were never going to win any awards, but we had a very devoted player community. šŸ˜ƒ Paintball Net was online from the summer of 1996 through the summer of 2000, when we took it offline to focus on other projects. The game was never huge, but we had thousands of players come through over that period. And since then, every year at least a few of the players have reached out and asked/begged/pleaded/demanded if we were going to put it back online. There really wasn't much chance of the original version going back online. The original server, written in ANSI C for Linux had proven rather fragile, and was a big part of why we took the game offline. It was taking hours every day just to keep it up and running, in addition to time spent managing the community of players. On top of that, a hard drive incident in 2008 had cost me the source code of a number of core third-party/modified components for PBTerm. This past summer, though, I realized I might be able to make the game live again using Smart Mobile Studio. I would do a straight port of the ANSI C server to Smart Pascal using Node.JS and WebSocket, and I would rebuild the PBTerm client as a browser-based client. I'm not going to say it was *easy*, but it has been a lot of fun. ANSI C converts to Pascal without a lot of painful gyrations. And Node.JS seems a LOT more flexible, stable, and powerful than the TCP sockets approach we were using before. Also, game development is a lot easier when you already own all the graphic and audio resources. šŸ˜ƒ This is the server "in action"... Recreating the client has been more complicated. 20+ years of Delphi habits had to be adapted to the new reality of SMS and a browser-based UI. But that's coming together too. It might be obvious, but I'm not targeting this game at mobile. Paintball Net needed a mouse and keyboard in 1996, it's gonna need a mouse and keyboard in 2018. Also, I've made as few modifications to the gameplay as possible. I really wanted to bring back the original as much as I could. Today I got the handful of sound effects integrated, which was easier than I expected. I'm planning to start testing soon. I just need to line up a server to use and find a few volunteers. I'm excited. This would never have happened without Smart Mobile Studio. So I figured I would share. Merry Xmas! -David
  6. 1 point

    Mixing Javascript and SMS

    Example 2 : see below (first post in that thread) for some function call examples Example 1 : depends on what attribute. In your example you want to manipulate the visibility property of a button. These types of properties usually are mapped on a property or attribute of the underlying DOM-element. In this case you could use the style element visibility : W3Button1.handle.style.visibility := 'hidden' / 'visible'. 'handle' is the doorway between object pascal on the left hand side and the dom on the right hand side. No need for an asm block here. you can go the other way too : var x : variant := W3Button1.handle; asm console.log((@x).style.visibility); end; but you can't directly manipulate the properties of an object pascal object, as in asm @W3Button1.Visible = true Of course you can do some conditional js coding and execute object pascal code (like W3Button1.Visible := true;) depending on the return outcomes. Out of habit I suppose I try to minimise the use of asm blocks (although there is nothing wrong with using them). The only times I have to use them if a js object doesn't have a create constructor but instead can only be instantiated by the 'new' keyword var formData : variant; asm @formData = new FormData(); end; //from here all methods and attributes of the js object are accessible outside an asm block formData.append("userfile", EditBox1.handle.files[0]); or wrapping a js function. (you can set @result in an asm block)
  7. 1 point
    Ok, this first follow up is what I did to get it working based on some of the links for handling forms in javascript. Fortunately because I could mix and match SMS Pascal and Javascript, I get the best of both worlds. On my Smart Form, I have a TW3Button and a TW3EditBox with a type of ltFile. Then with the following javascript, I can get the form posted correctly to a backend which is able to capture the file and other variables of the form. Note that the other elements are created dynamically based on an example I was using. The ShowMessage and Alert items were just feedback mechanisms for me to see this part working. Both my DMVC server and a PHP script were able to process this. I am sure that there is a more friendly SMS way of writing this, but for now it got my form working and I was able to continue to plow forward with this upload piece being reasonably well contained. My key take way was getting the file upload field and the code below did the trick. This may not be the best way, but at least it was a starting point. myFile = document.getElementById('id', 'fupload1'); The InitializeObject was important to label the TW3EditBox element correctly. Below that is the code that I stuck in the OnClick event for the button. I saw many other ways to deal with this, but I just wanted to keep it straight forward for the UI. procedure TForm_ImportFile.InitializeObject; begin inherited; {$I 'Form_ImportFile:impl'} W3ButtonBack.InnerHTML := '<i class="fa fa-arrow-left fa-2x"></i>'; // this is a good place to initialize components W3EditBox1.handle.setAttribute('name','fupload'); W3EditBox1.handle.setAttribute('id', 'fupload1'); // Initialize EditBox id to find it with getElementById below W3EditBox1.InputType := itFile; end; // BUTTON CLICK EVENT CODE ShowMessage('Starting'); asm var formData = new FormData(); alert('Trying to get file box'); myFile = document.getElementById("fupload1").files[0]; alert('Got file: ' + myFile.name); formData.append("username", "Groucho"); formData.append("accountnum", 123456); // number 123456 is immediately converted to a string "123456" // HTML file input, chosen by user //formData.append("fupload", fileInputElement.files[0]); //var myFile = new Blob([content], {type: "text/plain"}); formData.append("userfile", myFile, myFile.name); // JavaScript file-like object var content = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file... var blob = new Blob([content], { type: "text/xml"}); formData.append("webmasterfile", blob); var request = new XMLHttpRequest(); request.open("POST", ""); request.send(formData); end; ShowMessage('Done');
  8. 1 point
    Daniel Eiszele

    RTL Class Browser stays empty

    I added the commandline arguements into a batch file which works for me!
  9. 1 point

    RTL Class Browser stays empty

    Finally it works. Must have to do something with the ShortCut. Starting SmartUpdate via commandline is OK.
  10. 1 point
    Attached is a simple project with a Cw.Client.Core unit i a subdirectory Client. I've made an error in the Cw.Client.Core and when I try to compile i reports that the Cw.Client.Core not found. Also Ctrl-Click is not working and File/Open... will open the untiu but not shift to the tab sheet. Sindre SearchPathTest.zip
  11. 1 point
    Post rewritten. If using the html <form> element, as below, works for a DMVC server, then it will work for other servers like php, node as well. <form action="/file" method="post" enctype="multipart/form-data"> <input type="file" name="fupload"> <input type="submit"> </form> So the best bet would be to follow this same mechanism in Smart. The questions are then A: since there is no component in Smart which encapsulates the <form> element, how can we get one, or B: would it be possible to circumvent this <form> element completely Ad B (the difficult one first) This involves looking at what exactly happens when a <form> is used for file uploads, and reproduce that process in object pascal. Personally I am not in favour of this approach as it duplicates functionality which is freely available in the browser. However, it can be done. The <form> submit process for uploading files goes something like select a file to upload (type = itFile) read this file using the File api chop the content up in chunks surround each chunk with a unique border (something like "-----------------------------244962545219104") send these chunks using the xmlhttp post protocol using some specific headers There is an example here using this approach (with a simple php server as backend). A modified working version is available here, which gives as output (FF Params tab) something similar to -----------------------------168b2ce8400 Content-Disposition: form-data; name="myfile"; filename="bar.txt" Content-Type: text/plain test file -----------------------------168b2ce8400-- If this looks promising, the next step would be to translate the js framework into object pascal. Ad A It should be feasible to create a new component which encapsulates a <form> element. Stub like TW3FormElement = Class(TW3CustomControl) protected function MakeElementTagId: string; override; Procedure ObjectReady;Override; procedure InitializeObject;override; End; implementation function TW3FormElement.MakeElementTagId: String; Begin result:='FORM'; end; Note There is another thread which might be of use as well :
  12. 1 point
    I think you should use the record type to store/retrieve the JSON data. type TFishRecord = record Category: String; Common_Name: String; Length_Cm: String; Length_In: String; Notes: String; Species_Name: String; Species_No: String; end; type TForm1 = class(TW3Form) private {$I 'Form1:intf'} fishRecord: TFishRecord; protected procedure InitializeForm; override; procedure InitializeObject; override; procedure Resize; override; end; implementation var fishJsonData = #'[ {"Species_No":"90020","Category":"Triggerfishy","Common_Name":"Clown Triggerfish","Species_Name":"Ballistoides conspicillum","Length_Cm":"50","Length_In":"19.6850393700787","Notes":"Also known as the big spotted triggerfish. Inhabits outer reef areas and feeds upon crustaceans and mollusks by crushing them with powerful teeth. They are voracious eaters, and divers report seeing the clown triggerfish devour beds of pearl oysters.\r\n\r\nDo not eat this fish. According to an 1878 account, \"the poisonous flesh acts primarily upon the nervous tissue of the stomach, occasioning violent spasms of that organ, and shortly afterwards all the muscles of the body. The frame becomes rocked with spasms, the tongue thickened, the eye fixed, the breathing laborious, and the patient expires in a paroxysm of extreme suffering.\"\r\n\r\nNot edible.\r\n\r\nRange is Indo-Pacific and East Africa to Somoa."}, {"Species_No":"90030","Category":"Snapper","Common_Name":"Red Emperor","Species_Name":"Lutjanus sebae","Length_Cm":"60","Length_In":"23.6220472440945","Notes":"Called seaperch in Australia. Inhabits the areas around lagoon coral reefs and sandy bottoms.\r\n\r\nThe red emperor is a valuable food fish and considered a great sporting fish that fights with fury when hooked. The flesh of an old fish is just as tender to eat as that of the very young.\r\n\r\nRange is from the Indo-Pacific to East Africa."}, {"Species_No":"90050","Category":"Wrasse","Common_Name":"Giant Maori Wrasse","Species_Name":"Cheilinus undulatus","Length_Cm":"229","Length_In":"90.15748031496059","Notes":"This is the largest of all the wrasse. It is found in dense reef areas, feeding on a wide variety of mollusks, fishes, sea urchins, crustaceans, and other invertebrates. In spite of its immense size, divers find it a very wary fish.\r\n\r\nEdibility is considered poor.\r\n\r\nRange is the Indo-Pacific and the Red Sea."} ]'; function getList: variant; begin result := JSON.parse(fishJsonData); end; function JSON2TFishRecord(const Value: variant): TFishRecord; begin result.Category := Value.Category; result.Common_Name := Value.Common_Name; result.Length_Cm := Value.Length_Cm; result.Length_In := Value.Length_In; result.Notes := Value.Notes; result.Species_Name := Value.Species_Name; result.Species_No := Value.Species_No; end; function TFishRecord2JSON(const Value: TFishRecord): variant; begin result := new JObject; result.Category := Value.Category; result.Common_Name := Value.Common_Name; result.Length_Cm := Value.Length_Cm; result.Length_In := Value.Length_In; result.Notes := Value.Notes; result.Species_Name := Value.Species_Name; result.Species_No := Value.Species_No; end; ( TWEdit widget ) categoryEd.Text := fishRecord.Category;
  13. 1 point
    I had a look at the DelphiMVCFramework files-upload demo. The upload page, see below, lets the user select a file and submits a form with the selected file to the server. <html> <body> <h2>DMVCFramework - FileUpload DEMO</h2> <form action="/file" method="post" enctype="multipart/form-data"> <input type="file" name="fupload"> <input type="submit"> </form> </body> </html> To emulate this in Smart, the <input type="file ... line will be taken care of by an edit box with type =itFile. You will have to set the name attribute as well : procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components var EditBox1 : TW3EditBox := TW3EditBox.Create(self); EditBox1.SetBounds(50,50,400,30); EditBox1.InputType := itFile; EditBox1.handle.setAttribute('name','fupload'); The tricky part is to emulate the <form> element. While it is doable to make a new component based on the <form> element, it is probably easier to use a FormData object. FormData objects can capture the data entered in forms and these objects can then just be sent server-side using normal xmlhttprequests. See here. You can link this ajax call to a button, or alternatively to the onchange event of the editbox : EditBox1.OnChanged := procedure(sender:TObject) begin var formData : variant := new JObject; asm @formData = new FormData(); end; formData.append("userfile", EditBox1.handle.files[0]); var FHttp : TW3HttpRequest := TW3HttpRequest.Create; FHttp.OnDataReady := nil; //or a callback procedure FHttp.open("POST","/file"); FHttp.RequestHeaders.Add("Content-type","multipart/form-data"); FHttp.send(formData); end; end; I have not used the DelphiMVCFramework before and don't have it installed, so the above may not work. But this is how I would attack this.
  14. 1 point
    Yes. they removed the VarIsValidRef method. hum, at the System.types unit, there's a helper class TW3VariantHelper where lives a method Valid. if TW3VariantHelper.Valid(str) then ; I would prefer a global big unit with all methods instead of helper class approach.
  15. 1 point

    Declaring Record Type Constants

    solution I: =========== var // _TableList: array[0..0] of variant = [ _TableList:= [ CLASS TableName:= 'Server'; external 'TableName'; CreateFunc:= @CreateServer; external 'CreateFunc' END ]; // This works ========================================================== var _TableList2: array[0..0] of TMySqlCreateTable = [ ( TableName: 'Server'; CreateFunc: @CreateServer ) ]; // Syntax Error: Constant expression expected [line: 85, column: 52, file: unit2] ========================================================== _TableList2[0].TableName := 'Server'; _TableList2[0].CreateFunc := @CreateServer; // This works
  16. 1 point

    Endpoints & Resources ?

    As you see above, the http server demo also does that. It builds the post data in the content-string. When all the data is read, the end-event is triggered. At that point you know that you have all the post data. The code can easily be changed to build the content as a stream.
  17. 1 point

    Endpoints & Resources ?

    OH OK, Thanks for your help!
  18. 1 point

    Endpoints & Resources ?

    Well, you should always take what Jon says or writes with a grain of salt.
  19. 1 point


    update 2 : after some more testing on different platforms, the conclusion is that the window.print() method basically works on all platforms (Windows, MacOs, iOS, Android) and modern browsers (Chrome, FireFox, Safari), but only using the iFrame setup as mentioned in the prev. posts. The other methods may or may not work. The main exception is Chrome and FireFox on iOS where window.print() doesn't work at all : apparently Apple does not allow printing from Chrome in iOS due to it's policy on using alternative browser engines. These guys deserve a thumbs down, really
  20. 1 point

    Development updates

    New update available: RTL: New controls: TW3SpinButton, TW3ArrowUpButton, TW3ArrowDownButton, TW3ArrowLeftButton and TW3ArrowRightButton. Add 1px margin to TW3ButtonBorder to prevent the border from being clipped. Bug fixes to Tween.Effects IDE: Bug fixes and changes to renaming of forms: Renaming in Project Manager will not change form class any more. Form class name can be renamed in Object Inspector. Improvements to Project Statistics: Only count Total time when Smart Mobile Studio IDE has focus. Only Count Design time when changes are made in Form Designer. Add clear button. Component Palette: Added new controls New icons for many existing controls
  21. 1 point

    RoadMap 2019

    We'll be able to improve documentation in about 2 months. I do agree that it's currently the area where we need to improve. While waiting for that, I'm doing my best to help users here in the Forum.
  22. 1 point
    whew, that's a mouth full "getting the row # of a button in a cell of a TW3ButtonColumn in Tw3Grid ?" So, I have a TW3Grid, and a TW3ButtonColumn. When the button in the column is clicked, I need to know the row # that button resides in. see attached screenshot
  23. 1 point
    Update......couple changes changed TagId to TagValue (work with integers instead of strings) when prepping the row procedure TSelGrid.Add(AGrade, AClasses, AStudents, AProgram: String); begin fGrid.AddRow; (fGrid.Row[fGrid.LastAddedRow] as TW3CustomControl).TagValue := fGrid.LastAddedRow; '''''' end; Next, in order to get the row index from the TagValue property, I just did a cascading look into all the parents Button --> Cell -- > Row procedure TSelGrid.HandleDeleteClick(sender: TObject); var RowId: integer; begin RowId:= Tw3Row(TW3Cell(TW3Button(sender).Parent).Parent).TagValue; fGrid.DeleteRow(RowId); end; I would still be interested in knowing if there is an easier solution to get the row. Maybe add the property to the grids TW3Cell? TW3Column
  24. 1 point
    I jumped the gun @lynkfs .....that does not help me solve the original issue of how to determine the row from the button clicked in the button column. With your code, I was able to flag the row with the id, but I still dont have access to it from the button. I assume once I can figure that out, I can figure our the row number anyways, with out the need to store anything in TagId procedure TSelGrid.Add(AGrade, AClasses, AStudents, AProgram: String); begin fGrid.AddRow; (fGrid.Row[fGrid.LastAddedRow] as TW3CustomControl).TagId := inttostr(fGrid.LastAddedRow); fGrid.Row[fGrid.LastAddedRow].Color := clWhite; fGrid.Row[fGrid.LastAddedRow].Border.Style:= besSolid; fGrid.Cell[0, fGrid.LastAddedRow].Value := AGrade; fGrid.Cell[1, fGrid.LastAddedRow].Value := AClasses; fGrid.Cell[2, fGrid.LastAddedRow].Value := AStudents; fGrid.Cell[3, fGrid.LastAddedRow].Value := AProgram; fGrid.Cell[4, fGrid.LastAddedRow].Value := 'Edit'; fGrid.Cell[5, fGrid.LastAddedRow].Value := 'Delete'; end;
  25. 1 point

    Component styling

    Thanks for the components LynkFS. I have found this insertRule a useful technique, especially in prototyping. I just grab LynkFS SMS_MDL_Components and wrapped this set of MDL components and ended up put them on SmartMobileStudio IDE, and looks nice indeed. I've created a very simple projMDL with a set of MDL components. Iā€™m a little skeptical of the claim that adding rules to the stylesheet is more efficient rather than CSS lazy loading by inserting it in the DOM nodes. I didn't tested a lot. I think using this approach it will create some kinda penalties like browser reflows issue and is difficult to debug injected styles. I prefer implementing insertCSS procedure into the initialization scope instead of the ObjectReady scope, for instance, if we drop two TButtons into designer, I suspect on form load, will inject the same CSS twice (rerunning) on the entire document. I don't know if injecting dynamically styles is faster in some specific cases, in particular mobile environments.