Jump to content


Photo

website building

website web page

  • Please log in to reply
No replies to this topic

#1 Nico Wouterse

Nico Wouterse
  • Members
  • 175 posts
  • LocationAustralia

Posted 14 February 2017 - 04:45 PM

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;
 
interface
 
uses W3C.HTML5, W3C.DOM, W3C.CSS;
 
type
  TElement = class
  private
    FElement: JHTMLElement;
    function AsNode() : JNode;
  public
    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);
end;
 
implementation
 
{ TElement }
 
constructor TElement.Create(element: String; parent: TElement; className: String; innerHTML : String);
begin
  // 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);
end;
 
constructor TElement.Create(element: String; parent: TElement; className: String);
begin
  // 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);
end;
 
function TElement.AsNode() : JNode;
begin
  Result := FElement;
end;
 
Procedure TElement.SetProperty(s1: String; S2: String);
begin
  var FElementStyle := JElementCSSInlineStyle(FElement).style;
  FElementStyle.setProperty(S1, S2);
end;
 
Procedure TElement.SetAttribute(S1: String; S2: String);
begin
  FElement.setAttribute(S1, S2);
end;
 
end.
 
 
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
/*
  <header>
    <h2><a href="#">Website Logo</a></h2>
      <nav>
        <li><a href="#">Home</a></li>
        <li><a href="#">Products</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contacts</a></li>
      </nav>
  </header>
*/
//
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');
//h011.setAttribute('href','#');
etc.
 
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;
  FHttp.open("POST","http://www.xxxxxxxx/smsdbmysql.php");
  FHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
  asm @encodedstr = encodeURIComponent('SELECT user FROM testtable limit 50'); 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;
  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);
  end;
end;
 
The next question then is to see if this can be componentised.
 
For example a typical radiobutton component could look like

unit JRadio;
 
interface
 
uses W3C.HTML5, W3C.DOM, W3C.CSS, JElement;
 
type
  TRadio = class(TElement)
  public
    constructor Create(element: String; parent: TElement; className: String; innerHTML : String); virtual;
    constructor Create; overload;
end;
 
implementation
 
{ TRadio }
 
constructor TRadio.Create(element: String; parent: TElement; className: String; innerHTML : String);
begin
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');
end;
 
constructor TRadio.Create;
begin
var r0 := TElement.Create('fieldset', nil, 'legacy-form-row');
  var r01 := .......  //same as above
  etc.
end;
 
 
end.
 
which can simply be invoked as
TRadio.Create; 
 
Of course some event handlers and property getters/setters need to be added to make this a usable component.
 
So far so good,
.

  • Jørn E. Angeltveit, ielite and Igor Savkic like this

Nico Wouterse





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

IPB Skin By Virteq