Archive
HTML5 Attributes, learn how to trigger conditional styling with Smart Mobile Studio
Im not sure if I have written about Attributes before; Probably, because they are so awesome to work with. But today I’m going to show you something that makes it even more awesome, bordering on unbelievable.
What are HTML attributes again?
Before we dig into the juicy stuff, let’s talk about attributes. For those that dont know much about HTML or CSS, here is a quick and dirty overview. A lot of people use Smart Mobile Studio because they dont know CSS or HTML beyond the basics (or even because they dont want to learn it, quite a few cant stand JavaScript and CSS). Well that is not a problem.
Note-1: While not a vital prerequisite, I do suggest you buy a good book on JavaScript, HTML and CSS. If you are serious about using web technology (like node.js on the server) your Smart skills will benefit greatly by knowing how things work “under the hood” so to speak. You will make better Smart Mobile Studio applications and you will understand the RTL at a deeper level than the average user.
OK, back to attributes. You know how HTML tags have parameters right? For example, a link to another webpage looks like this:
<a href="http://blablabla">This is a link</a>
Note-2: I dont have time to teach you HTML from scratch, so if you have no idea what the “A” tag is then please google it.
Focus here is not on the “a” part, but rather on the “href” parameter. That is actually not a parameter but a tag-attribute (which must not be confused with a tag-property btw).
Back in the day attributes used to be exclusive; Meaning that if you tried to set some attribute value the tag didnt support – nothing would happen. The browser would just ignore it and the information would be deleted.
Around HTML4 all of that changed. Suddenly we got the freedom to declare our own attributes, regardless of tag. The only catch is that the attribute name must be prefixed with “data-“. Which makes sense because the browser needs to tell the difference between valid attributes, junk and intrinsic (supported) attributes.
Storing information outside the pascal instance
When you create a visual control, the control internally creates a DOM element (or tag object, same thing) that it manages. Most visual controls in our RTL manages a DIV element because that is just a square block that can be easily molded and shaped into whatever you like.
But, when you create a Smart Pascal class you dont just get a DOM element in return. You get a Smart Pascal object instance. This is the same as Delphi and Lazarus: a class is a blueprint of an object. You dont create classes you create instances.
The same thing happens when you use Smart Pascal: the JSVM (JavaScript virtual machine) delivers a JavaScript object instance – and that is what your code operates on. When you create a visual class instance, that in turn will create a DOM element and manage that until you release the Smart Pascal instance.
Storing information in a class is easy. It’s one of the fundamental aspects of object oriented programming and there really isnt that much to say about that. But what if you need to store information in a control you dont own? Perhaps you have installed a package you bought, or that a friend shared with you – and you cant change the class (or perhaps dont want to change the class). What then?
This is where the attribute object comes to the rescue. Because now you can store information directly in the DOM element rather than altering the class itself (!)
That is so powerful I dont even know where to start, because you can write libraries that can do amazing things without fields or demanding the user to change their controls (and in some cases, avoid forcing the user to inherit from a particular custom-control).
A real-life example
Our special effect unit, SmartCL.Effects.pas, uses this technique to keep track of effect state. When you execute an effect on a control a busy-flag is written as an attribute to the managed DOM object. And when the effect is finished the busy-flag is reset.
If you execute 10 effects on a control, it’s this busy flag that stops all of them running at the same time (which would cause havoc). While this attribute is set any queued effects wait their turn.
This would be impossible to achieve without declaring a busy property, or doing some form of stacking behind the scene; both of them expensive codewise. But with attributes it’s a piece of cake.
And now for the juicy parts
Now that you know what attributes do and how awesome they are, what can possibly make them even more awesome? In short: “CSS attribute pseudo selectors” (phew, that is a mouthful isnt it!).
So what the heck is a pseudo selector? Again its a long story, so im just going to call it “states”. It allows you to define styles that should be activated when a particular state occurs. The most typical state is the :active state. When you press a button the DOM element is said to be active. This allows us to write CSS styles that are applied when you press the button (like changing the background, border or font-color).
But did you know you can also define styles that react to attribute changes?
Just stop and think about this for a moment:
- You can define your own attributes
- You can read, write and check for attributes
- Attributes are part of the DOM element, not the JS instance
- You can define CSS that apply when an element has an attribute
- You can define CSS that apply if an attribute has a particular value
If you are still wondering what the heck this is good for, imagine the following:
With this, you can do the following:
- Write an event-handler for TW3Application.OnOrientationChange (an event that fires when the user rotate the mobile device horizontally or vertically).
- Store the orientation as a attribute value
- Define CSS especially for the orientation attribute values
The browser will automatically notice the attribute change and apply the corresponding CSS. This is probably one of the coolest CSS features ever.
Other things that come to mind:
- You can write CSS that colors the rows in a grid or listbox based on the data-type the row contains. So an integer can have a different background from a float, boolean or string. And all of it can be automated with no code required on your part. You just need to write the CSS rule once and that’s it.
- You can use attributes it to trigger pre-defined animations. In fact, you could pre define 100 different animations, and based on the attribute-name you can trigger the correct one. Again all of it can be neatly implemented as CSS.
Let’s make a button that triggers a style
While simple, the following example should serve as a good example. It’s easy to build on and not to complex. Let’s start with the CSS:
button[data-funky="this rocks"] { background: none; background-color: #FF00FF; font-color: #FFFFFF; font-size: 22px; font-weight: bold; }
The CSS above should be easy to understand. First we define the name of the DOM element, which in my case is a button. Next we define the attribute, and like mentioned it has to be prefxed with “data-” (our attributes class does this automatically in the RTL, so you dont need to prefix it when you code). And finally we define the value the style should trigger on, “this rocks”.
Right, let’s write some code:
var MyButton := TW3Button.Create(self); MyButton.SetBounds(100,280, 100, 44); MyButton.Caption := 'Click me!'; MyButton.OnClick := procedure (Sender: TObject) begin var Text := MyButton.Attributes.Read('funky'); if Text <> 'this rocks' then MyButton.Attributes.Write('funky','this rocks') else MyButton.Attributes.Write('funky',''); end;
The code is very simple, we read the value of the attribute and then we do a toggle based on the content. So when you click the button it will just toggle the trigger value.
This is how the button looks before we click it:
And when we click the button the attribute is written to, and it’s automatically styled:
How cool is that! The things you can automate with this is almost endless. It is a huge boon for anyone writing mobile applications with Smart Mobile Studio and it makes what would otherwise be a difficult task ridiculously easy.
Cheers!
You must be logged in to post a comment.