Jump to content
lynkfs@gmail.com

website building - 2

Recommended Posts

This is an addendum to my previous post

 

The Smart visual components system is based on absolute positioning.

Which is great in many cases for pixel perfect rendering under program control.

 

This post is about relying on browser capabilities, which means the positioning default is not 'absolute' but 'static' (or 'absolute', or 'fixed') and the browser determines element positioning depending on context.

 

So to have a certain degree of control, something else is needed.

 

There are some great css frameworks available based on the flex-box element

and I particularly like 'Frow', hosted on github and available for free

 

just substitute the frow css file for the app.css file

 

Frow is a css framework and features basic element positioning on pages.

Works great and contains among other components a grid system as well

 

Below program (that's all there is to it !) positions a grid and a button

The grid is populated from a database and the button is custom styled

uses W3C.HTML5, W3C.DOM, W3C.CSS, W3C.Console, JElement, W3C.XMLHttpRequest, ECMA.JSON;
 
//Frow 3 column grid
 
var h0   := TElement.Create('div', nil, 'frow-container');        //grid container
  var h01  := TElement.Create('div', h0,  'frow centered');       //rows
// columns h011 - h013 created from database                      //column elements
 
var sql_statement : String;
var encodedstr : String;
 
var FHttp := JXMLHttpRequest.Create;
  FHttp.open("POST","http://www.xxxxxxxxxxxxxx/smsdbmysql.php");
  FHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
  asm @encodedstr = encodeURIComponent('SELECT * FROM testtable limit 5'); end;
  sql_statement := "sql_statement="+encodedstr;
  FHttp.send(sql_statement);
 
var smscursor : Variant;
var DBRows : Integer;
 
JGlobalEventHandlers(FHttp).onLoad := lambda(e:JEvent)
  Console.Log('SQL statement executed and cursor ' + e.type + 'ed !');
  smscursor := JSON.parse(FHttp.ResponseText);
  DBRows := smscursor.smsrows.length;
 
//create 100*5=500 rows
  For var j := 0 to 100 do begin
   For var i := 0 to DBRows - 1 do begin
 
    var r01 := TElement.Create('div', h01, 'col-md-2-12', smscursor.smsrows[i].user);
               TElement.Create('div', h01, 'col-md-1-12', '<br><br>');
    var r02 := TElement.Create('div', h01, 'col-md-2-12', smscursor.smsrows[i].password);
               TElement.Create('div', h01, 'col-md-1-12');
    var r03 := TElement.Create('div', h01, 'col-md-2-4', smscursor.smsrows[i].pwhint);
 
    r01.SetProperty('background', 'lightblue');
    r02.SetProperty('background', 'lightgrey');
    r03.SetProperty('background', 'lightgreen');
    r03.SetProperty('border','1px solid lightseagreen');
   end;
  end;
 
//add a blank line and a nicely styled button
var p01 := TElement.Create('p', nil, 'p', ' ');
var d01 := TElement.Create('div', nil, 'div');
  var d011 := TElement.Create('div', d01, 'frow');
    var d0111 := TElement.Create('button', d011, 'button', 'Submit');
    d0111.SetProperty('background','none');
    d0111.SetProperty('border','2px solid lightseagreen');
    d0111.SetProperty('color', 'lightseagreen');
 
end;
 

it comes out of the box with responsive styling, so this demo changes layout depending on screen size.

Scrolls nicely on mobile too

 

In some cases may be a good alternative for the standard grid component

Share this post


Link to post
Share on other sites

Also check out the ux kitchen sink

uses W3C.HTML5, W3C.DOM, W3C.CSS, W3C.Console, JElement;
 
//Frow kitchensink
 
var p0   := TElement.Create('p', nil, 'p');
 
var ks := TElement.Create('div', nil, 'form-example-contain bottom-margin');
    var ks1 := Telement.Create('div', ks, 'frow centered');
        var ks2 := TElement.Create('div', ks1, 'form-example card-shadow');
            var ks3a := TElement.Create('label', ks2, 'blue', 'Name');
            var ks3b := TElement.Create('input', ks2, 'input');
                ks3b.SetAttribute('type', 'text');
                ks3b.SetAttribute('placeholder', 'Placeholder Text');
            var ks3c := TElement.Create('label', ks2, 'label', 'Disabled Field');
            var ks3d := TElement.Create('input', ks2, 'blue');
                ks3d.SetAttribute('type', 'text');
                ks3d.SetAttribute('placeholder', 'Placeholder Text');
                ks3d.SetAttribute('disabled', 'disabled');
            var ks3e := TElement.Create('div', ks2, 'frow gutters');
                var ks4a := TElement.Create('div', ks3e, 'col-md-1-2');
                    var ks5a := TElement.Create('label', ks4a, 'blue', 'Zipcode');
                    var ks5b := TElement.Create('input', ks4a, 'input');
                        ks5b.SetAttribute('type', 'text');
                        ks5b.SetAttribute('pattern', '\d*');
                        ks5b.SetAttribute('maxlength', '5');
                var ks4b := TElement.Create('div', ks3e, 'col-md-1-2');
                    var ks5c := TElement.Create('label', ks4b, 'inline', 'Color');
                    var ks5d := TElement.Create('select', ks4b, 'my-custom-select inline');
                        var ks6a := TElement.Create('option', ks5d, 'option', 'Red');
                        var ks6b := TElement.Create('option', ks5d, 'option', 'Green');
                        var ks6c := TElement.Create('option', ks5d, 'option', 'Blue');
            var ks3f := TElement.Create('label', ks2, 'blue', 'File Upload');
            var ks3g := TElement.Create('input', ks2, 'input');
                ks3g.SetAttribute('type', 'file');
            var ks3h := TElement.Create('label', ks2, 'blue', 'Text Area');
            var ks3i := TElement.Create('textarea', ks2, 'my-custom-textarea card-shadow', '');
            var ks3j := TElement.Create('div', ks2, 'frow justify-around');
                var ks4c := TElement.Create('button', ks3j, 'blue card-shadow hidden-xs', 'Submit');
                var ks4d := TElement.Create('button', ks3j, 'rounded', 'Submit');
                var ks4e := TElement.Create('button', ks3j, 'my-custom-button', 'Submit');
 
JGlobalEventHandlers(ks4c.AsNode).onClick := lambda(e:JEvent)
  asm alert('First button'); end;
end;
JGlobalEventHandlers(ks4d.AsNode).onClick := lambda(e:JEvent)
  asm alert('Second button'); end;
end;
JGlobalEventHandlers(ks4e.AsNode).onClick := lambda(e:JEvent)
  asm alert('Third button'); end;
end;

with eventhandlers included

 

.

Share this post


Link to post
Share on other sites

Thanks for sharing, this frow system is really impressive, I'll have to try it and apply when possible.                             

It would be great if next SMS update would be fully compatible with it.

Share this post


Link to post
Share on other sites
Yeap, the visual designer expects the controls to be derived from TW3CustomControl (which brings in a more heavy infrastructure).
 
It has been said, the upcoming new RTL, jonlennartaasenden has made some changes architectually in the RTL. 
The TW3Component is now the basis for non-visual components, which opens up for a whole new set of lightweight controls 
that can be dragged onto a form. Here is the new inheritance chain:
[+]TW3CustomComponent
  [+]TW3Component
     [+]TW3TagObj
        [+]TW3TagContainer
           [+]TW3MovableControl
              [+]TW3GraphicControl
              [+]TW3CustomControl

Personally, I think this approach is a great idea, you could even use a SmartMS Lite IDE alternative, maybe open source.

 

Unfortunately, they didn't really like of this idea (all bets are on the RAD approach) - the visual designer and "live" rendering of controls. The SmartCL* framework has its strenghts.

 

BTW, I have already used your approach, that I'd call the "hard core metal smart programming", in several projects, for instance:

 

https://rawgit.com/smartpascal/smartms/master/games/iSroll_SMS/www/loader.html

https://rawgit.com/smartpascal/smartms/master/games/ProjHybrid/www/preview.html

https://rawgit.com/smartpascal/smartms/master/games/projSearchBar/www/preview.html

https://rawgit.com/smartpascal/smartms/master/games/projCreatures/www/index.html

https://rawgit.com/smartpascal/smartms/master/games/ProjSmartBank/www/index.html

https://rawgit.com/smartpascal/smartms/master/games/smsLoader/www/index.html

https://rawgit.com/smartpascal/smartms/master/games/projLOG/www/index.html

 

 

Hey, I will wait the next RTL release, and modify the the  SMS Component Generator tool to generate a component template based on the TW3Component class, I hope it will generate plain smart JHTMLElements on the fly in a second :)

 

Share this post


Link to post
Share on other sites

I've been thinking too of asking to change the IDE so that it caters for other component structures (like the bare-metal JHTMLElements of this post).

Or to be made open source, or having some sort of api to make it more accessible for alternative components

 

That might drain the scarce resources too much though,

or it might be on the drawing board already

We'll see what happens in the (near) future.

 

The generator tool would certainly be an asset !

I was looking for your previous version, but it has been removed from the link

 

By the way (and somewhat unrelated) I also compiled the project for the ux kitchen sink with the command line compiler, and that works just great too.

Share this post


Link to post
Share on other sites

hmmmmmm (thinking)

 

These classes form part of SmartCL.Components :

 

 

 
  //Baseclass for custom application target containers
  TCustomAppContainer = class(TW3Component)
  end;
 
  //DIV based application target
  TDIVAppContainer = class(TCustomAppContainer)
  end;
 
  //Document Body container
  TDocumentBody = class(TCustomAppContainer)

Share this post


Link to post
Share on other sites

Just curious, It look me less than 1 second to clone your kitchen demo http://www.lynkfs.com/j5/www/main0.html using the generator.

var docFragment := JDocumentFragment( document.createDocumentFragment() ); // contains all gathered nodes

var div_ := JHTMLDivElement( document.createElement('DIV') );
div_.setAttribute("class", "form-example-contain bottom-margin");
docFragment.appendChild(div_);

var div_0 := JHTMLDivElement( document.createElement('DIV') );
div_0.setAttribute("class", "frow centered");
div_.appendChild(div_0);

var div_1 := JHTMLDivElement( document.createElement('DIV') );
div_1.setAttribute("class", "form-example card-shadow");
div_0.appendChild(div_1);

var label_ := JHTMLLabelElement( document.createElement('LABEL') );
label_.setAttribute("class", "blue");
div_1.appendChild(label_);
var text_ := JText( document.createTextNode("Name") );
label_.appendChild(text_);

var input_ := JHTMLInputElement( document.createElement('INPUT') );
input_.setAttribute("class", "input");
input_.setAttribute("type", "text");
input_.setAttribute("placeholder", "Placeholder Text");
div_1.appendChild(input_);

var label_0 := JHTMLLabelElement( document.createElement('LABEL') );
label_0.setAttribute("class", "label");
div_1.appendChild(label_0);
var text_0 := JText( document.createTextNode("Disabled Field") );
label_0.appendChild(text_0);

var input_0 := JHTMLInputElement( document.createElement('INPUT') );
input_0.setAttribute("class", "blue");
input_0.setAttribute("type", "text");
input_0.setAttribute("placeholder", "Placeholder Text");
input_0.setAttribute("disabled", "disabled");
div_1.appendChild(input_0);

var div_2 := JHTMLDivElement( document.createElement('DIV') );
div_2.setAttribute("class", "frow gutters");
div_1.appendChild(div_2);

var div_3 := JHTMLDivElement( document.createElement('DIV') );
div_3.setAttribute("class", "col-md-1-2");
div_2.appendChild(div_3);

var label_1 := JHTMLLabelElement( document.createElement('LABEL') );
label_1.setAttribute("class", "blue");
div_3.appendChild(label_1);
var text_1 := JText( document.createTextNode("Zipcode") );
label_1.appendChild(text_1);

var input_1 := JHTMLInputElement( document.createElement('INPUT') );
input_1.setAttribute("class", "input");
input_1.setAttribute("type", "text");
input_1.setAttribute("pattern", "\\d*");
input_1.setAttribute("maxlength", "5");
div_3.appendChild(input_1);

var div_4 := JHTMLDivElement( document.createElement('DIV') );
div_4.setAttribute("class", "col-md-1-2");
div_2.appendChild(div_4);

var label_2 := JHTMLLabelElement( document.createElement('LABEL') );
label_2.setAttribute("class", "inline");
div_4.appendChild(label_2);
var text_2 := JText( document.createTextNode("Color") );
label_2.appendChild(text_2);

var select_ := JHTMLSelectElement( document.createElement('SELECT') );
select_.setAttribute("class", "my-custom-select inline");
div_4.appendChild(select_);

var option_ := JHTMLOptionElement( document.createElement('OPTION') );
option_.setAttribute("class", "option");
select_.appendChild(option_);
var text_3 := JText( document.createTextNode("Red") );
option_.appendChild(text_3);

var option_0 := JHTMLOptionElement( document.createElement('OPTION') );
option_0.setAttribute("class", "option");
select_.appendChild(option_0);
var text_4 := JText( document.createTextNode("Green") );
option_0.appendChild(text_4);

var option_1 := JHTMLOptionElement( document.createElement('OPTION') );
option_1.setAttribute("class", "option");
select_.appendChild(option_1);
var text_5 := JText( document.createTextNode("Blue") );
option_1.appendChild(text_5);

var label_3 := JHTMLLabelElement( document.createElement('LABEL') );
label_3.setAttribute("class", "blue");
div_1.appendChild(label_3);
var text_6 := JText( document.createTextNode("File Upload") );
label_3.appendChild(text_6);

var input_2 := JHTMLInputElement( document.createElement('INPUT') );
input_2.setAttribute("class", "input");
input_2.setAttribute("type", "file");
div_1.appendChild(input_2);

var label_4 := JHTMLLabelElement( document.createElement('LABEL') );
label_4.setAttribute("class", "blue");
div_1.appendChild(label_4);
var text_7 := JText( document.createTextNode("Text Area") );
label_4.appendChild(text_7);

var textarea_ := JHTMLTextareaElement( document.createElement('TEXTAREA') );
textarea_.setAttribute("class", "my-custom-textarea card-shadow");
div_1.appendChild(textarea_);

var div_5 := JHTMLDivElement( document.createElement('DIV') );
div_5.setAttribute("class", "frow justify-around");
div_1.appendChild(div_5);

var button_ := JHTMLButtonElement( document.createElement('BUTTON') );
button_.setAttribute("class", "blue card-shadow hidden-xs");
div_5.appendChild(button_);
var text_8 := JText( document.createTextNode("Submit") );
button_.appendChild(text_8);

var button_0 := JHTMLButtonElement( document.createElement('BUTTON') );
button_0.setAttribute("class", "rounded");
div_5.appendChild(button_0);
var text_9 := JText( document.createTextNode("Submit") );
button_0.appendChild(text_9);

var button_1 := JHTMLButtonElement( document.createElement('BUTTON') );
button_1.setAttribute("class", "my-custom-button");
div_5.appendChild(button_1);
var text_10 := JText( document.createTextNode("Submit") );
button_1.appendChild(text_10);

document.body.appendChild( docFragment );

The main advantage to use the DocumentFragments allow to place child elements onto an arbitrary node-like parent (the parent can be a visual smart component or inject directly on the body), allowing for node-like interactions without a true root node.  

 

Doing so allows developers to produce structure without doing so within the visible DOM.

 

The main advantage, using the JHTMLElement interfaces - to create node element - is the code insight/completion available in the smart IDE, such parameter/methods hits is available everywhere. We can easily assign event handlers directly on the corresponding JElement node or indirectly via a custom published property.

 

e.g. Assign event handle on the specific node:

type
  TProcedure = procedure;

procedure bindEvent(element: Variant; EventType: variant; handler: TProcedure);
begin
  if (element.addEventListener) then
    element.addEventListener(EventType, @handler, false)
  else
    element.attachEvent('on'+EventType, @handler);
end;

procedure teste;
begin
  WriteLn('clicked!')
end;

bindEvent(button_1, "click", teste); // button_1 is JElement node 

Unfortunately, the smart generator is not complete, some tags doesn't have the corresponding JElement interface in the w3C.HTML5 unit. 

Share this post


Link to post
Share on other sites

Hi Warleyalex

 

Thanks for your views and sharing

 

Looks like we've been working along similar lines, 

and obviously you got there sooner 

 

I particularly like your documentFragment approach, it saves a lot of browser reflows when inserting multiple elements

 

Your diversification of the different JElement types is more specific and makes for better reading too, although sometimes the generic JElement approach may make life easier.

 

I started this post as I needed to find out how to produce lightweight web pages, so I'll just add the remainder that I wanted to share in the next day or so

Maybe at some point we can merge some code if that's of general interest

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×