Jump to content
Sign in to follow this  
lynkfs

HTML programming

Recommended Posts

A bit of a weird topic name for a product which elevates Object Pascal using javascript.
I could have named it 'Web Components' (as I did a while ago) or maybe better 'Api Programming'.

There are a number of organisations which look after the web api's. W3C is the most known one, but there are others looking after specific parts (WhatWG, Khronos etc.). What they have in common is that they publish the web api's they're looking after in a specific formal format (WebIDL).

Smart has transformed these specifications in corresponding pascal classes, contained in the APIs directory in the RTL. These classes basically map directly onto functions and data available in the browser itself, and using them is sort of similar to for instance incorporating Microsoft Office functions in a Delphi program (although technically very different from using COM).

The RTL uses some of these api's under the hood, this post is about a mini-rtl if you like consisting of just 1 component.

I use this approach a lot for non-form based projects, single-page-apps (or multiple) and websites.

Demo of a semi-static SPA 

The inheritance chain of the DOM looks like
- EventTarget
  - Node
    - Element
      - HTMLElement

with all the various html elements underneath : HTMLDivElement for a <div>, HTMLAnchorElement for a <a> etc.
The code below wraps the HTMLElement, but allows its constructor to create any of the specialised sub-elements.

unit JElement;

interface

uses W3C.HTML5, W3C.DOM, W3C.CSS;

type
  THTMLElement = class
  private
    FHTMLElement: JHTMLElement;
  public
    constructor Create(element: String; parent: THTMLElement; className: String; innerHTML : String); 
end;

implementation

{ THTMLElement }

constructor THTMLElement.Create(element: String; parent: THTMLElement; className: String; innerHTML : String);
begin
  // cache element and set innerHTML and className
  FHTMLElement := JHTMLElement(Document.createElement(element));
  FHTMLElement.innerHTML := innerHTML;
  FHTMLElement.className := ClassName;

  If parent = nil
    then document.body.appendChild(FHTMLElement)
    else parent.FHTMLElement.appendchild(FHTMLElement);

end;

HTMLElements have as specifiers 'attributes' and 'properties'. Properties are any of the values in the 'style' attribute : in the html expression style="left=10px; color=white;" href="#" both 'left' and 'color' are properties, and both 'style' and 'href' are attributes.
So we need to add the setters for these parameters :

Procedure THTMLElement.SetProperty(s1: String; S2: String);
begin
  var FElementStyle := JElementCSSInlineStyle(FHTMLElement).style;
  FElementStyle.setProperty(S1, S2);
end;

Procedure THTMLElement.SetAttribute(S1: String; S2: String);
begin
  FHTMLElement.setAttribute(S1, S2);
end;

The first part of the demo app is an image, which fills the complete viewport on any device and orientation, a slightly darker tinted bar on top, and a button in the bar linking to an email form further down.

This header can be constructed as per below :

unit JHeader;

interface

uses JHTMLElement, smartcl.system;

type
  THeader = class(THTMLElement)
  public
    constructor Create(props: Variant);
end;

implementation

{ THeader }

constructor THeader.Create(props: Variant);
begin
  //hero image
  var hdr0  := THTMLElement.Create('div', nil, 'div');
      hdr0.setProperty('width', '100%');
      hdr0.setProperty('height', '100%');
      hdr0.setProperty('min-height', '100vh');
      hdr0.setProperty('background-image','url('+props['header-img']+')');
      hdr0.setProperty('background-size','cover');

    //top bar 100px
    var hdr11  := THTMLElement.Create('div', hdr0, 'div');
        hdr11.setProperty('width', '100%');
        hdr11.setProperty('height', '100px');
        hdr11.setProperty('background-color','rgb(21,21,21,0.2)');

      //contact button
      var hdr21  := THTMLElement.Create('a', hdr11, 'div', 'Contact');
          hdr21.SetBounds(20,30,75,35);
          hdr21.setProperty('color', 'white');
          hdr21.SetAttribute('type', 'button');
          hdr21.setAttribute('href', '#contact');
          hdr21.SetProperty('background-color', 'rgb(21,21,21,0.2)');

which can be instantiated as in (with a variable for the image)

//THeader
  props['header-img'] := 'assets/img/blueprint.jpg';
  THeader.Create(props);

and which on execution time resolves in

<div class="div" style="width: 100%; height: 100%; min-height: 100vh; background-image: url(http://127.0.0.1:8090/assets/img/blueprint.jpg); background-size: cover;">
  <div class="div" style="width: 100%; height: 100px;">
    <a class="div" type="button" href="#contact" style="visibility: visible; display: inline-block; position: absolute; overflow: auto; left: 20px; top: 30px; width: 75px; height: 35px; color: white;">
      Contact
    </a>
  </div>
</div>


Hence the title of this post : HTML programming.

The advantage of this approach is that once there are a number of these multi-purpose constructs like THeader available, making up another webpage is as easy as providing values for constructor parameters and stringing them together.

At some stage I created the constructs listed here
They need to be updated and streamlined a bit.
  

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
Sign in to follow this  

×