Jump to content
Sign in to follow this  
lynkfs@gmail.com

web site-page-app building 5

Recommended Posts

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.

 

HTML

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

Etc.

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.

 

CSS

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);
begin
  FElement := JHTMLElement(Document.createElement('div'));
  SetProperty('background-color','white');
  SetProperty('border','1px solid black');
...


 

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

 



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


 

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);
begin
//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");
    browserapi.document.head.appendChild(style);
  end;
 
  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);
end;


 

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

Share this post


Link to post
Share on other sites
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);
    sv.SetLocation('-33.8568','151.2153');

 

 

and unit code

 


unit JStreetview;
 
interface
 
uses
  JElement;
 
type
  TStreetView = class(TElement)
  public
    constructor Create(parent: TElement);
    procedure SetLocation(s1,s2: string);
    ifr : TElement;
  end;
 
implementation
 
{ TPanel }
 
Constructor TStreetView.Create(parent: TElement);
begin
  inherited Create('div', parent);
 
  ifr := TElement.Create('iframe', self);
  ifr.SetCSS('width','600px');
  ifr.SetCSS('height','600px');
  ifr.SetCSS('frameBorder','0px');
  ifr.SetCSS('padding','1em');
  ifr.SetCSS('border-radius','.25em');
  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)');
 
end;
 
Procedure TStreetView.SetLocation(s1,s2: String);
begin
  var s : string := 'https://www.google.com/maps/embed/v1/streetview?location=' +
                    s1 + ',' + s2 + '&key=' + <API KEY>;
 
  ifr.SetAttribute('src',s);
end;
 
end.

 

 

And a rewritten Polymer demo, a creditcard form

 

with the simple invocation of :

 


TCreditCard.Create(nil, '300');

.

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  

×