April 20, 2024

A standard feature of many web sites is to use colour to indicate bad entries needing user attention.

With EWB you can set the font colour to red if you dislike a value, but that doesn’t show up if the field is empty, and the convention is more often to use background colour to convey this information.

eg.

procedure TForm1.edYearChange(Sender: TObject);
begin
  if strtointDef( edYear.Text, -1 ) < 2000 then
     edYear.Font.Color := clRed
  else
     edYear.Font.Color := clWhite
end;

But sometimes you have other needs such as

Consider this sample, a Year field which shows up as pinkish unless the year is valid, which we define as 2000 or later.

24a

Standard EWB doesn’t let you create such a coloured entry as there is no background attribute for TEdits.

We’re going to add exactly that feature in this blog post.

First, create a edYear TEdit with an OnChange event pointing to

procedure TForm1.edYearChange(Sender: TObject);
begin
  if strtointDef( edYear.Text, -1 ) < 2000 then
     SetBackground( edYear, 'rgb(255,200,200)') // rose
  else
     SetBackground( edYear, 'rgb(255,255,255)' ); // white
end;

Now we just need to write the code to implement the SetBackground function.

The first thing to note is that TEdits point to an HTML DIV or container which holds the actual HTML Edit. So edYear points to a container whose first and only child is an actual Edit, which is what we will be modifying.

In the case of a TMultiLineEdit, there is no DIV. So we just use the first child if and only if it exists.

Next thing worth considering is that we need to set the TEdit’s ID field so we can use getElementByClientID(). This is done with TEdit’s ClientID = …​ syntax.

However, note that if we have two EWB forms open with identically named TEdit’s (edYear), the browser won’t know which of the edYear values will be referenced. So we append a unique integer to the ClientID. With JavaScript’s 52 bit integers, we won’t run out of one anytime soon.

Finally, once we have the EDIT HTMLelement, we need to set the style.backgroundColour portion to an RGB() valued colour.

With all those notes, here is the resulting function.

var
  increasingInt : integer = 1;  // used to give a unique ClientID

procedure SetBackground( c : TControl ; cl : string );
var
  domele : TDomElement;
  nam : string;  // our temporary name
begin
   // get a fresh integer
   inc( increasingInt );

   // come up with a unique name
   nam := c.name + '_'+ IntToStr(increasingInt);

   // give it an ID so getElementById will work
   c.ClientID := nam;

   domele := window.document.getElementById( nam );
   if not Assigned( domele ) then
      Showmessage('Could not find element ' + c.name + ' ('+nam+')' )
   else begin
      // if Element points to a DIV, we want the first child....
      if Assigned( domele.childNodes[0] ) then
          domele := variant(domele.childNodes[0]);
      // and set the style.backgroundColor....
      THTMLElement(domele).style.backgroundColor := cl;

   end;
end;

To have a yellow TMultiLineEdit background, call the following from the form’s OnShow event handler.

  // set the note to yellow
  SetBackground(multilineedit1, 'rgb(255,255,0 )');
Tip
The TEdit’s cell background will be reset if it changes focus. One way of dealing with that is to have edYearChange( nil) called from a TTimer event. TMultiLineEdit does not change when swithcing focus.