Jump to content

Ron

uniGUI Subscriber
  • Posts

    375
  • Joined

  • Last visited

  • Days Won

    31

Posts posted by Ron

  1. Hello,

     

    Here is an easy way to get a free Class 1 SSL certificate on startssl.com,

    valid for 1 year, which I just tried - and it works right out of the box.

     

    -Sign in at startssl.com and validate email and domain.

    -Retrieve certificate and save as cert.pem

    -Use online tool to decrypt private key and save as key.pem

    -Download the CA root certificate .pem file and save as ca.pem

    -Enable SSL on servermodule

    -Change port to 443

    -Put .pem files in same folder as exe, with openssl windows binaries

    -upload all the files to the server

     

    Cheers :)

    • Upvote 2
  2. I do not use a grid component in those shots.

     

    What you see are two HtmlFrames, one showing day and one showing month.

     

    Both are set at align Client, and depending on what view you want, one is set visible and the other invisible.

     

    I could not use a Pagecontrol for this, as only the visible frame will actually display loaded html.

     

    Depending on what data is already loaded, the Htmlframe is updated on date change,

    the html is preloaded and then the variables are updated and then the script is sent to the frame.

     

    Any other JS variable change is made using unisession.addJS.

     

     

    Why do it like this?

     

    Because Unigui does not send mouse moves, and for drag and drop you absolutely must have that,

    and this functionality was one of core requirements, along with net functionality.

     

    So there is no way around having the grids in javascript, but it is not hard to

    create a fluid grid layout in JS. And of course, when there is so much going on at the

    user interface mouse event level, it is a very good thing - in my opinion - to get a separation

    of code here, with like 80% of the user interface code in javascript.

     

    So there is 2000 lines of JS for the interface, 3000 lines of code in Mainform making up the

    server side engine logic, and then 10.000 lines spread around in 35 units for other forms,

    making up a nice and logical separation of things.

     

    I could have tried to adapt a commercial or free JS calendar script, but when looking at

    the event collision routines at some of these scripts, with thousands of lines of code

    just for that, I knew I could make it simpler myself. My mousemove event is now

    only 234 lines, so most of the struggle is to just keep it simple. The less code, the less bugs.

     

    But Javascript dates.....is an "interesting" issue, and of course we have three different date

    paradigms in JS, Object Pascal and MySQL, just to be sure that we get enough confused.

    TIP: avoid using JS time portion of date objects, due to uncontrollable daylight savings issue.

     

    Btw, I have opened up the guest account at avtalebok.com, to normal user level, not admin,

    but now you can test app movement and resize etc.

  3. After 3 months of work, porting a desktop app to Unigui,

    reaching 16.000 lines of code, including 2.000 lines of Javascript,

    I have started online testing of my booking app, running

    it on two separate Amazon EC2 instances:

     

    1. Win 2012 Server, at timebok.com - login: guest/guest

     

    2. Win 2008 Server, at avtalebok.com - login: guest/guest

     

    At 1. only, Guest login is readonly and has restricted access.

     

    Attached are images when logged in, and I notice:

     

    -the toolbar has wrong color

    -things are definitely responding slower on the 2008 server

     

    I am running a standalone app, on port 80 of course, using mysql 5.6,

    and Unigui build 1172, on both servers.

     

    The EC2 instance is the smallest (free) possible, and I am going

    to upgrade this to see what happens, so that may impact the speed,

    but I assumed the 2012 opsys was slower....

     

    The app itself is not big, about 23 Mb.

     

    But it runs fine on the 2012 server, it seems.

     

    I notice a slight flicker when the pattern background is being loaded,

    but I guess that is hard to avoid....maybe it could be preloaded somehow?

     

    But the setup is exactly the same on both operating systems, the very

    same standalone exe running too.

     

    Easy to set up on EC2, takes only 20 minutes if you remember to

    change security policy and reboot the instance.

     

     

    I really love the Unigui system, amazingly easy to work with and

    an incredibly productive tool. It would have taken me at least

    12 months to build this in pure javascript/Node or php.

     

    I my view, Unigui is the only working WebRAD tool around. I even bought

    Morfik, but had to give that up too. For 6 years I searched for a good tool

    which should make it possible to do this work in a few months, and finally

    I found it. Being able to just move thousands of lines of code, without change,

    including database objects (DAC for MySQL) complete with the SQL,

    was truly a great timesaver.

     

    So thumbs up for a great programming tool which will revolutionize the webapp industry !

    post-980-0-09704800-1437608918_thumb.png

    post-980-0-93231500-1437608927_thumb.png

    post-980-0-15231800-1437609673_thumb.png

    post-980-0-88053600-1437609962_thumb.png

    • Upvote 2
  4. Wondering if anyone has a good solution to this glyph issue,

    or am I the only one experiencing this?

     

    A glyph margin property would have been the perfect thing, I guess...

     

    I run build 1172, this project on XE2.

    post-980-0-50071300-1437538100_thumb.png

  5. Yes, one database, one server, but two different clients with different main windows.

     

    No it's not an option, server should be only single. I know there can be only one port per server, so I added the "First" and the "Second" parts in URL to distinguish the clients.

     

    Yes, exactly, I need such mechanism but don't know how to create it cause the main Unigui form is created automatically.

     

     

    If you look at the URLParameters demo, the parameters are accessible

    in the onShow event of the main form, and that means you can at that 

    point change whatever you want, depending on the parameter, before

    the "client experience" is produced by the unigui http server.

     

    At the simplest level, you can change/adapt design-time interface elements

    here, or fully create the two interfaces at runtime on show, or doing it more complex,

    you can load two different html files into one htmlframe, and go from there,

    with the ajaxrequest handling two different event sets from the two different

    html/javascript setups.

  6. I assume you mean two servers working against the same database,

    on the same physical server - and that is no problem.

     

    But of course not on the same port - as only one server process

    can listen to a port at a time, on a single IP, as it locks it.

     

    So you can just run them in the same folder, but on 8077

    and 8088 for example, if you just test with standalone.

     

    To create two different "client" versions from a single

    server process, you need some trigger mechanism that tells

    the single server what to deliver - could be anything like

    something in the url to the average temperature of LA

    on that day...and it produces one of two versions.

     

    If you need two servers on the same port, the server IPs

    must be different, and then again folders dont matter.

  7. I needed a phone number lookup function, so I used an Indy http client component to 
    GET the html file from the phone lookup site, and then made a very simple parsing
    procedure to extract the phone/user info.
     
    I guess you could do the same, even extract all links and get them too, like css
    and images etc. I dont see the reason to use urlframe to get only the html file itself, as
    you then also have the visual presentation taking up resources. Compared to this,
    the resource use by only downloading may be much smaller, esp. if media is involved.

    uses
      IdHTTP;
    
    ...
    
    function getUrl(aURL: string): string;
    const
      cUSER_AGENT = 'Mozilla/4.0 (MSIE 6.0; Windows NT 5.1)';
    var
      IdHTTP: TIdHTTP;
      Stream: TStringStream;
    begin
      Result := '';
      IdHTTP := TIdHTTP.Create(nil);
      Stream := TStringStream.Create;
      try
        IdHTTP.Request.UserAgent := cUSER_AGENT;
        try
          IdHTTP.Get(aURL, Stream);
          Result := Stream.DataString;
        except
          Result := '';
        end;
      finally
        Stream.Free;
        IdHTTP.Free;
      end;
    end;
    

    URLFrame.zip

  8. Agree - and also quite often you need to be able to pick a value with its key,

    from a single control - without using a grid -and then a dbcombobox or dblistbox

    with a keyfield would do the trick.

     

    At the same time - if you make this, Farshad - why not also make a

    non-db version where you can store an integer value for each item,

    which could then take a key value.

    • Upvote 1
  9. I also wondered about that...but ended up coding the calendar myself

    in javascript, so I got the drag/drop move and resize appointments etc.

     

    Not that much work, "only" 1.300 lines of JS! See attached screenshot.

     

    Good thing is you get all the details you want, as fast as possible,

    and there is no calendar API to locate and study...

     

    For instance: how to get several columns for each day?

     

    Have several instances of the calendar? 

     

    And how to drag and drop between them? 

     

    I can just imagine how complex that might be...or to be honest, I can't ! :)

     

     

     

    post-980-0-79608000-1434569500_thumb.png

  10. I also researched this a bit, and came across VCL components that do this, there was one in

    the JEDI library I think.

     

    Anyway, these components often come with lots of complexity, and it easily takes more hours

    to read and understand all that, than to create a simple solution, I suspected.

     

    So I made a simple solution, using an online activation concept, where I just run a simple

    HTTP GET towards the online DB, using a very small PHP script which checks username

    and password of the online account.

     

    If that exists, and the license is valid, then I store the username both in plain form

    and in encrypted form in the local DB (this was for desktop app in Lazarus), and 

    always decrypt and check this on app startup.

     

    The user DB you already should have, the PHP script is like 20 lines,

    the client HTTP GET routine is very simple...and the only thing that 

    takes a little time is writing the storing/reading with encrypt/decrypt,

    using some library, but anyway it boils down to 20 lines of code,

    and that is it.

     

     

    But you can make it even simpler, since this app runs online.

     

    Just do a HTTP GET every time the servermodule loads,

    and check license data - no need to store anything.

     

    if not HTTP-GET(licensedata)=OK then close;

     

    I guess the response should not be some static piece of

    data, as that could be hacked by changing hosts file and thus

    routing the request to some local fix, but encrypt some

    time varied data, send it and modify it and get it back and

    and then decrypt upon receipt - like the current date and time

    for instance.

     

    You can check this onstartup or as often as you like,

    or on specific routines. All you need is a modified encrypted

    response to your encrypted request, from your licensing server,

    and if you already have SSL setup then there is no need

    for extra encryption even. JUst a simple HTTP GET DB check.

     

    This assumes the customer is online constantly.

     

    If not, you can require the customer to be online for licensing only.

     

    Who would reject that, claiming that they can never be online?

    Hard to believe - since they probably found you online anway.

    I dont buy that - everybody can access the net for a little time

    to activate, unless you are in the middle of %¤&%¤ Amazon Jungle,

    but then this is such a special customer that he can pay big time

    and you need no protection, or he is working for secret intelligence

    and then also there is unlimited money in the black budgets.

     

    So I suggest, Keep It Simple, demand online activation, go SSL, 

    do a simple HTTP GET check for license info on startup and thats it.

    • Upvote 1
  11. I experimented a little with the drawing routine, and came up with a simple solution

    where you push invalid pixel data to split the paths:

     function drawStuff() {
         //first clear the canvas and draw a thin border
         ctx.beginPath();
         ctx.strokeStyle = "#000000"; //black color
         ctx.lineCap = 'square';
         ctx.lineWidth = 0.5;
         ctx.fillStyle = "#FFFFFF";    
         ctx.rect(0,0,canvas.width, canvas.height);
         ctx.fill();
         ctx.stroke(); 
         ctx.closePath();
         //loop through the pixel data
         ctx.beginPath();
         for(var i=0;i<(myArray.length-1);i++){
           //when we encounter illegal pixel data, close the path	
           if(myArray[i].x === -1){
           	 ctx.stroke();     
             ctx.closePath();
    	 ctx.beginPath();
    	 } else 
    	//skip to valid pixel data and draw paths
    	if(myArray[i+1].x != -1) {
             ctx.moveTo(myArray[i].x, myArray[i].y);
             ctx.lineTo(myArray[i+1].x, myArray[i+1].y);
           }
         } 
         //close last path
         ctx.stroke();     
         ctx.closePath();
       } 
    

    And you do this in the mouseup event: 

     $("#mycanvas").mouseup(function(event){
         //skip right mouse up
         if(event.which===3) return;
         mDown = false;
         document.getElementById("mycanvas").style.cursor = 'default'; 
         //push invalid pixel data to mark end of path
         myArray.push({x:  -1, y : -1});
         drawStuff();
         //turn screenmask on...
         //myMask.show();
         //ajaxRequest(MainForm.myHTMLFrame, ['saveCanvasData'], { myArray... });
       }); 
    

    In addition I have added a line to the mousedown event, changing cursor style:

    $("#mycanvas").mousedown(function(event){
         //skip right mouse up
         if(event.which===3) return;
         //start logging
         mDown = true;
         
         document.getElementById("mycanvas").style.cursor = 'pointer'; 
         drawStuff();
       }); 
    

    Testing this quickly, it seems to work. Of course this must be

    debugged re events and statuses etc. As the mouse leaves

    the canvas, the mouseup event will not be triggered, so you

    have to add a mouseout event - I guess - and set mDown=false

    to avoid a mouse "hang-up"...etc. - like this:

     $("#mycanvas").mouseout(function(event){
      	if(event.which===3) return;
      	mDown = false;
      	myArray.push({x:  -1, y : -1});
            document.getElementById("mycanvas").style.cursor = 'default'; 
      	drawStuff();
       }); 
    

    One can use this to create a simple CAPTCHA routine, where

    e.g. the user must draw a line between two shapes, to continue.

    • Upvote 1
  12. Here is an example of JS code which works in docpad, as signature.js:

     $(document).ready( function() {
      //canvas id="mycanvas">
      //<script type="text/javascript">
    
      var canvas = document.getElementById("mycanvas");
      var ctx = canvas.getContext("2d");
      var mDown = false;
      var myArray = [];
      var coords = [];
          
      function drawStuff() {
      	//do your canvas drawing here...
      	 ctx.beginPath();
         ctx.fillStyle = "#EEEEEE";    
         ctx.rect(0,0,canvas.width, canvas.height);
         ctx.fill();
         
         ctx.beginPath();
         ctx.strokeStyle = "#000000"; //black color
         ctx.lineWidth = 0.8;
         ctx.lineCap = 'square';
         var i = 0;
         for(i=0;i<(myArray.length-1);i++){
           ctx.moveTo(myArray[i].x, myArray[i].y);
           ctx.lineTo(myArray[i+1].x, myArray[i+1].y);
         }
         ctx.stroke();     
         ctx.closePath();
        } 
        
       function relMouseCoords(event){
        var totalOffsetX = 0;
        var totalOffsetY = 0;
        var canvasX = 0;
        var canvasY = 0;
        var currentElement = this;
    
        do{
            totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
            totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
        }
        while(currentElement = currentElement.offsetParent);
    
        canvasX = event.pageX - totalOffsetX;
        canvasY = event.pageY - totalOffsetY;
    
        return {x:canvasX, y:canvasY}
      }
      HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;
        
      
       $("#mycanvas").mousemove(function(event){
          //store mouse movements
          if(mDown){
          coords = canvas.relMouseCoords(event);
          myArray.push({x:  coords.x, y : coords.y});
          drawStuff();
          }
       });
        
       $("#mycanvas").mousedown(function(event){
       	//skip right mouse up
      	if(event.which===3) return;
         //start logging
         mDown = true;
         drawStuff();
       }); 
       
      $("#mycanvas").mouseup(function(event){
      	//skip right mouse up
      	if(event.which===3) return;
      	mDown = false;
      	 //turn screenmask on...
         //myMask.show();
         //ajaxRequest(MainForm.myHTMLFrame, ['saveCanvasData'], { myArray... });
       }); 
       
      
      window.addEventListener('resize', updateCanvas, true);
      function updateCanvas() {
        //canvas.width = MainForm.myHTMLFrame.getWidth();
        //canvas.height = MainForm.myHTMLFrame.getHeight(); 
        drawStuff();
        
      }
      updateCanvas();
       
    //</script>
      });
    

    In addition to this, you have this index.html:

    ---
    title: "Welcome!"
    layout: "default"
    isPage: true
    ---
    
    
    <canvas id="mycanvas" style="border:0px solid #990000;">
    </canvas>
    

    And this eco layout file:

    <html>
    <head>
       <title><%= @document.title %> | My Website</title>
       <%- @getBlock("meta").toHTML() %>
    </head>
    <body>
        <%- @content %>
        <%- @getBlock("scripts").add(["/vendor/jquery.js","/scripts/signature.js",]).toHTML() %>
    
    </body>
    </html>
    

    Notice that jQuery is there too.

     

    Of course you have to modify this code, to split the paths you draw,

    so not all pixels are connected, and then create the upload code.

     

    If you want me to do it for you, we can maybe work out a deal,

    but this should not be too hard to finish.

  13. Hi Sandro;

     

    The basic idea is that as the mouse moves, it reports x and y coordinates,

    and you push these into an array.

     

    THen in drawStuff() you simply draw these pixels, by drawing

    lines between them, as you loop through the array,

    something like this:

     

    ctx.beginPath();

    ctx.strokeStyle = "#000000"; //black color
    ctx.lineWidth = 0.8;
    ctx.lineCap = 'square';
     

    for(i=0;i<myArray.length-1;i++){

    ctx.moveTo(myArray.x, myArray.y);
    ctx.lineTo(myArray[i+1].x, myArray[i+1].y);
    }

     

    ctx.stroke();

    ctx.closePath();

     

    Basic Javscript is not difficult at all, and you will get used to the syntax in no time,

    and W3Schools have all the info you need.

     

    My impression is that Javascript is a very powerful language, I simply love it !

    It is amazing what you can do, and with a knowledge of JS combined with

    Unigui, you can create almost anything.. :)

     

    Best to just dive into it ! :)

     

    And the communication between JS in the client and Unigui, is so simple

    and easy to set up, it is like a walk in the park compared to creating things

    piece by piece in PHP for instance, and also much easier than Node &

    various JS frameworks like backbone.JS, sails.JS etc, even though you

    have JS on both sides there.

     

    Tip: Use docpad, with LiveReload, when you make JS code.

     

    I do that, and when I click Ctrl-S, the browser is updated in the

    background, and with the console you get easy debugging.

     

    This way it is so FAST to develop client code with JS, it is fun

    and you learn JS fast too, because of this close feedback loop.

     

     

    Anyway, after the signature is ok, you just upload this to the server,

    meaning that array, and save it, and reconstruct the signature

    image based on that pixel data.


  14. //example JS code for capturing mouse events, load this into htmlfram
    //turn screenmask off by UniSession.AddJS('myMask.hide();'); after saving canvas data

    <canvas id="mycanvas">

    <script type="text/javascript">
    var canvas = document.getElementById("mycanvas");
    var ctx = canvas.getContext("2d");
    var mDown = false;
    var myMask = new Ext.LoadMask(MainForm.myHTMLFrame, {msg:"Saving data ..."});

    function drawStuff() {
    //do your canvas drawing here...
    ctx.moveTo(...)
    }

    function relMouseCoords(event){
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do{
    totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
    totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
    }
    while(currentElement = currentElement.offsetParent);

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    return {x:canvasX, y:canvasY}
    }
    HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;


    $("#mycanvas").mousemove(function(event){
    //store mouse movements
    if(mDown){
    coords = canvas.relMouseCoords(event);
    push(myArray, {x: coords.x, y: coords.y});
    drawStuff();
    }
    });

    $("#mycanvas").mousedown(function(event){
    //skip right mouse up
    if(event.which===3) return;
    //start logging
    mDown = true;
    });

    $("#mycanvas").mouseup(function(event){
    //skip right mouse up
    if(event.which===3) return;
    //turn screenmask on...
    myMask.show();
    ajaxRequest(MainForm.myHTMLFrame, ['saveCanvasData'], { myArray... });
    });


    window.addEventListener('resize', updateCanvas, true);
    function updateCanvas() {
    canvas.width = MainForm.myHTMLFrame.getWidth();
    canvas.height = MainForm.myHTMLFrame.getHeight();
    drawStuff();

    }
    updateCanvas();

    </script>



     

  15. I assume you can use the canvas, just get the right

    screen size set up, log the mouse movements when mouse is down,

    draw the pixels on the canvas, and upload the canvas data by ajax

    to the server afterwards....process it and save as image,

    and load it back to the client again as confirmation.

     

    Write the client part in javascript, use a htmlframe with a <canvas id="mycanvas">

    and write the mouse handlers in JS too, and then use an ajaxcall

    to the htmlframe, picking up that in ajaxevent, when uploading the 

    canvas data.

     

    Load the JS into the htmlframe on formshow e.g. This works very well,

    and is the only good solution when needing to capture mouse movements,

    as far as I know.

  16. This was very well done! Nice combination of elements and technologies it seems.

     

    Congratulations :)

     

    I too would be interested in looking into how this was done....or see the basic principles.

     

    I am beginning to think that you can build anything with this Unigui tool....just amazing.

     

    The clue is to learn how to extend it with css, js and html5 etc, in the smartest way,

     

    to get a minimum level of code organizing.

    • Upvote 1
  17. Hello!

     

    I add some code using UniSession.AddJS, and this code contains:

     

    1.insertion of a canvas element, and getting context:

     

    var canv = document.createElement("canvas");
    canv.id = "daycal";
    document.body.appendChild(canv);
    var canvas = document.getElementById("daycal");
    var ctx = canvas.getContext("2d");
     
    2. THen some drawing on that canvas
     
    3. Then an event listener on canvas resize, to trigger the drawing function:
     
    window.addEventListener('resize', resizeCanvas, true);
      function resizeCanvas() {
        canvas.width = window.innerWidth-2;
        canvas.height = window.innerHeight-40;
        drawDayCalendar();
        drawAppopintments(); 
      }
     
     
    4. Then at last I trigger the resizefunction at the JS load
     resizeCanvas();

     

     

     

    Now, when I load the application, I get a short glimpse of the calendar graphics,

    but then the canvas gets cleared.

     

    Why does this happen?

     

    The drawing routine works, because I can see the graphics.

     

    So the event listener does not work, as the canvas is not redrawn - wonder why?

     

    I am doing things this way because I need mouse movements for drag/drop and appointment resize,

    so I have 600 lines of javascript loading here, including event code.

     

    Btw I had to drop the mouse events while testing because I do not have jQuery, but I guess I could load that too (?),

    or use some other method to capture those events if possible.

     

    Anyway, there is something not working here.

     

     

    Is it a problem that I create the canvas html element in javascript?

     

    Does Unigui mess with the event listening setup?

     

    Any advise is most welcome!

     

     

    Kaj

  18. My online ordering application has been running on exactly such a setup,

    for over two years, without a single change in fact - accepting something in

    the amount of 20-30 orders a week I think, or maybe even more nowadays.

     

    And that is even on a very slow line...slow upload speed, takes maybe 20 

    seconds to load, at least. But still people use it, and it works. No code change

    for over two years. So Unigui has been very stable, and been able to run

    on exceptionally few resources....quite impressive I think.

    • Upvote 2
×
×
  • Create New...