Jump to content

website building

Recommended Posts

  • Moderators
Making multipage websites using Smart, including shopping functions and cc payments, is very feasable. 
A substantial amount of code though needs to be added to handle scrolling, the browsers back button, fontsizes related to screen size and flowcontrol/responsiveness, among other issues. 
There are posts on different ways how to tackle these subjects in the forum.
The amount of coding it takes made me realise that most of the functions mentioned above above are already present in the browser code.
Browsers know how to handle the back-button, are very good at scrolling and are expert in laying out elements on screens with variable dimensions. 
Besides that, the browser knows all about the main ux elements like button, editbox, radio button etc
So this post is about exploring if it is feasable to leverage these innate browser functions rather than re-code them.
Or in other words to see if it is possible to re-create a web-site in code while bypassing the use of Smart components.
The demo website to be re-created is a tutorialzine freebie , a device-responsive one-pager built in html and css, no js involved.
Starting off with the principles shown in this post, the minimum code to generate all of the various html-elements in the target website is something like this 

unit JElement;
uses W3C.HTML5, W3C.DOM, W3C.CSS;
  TElement = class
    FElement: JHTMLElement;
    function AsNode() : JNode;
    constructor Create(element: String; parent: TElement; className: String; innerHTML : String); virtual;
    constructor Create(element: String; parent: TElement; className: String); overload;
    Procedure SetProperty(S1: String; S2: String);
    Procedure SetAttribute(S1: String; S2: String);
{ TElement }
constructor TElement.Create(element: String; parent: TElement; className: String; innerHTML : String);
  // cache element and set innerHTML and className
  FElement := JHTMLElement(Document.createElement(element));
  FElement.innerHTML := innerHTML;
  FElement.className := ClassName;
  If parent = nil
    then document.body.appendChild(self.AsNode)
    else parent.AsNode.appendchild(self.AsNode);
constructor TElement.Create(element: String; parent: TElement; className: String);
  // cache element and set className
  FElement := JHTMLElement(Document.createElement(element));
  FElement.innerHTML := '';
  FElement.className := ClassName;
  If parent = nil
    then document.body.appendChild(self.AsNode)
    else parent.AsNode.appendchild(self.AsNode);
function TElement.AsNode() : JNode;
  Result := FElement;
Procedure TElement.SetProperty(s1: String; S2: String);
  var FElementStyle := JElementCSSInlineStyle(FElement).style;
  FElementStyle.setProperty(S1, S2);
Procedure TElement.SetAttribute(S1: String; S2: String);
  FElement.setAttribute(S1, S2);
which creates elements like 'div', 'p' etc. including style properties and attributes
The constructor accepts the element-type, a parent, a classname (styling) and optionally some content
Re-creating the demo website then starts with 

uses W3C.HTML5, W3C.DOM, W3C.CSS, W3C.Console, JElement;
//First few html lines in the demo website
    <h2><a href="#">Website Logo</a></h2>
        <li><a href="#">Home</a></li>
        <li><a href="#">Products</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contacts</a></li>
var h0   := TElement.Create('header', nil, 'header');  //create a header element which has no parent (nil) and has a className 'header'
  var h01  := TElement.Create('h2', h0,  'h2', '<a href="#">Website Logo</a>');
  var h02  := TElement.Create('nav', h0, 'nav');
    var h021 := TElement.Create('li', h02, 'li', '<a href="#">Home</a>');
    var h022 := TElement.Create('li', h02, 'li', '<a href="#">Products</a>');
    var h023 := TElement.Create('li', h02, 'li', '<a href="#">About</a>');
    var h024 := TElement.Create('li', h02, 'li', '<a href="#">Contacts</a>');
//Note : alternatively h01 could have been coded with the <a> element separated out :
//var h01  := TElement.Create('h2', h0,  'h2');
//var h011 := TElement.Create('a', h01, 'a', 'WebSite Logo');
Not very exciting as this simply is a 1 on 1 conversion of each html line into a pascal line
It does work though, executing this program gives an exact replica of the target website
Note that the compiled main.js file is less then 10kB, which helps in keeping latency as low as possible
The other benefit of course is that these elements can be generated under program control
So for instance the following snippet reads data from a cloudbased mysql database and generates p-elements correspondingly

var sql_statement : String;
var encodedstr : String;
var FHttp := JXMLHttpRequest.Create;
  asm @encodedstr = encodeURIComponent('SELECT user FROM testtable limit 50'); end;
  sql_statement := "sql_statement="+encodedstr;
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;
  For var i := 0 to DBRows - 1 do begin
    TElement.Create('p', sd0, 'p', 'Mauris sit amet mauris a arcu eleifend ultricies eget ut dolor.');
    TElement.Create('p', sd0, 'author', smscursor.smsrows[i].user);
The next question then is to see if this can be componentised.
For example a typical radiobutton component could look like

unit JRadio;
uses W3C.HTML5, W3C.DOM, W3C.CSS, JElement;
  TRadio = class(TElement)
    constructor Create(element: String; parent: TElement; className: String; innerHTML : String); virtual;
    constructor Create; overload;
{ TRadio }
constructor TRadio.Create(element: String; parent: TElement; className: String; innerHTML : String);
var r0 := TElement.Create('fieldset', parent, 'legacy-form-row');
  var r01 := TElement.Create('legend', r0,  'legend', 'Type of Talk');
  var r02 := TElement.Create('input', r0, 'input');
  r02.setAttribute('id', 'talk-type-1');
  r02.setAttribute('name', 'talk-type');
  r02.setAttribute('type', 'radio');
  r02.setAttribute('value', 'main-stage');
  var r03 := TElement.Create('label', r0, 'radio-label', 'Main Stage');
  r03.setAttribute('for', 'talk-type-main');
  var r04 := TElement.Create('input', r0, 'input');
  r04.setAttribute('id', 'talk-type-2');
  r04.setAttribute('name', 'talk-type');
  r04.setAttribute('type', 'radio');
  r04.setAttribute('value', 'workshop');
  var r05 := TElement.Create('label', r0, 'radio-label', 'Work Stage');
  r05.setAttribute('for', 'talk-type-2');
constructor TRadio.Create;
var r0 := TElement.Create('fieldset', nil, 'legacy-form-row');
  var r01 := .......  //same as above
which can simply be invoked as
Of course some event handlers and property getters/setters need to be added to make this a usable component.
So far so good,
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...