Cracker Classes and Solving Placeholders
April 11, 2023
Elevate Web Builder, like most other Object Pascal implementations, allows the use of cracker classes and other features which can expose normally hidden class variables and methods to the clever programmer. These can be used to extend EWB’s functionality very easily without having to go through the hassle of defining a totally new class and all that entails.
The Problem: Placeholders It’s nice to have a placeholder in an Edit field. A placeholder is text which is displayed before the user puts data into the Edit field, so it’s a form of user-friendly and space-saving prompt.
It’s entirely possible and reasonable to define a new TEdit descendant class which im,plements the placeholder strategy, and in fact, I did that and include it in my Nice Toolkit (https://erickengelke.com/nice). But for this example I’m going to show how to implement placeholders with just a few short lines of code that can be used in your programs.
Background
EWB actually has implemented placeholders, but it doesn’t expose the functionality, I guess that was a design choice back in the day. I won’t use the built-in functionality to do this, instead showing how you manipulate the HTML directly instead.
Also, every browser except the ugly tired Internet Explorer implements placeholders correctly. Of course IE does not. So do not be discouraged when IE acts erratically – it does that all the time.
To tell the browser to use placeholders, we have to access the actual Edit element and set the Placeholder in the TDomElement class attribute to the desired placeholder text value.
Typical Solution: If you are implementing a placeholder with the standard recommended solution – a new class, you would write a setplaceholder function which gets the underlying Edit element of a TEdit and then set the attribute “Placeholder” with the setAttribute method.
The code looks something like
Procedure TExtendedEdit.setplaceholder( s : string );
var
Inele : TInputElement;
domele : TDomElement;
begin
inele := self.GetInputElement;
domele := TDomELement(variant(inele.DOMElement));
domele.setattribute('placeholder', s);
end;
But then you have to do several steps to declare your new class, add it to the Library, etc.
Note, GetInputElement is a protected function, it cannot be accessed by user code, only by the internal methods within this class and descendant classes.
Cracker Solution
Here’s a simpler, quick and dirty solution to achieve similar results in just a few lines of code.
We will use two facts:
- Descendant classes have access to protected methods
- EWB allows companion code in the same file access to protected methods of classes
First, we declare a temporary class we use to crack TEdit, we’ll call it TPlaceholderEdit. It doesn’t need any member attributes or methods.
type
// This is a cracker class, we don't need to define any class varaiables or methods, just need to
// reference this class to access internal funcitons in a different TEdit
TPlaceHolderEdit = class( TEdit )
end;
Now we create a TForm with two TEdits and a Tbutton, and declare the TForm’s OnShow handler to call AddPlaceholder( e : TEdit ; s : string); which will add the placeholder s to the specified TEdit.
procedure TForm1.Form1Show(Sender: TObject);
var
s : string;
begin
// add some placeholders
AddPlaceHolder( edit1, 'please enter name' );
AddPlaceHolder( edit2, 'please enter address' );
// set focus on the button so above placeholders
// are displayed in Buggy IE which does not display
// placeholders correctly
Button1.Setfocus;
end;
Finally, the AddPlaceholder() function.
procedure AddPlaceHolder( e : Tedit ; s : string );
var
newedit : TPlaceHolderEdit;
inele : TInputElement;
domele : TDomElement;
begin
// need TInputElement, but you cannot call
// e.GetInputElement like EWB internal functions
// do so use a local TPlaceHolderEdit "cracker"
// class to access that function
newedit := TPlaceHOlderEdit( e );
inele := newedit.GetInputElement;
domele := TDomELement(variant(inele.DOMElement));
domele.setattribute('placeholder', s);
end;
Voila, the code creates beautiful placeholders. They work strangely in IE which is the default browser in EWB, but for all REAL browsers they work perfectly. sample project.