Jump to content

web site-page-app building 5

Recommended Posts

  • Moderators
43,550 choices to make


The underlying motivation to start this thread was the realisation that there is a massive amount of functionality built into the modern browser. 

Play video, calculate font-size depending on viewport dimensions using vanilla css, automatically add amounts in table cells without using javascript, store user-data in elements - the list is almost endless.

Much of this functionality is not natively exposed in smart pascal.


So somewhat belatedly I had a bit of a better look at the web development basics.

The 3 basic pillars are of course html, css and javascript. 

Html describes the structure of a page/web-app, css is used for styling and js defines the business logic.



There is a large number of HTML elements specified: <a>, <input>, <header> etc. 

All in all there are currently 108 elements defined by the W3C, not including 26 depreciated ones which may still be supported. 


Each element can have a modifying attribute, like <a> has the 'href' attribute. 

Some attributes are valid for only one element, but most can be used on more than one.

'Height' for instance is an attribute which relates to <canvas>, <embed>, <iframe>, <img>, <input>, <object> and <video>

while 'href' relates to <a>, <area>, <base> and <link>. 


Currently there are 115 attributes.


On average each attribute relates to some 3 html-elements, 

which gives 3 * 115 = say 350 possible element / attribute combinations.



To make life even more complicated, there are some 400+ css properties, like 'background-color', 'border-width' etc.

And more are coming on a frequent basis. 

The latest addition is the css-grid with lots of new properties, 

The css-grid was implemented in FireFox last week and apparently comes to Chrome this week.


The w3c specs state that in theory each and every css-property is applicable to all html-elements.


That gives by my reckoning a maximum of 350 + (108 * 400) = 43,550 permutations

Quite a bit to choose from


In practice it is not as bad as that of course.

Some combinations are just not valid, are ignored by browsers and should never be used.

Also the W3C has specified default values for html-elements and browsers have an internal style-sheet with default property values.


Nevertheless there still is a dizzying array of choices to be made in vanilla web-development.


So the question is if life can be made a bit easier.



1) Combine the most sensible properties and attributes in discrete components

Sort of producing a mini lightweight rtl.


Lets say we want to have a TPanel with a white background and a black 1px border.

The code for this could be a variation on the TElement class : 


Constructor TPanel.Create(parent: TElement);
  FElement := JHTMLElement(Document.createElement('div'));
  SetProperty('border','1px solid black');


or alternatively this TPanel class can be derived from TElement with setters and getters for defined properties


  TPanel = class(TElement)
    procedure SetMyinnerHTML(Value : String);
    procedure SetMyColor(Value: String);
    constructor Create(parent: TElement); virtual;
    property Text : string write SetMyinnerHTML;
    property Color : String write SetMyColor;


It would certainly be doable to do produce enough light-weight components for normal webpage or form development. 



2) Abolish CSS style sheets

Style sheets define style properties per element type or per attribute or even for all elements (*)

I find them hard to read.

I like to abolish them altogether and instead define styles per element.


Styles of course can be set by using SetProperty (see previous posts), whuich works perfectly. 

However it fails miserably in the case of css pseudo-classes.


A pseudo class is a state which gives rise to a different behaviour.

A classic example (hover) which speaks for itself is

a:hover {
  color: green;

There is just no way this can be generated using smart or js, it only works in a stylesheet.


If that is the case, the solution then is to dynamically insert these rules into a stylesheet.

The snippet below checks to see whether there is a stylesheet at all and if not creates an empty one.

and then inserts the specific rule


Procedure TElement.SetCSS(pseudo, prop, value: string);
//sheet.addRule('#OBJ5:hover','background-color: #4CAF50;');
//sheet.insertRule('#OBJ5:hover { color: green }', 0);
  var s = browserapi.document.styleSheets;
  if s.length = 0 then begin
    var style := browserapi.document.createElement("STYLE");
  var s0,s1 : string;
  s0 := '#' + FElement.id; //'#OBJ5';
  s1 := prop + ': ' + value;
//  sheet.addRule(s0+':'+ pseudo,s1);
  browserapi.document.styleSheets[0].insertRule(s0 + ':' + pseudo + ' { ' + s1 +'}', 0);


Note :all browsers are fine with using addRule, except FireFox

Luckily insertRule is an alternative which works in all browsers (FireFox, Chrome, Edge and even IE)


And now we can abolish SetProperty completely and use this method to dynamically set css rules for any element.


So what do we have now

Basically this enables the creation of a very lightweight rtl based on TElement rather then TObject.


The project here features just two of such components : TPanel and TButton

For fun I've added the ability to size text (font-size) dynamically according to screen-width. 

Resize your screen and you'll see it happen. Not bad for just a single css statement.

I've also added a couple of ways to bind events to these elements


So creating and styling elements can be done by leveraging native browser functionality, by using html and css only - no pascal necessary for these purposes.

Which leaves js to where it belongs - business logic.


 code here, by the way
Link to post
Share on other sites
  • Moderators
This brings it in the domain of custom elements

Google has a set of libraries called Polymer to enable development of custom elements, Microsoft has X-TAG and Mozilla has Bricks


Now we have a close alternative to these

See a rewritten X-TAG custom element demo here,

a google streetview custom element with the simple invocation of


var sv := new TStreetView(nil);



and unit code


unit JStreetview;
  TStreetView = class(TElement)
    constructor Create(parent: TElement);
    procedure SetLocation(s1,s2: string);
    ifr : TElement;
{ TPanel }
Constructor TStreetView.Create(parent: TElement);
  inherited Create('div', parent);
  ifr := TElement.Create('iframe', self);
  ifr.SetCSS('box-shadow','0 2px 2px 0 rgba(0, 0, 0, 0.14),' +
                      '0 1px 5px 0 rgba(0, 0, 0, 0.12),' +
                      '0 3px 1px -2px rgba(0, 0, 0, 0.2)');
Procedure TStreetView.SetLocation(s1,s2: String);
  var s : string := 'https://www.google.com/maps/embed/v1/streetview?location=' +
                    s1 + ',' + s2 + '&key=' + <API KEY>;



And a rewritten Polymer demo, a creditcard form


with the simple invocation of :


TCreditCard.Create(nil, '300');


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...