Field with placeholder/hint text

Anything beyond the basics in using the LiveCode language. Share your handlers, functions and magic here.

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

stam
Posts: 2686
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Field with placeholder/hint text

Post by stam » Fri Nov 24, 2023 4:41 pm

The solution to the first question
Make the field clickable by setting lockText to true on exiting field
Then on mouseDown reverse this and set the selection :)

Just by manipulating lockText, the cursor appears at the start of the text if showing the placeholder text, or hilites the entire text if it contains a real string. I knew this must be possible... Phew!

(there is the even more minor issue that if the user has entered the field and and then decides to click and hold the mouse the same minor issue again occurs - but I'll let that one go ;) )

Code: Select all

on mouseDown
    set the lockText of me to false
    if fieldIsEmpty() then
        select before me
    else
        select the text of me
    end if
end mouseDown

Code: Select all

on exitField
    setTextStyle
    if fieldIsEmpty() then set the text of me to the uPlaceholderText of me
    set the lockText of me to true
end exitField

on closeField
    exitField  -- thanks for the tip Paul :)
end closeField


The remaining question (to which is suspect the answer to will be 'No"):

if the field text is changed in script is it possible to react automatically to this? (i.e. if the field is showing it's placeholder text and I assign a string to this, how can I get it to trigger an update without firing a second command - in my case exitField - to do this?)

textChanged won't fire if text set by script
setProp is only available for custom properties
Is there way of trapping the "set text" message so a handler can update automatically? (again no biggie if not possible, will just send exitField to the field - but would have been nice to fully encapsulate all functionality in a single standard command).

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4003
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: Field with placeholder/hint text

Post by bn » Fri Nov 24, 2023 11:26 pm

if the field text is changed in script is it possible to react automatically to this? (i.e. if the field is showing it's placeholder text and I assign a string to this, how can I get it to trigger an update without firing a second command - in my case exitField - to do this?)
If I understand you correctly sometimes you want to set the text by script. As it is now the field is locked.

A locked field gets a "focusIn" message if the text of the locked field is changed by script AND the text is selected by script. (You can remove the selection from the same script right after having selected it. See "description" in the dictionary for "openField")

Also the "focusIn" messages is sent when you tab into the locked field.
(Does tabbing into your locked input field work currently?)

Kind regards
Bernd

stam
Posts: 2686
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Field with placeholder/hint text

Post by stam » Mon Nov 27, 2023 12:00 am

bn wrote:
Fri Nov 24, 2023 11:26 pm
A locked field gets a "focusIn" message if the text of the locked field is changed by script AND the text is selected by script. (You can remove the selection from the same script right after having selected it. See "description" in the dictionary for "openField")

Also the "focusIn" messages is sent when you tab into the locked field.
(Does tabbing into your locked input field work currently?)

Kind regards
Bernd
Hi Bernd - actually I use focusIn to manage tabbing in:

Code: Select all

on focusIn
    set the lockText of me to false
    setTextStyle
    if fieldIsEmpty() then
        select before me
    else
        select the text of me
    end if
end focusIn
So tabbing into a field isn't an issue. And setting the text of a locked field isn't an issue either (lockText seems to work only for user input).

But set the text of field in itself doesn't trigger reformatting of the placeholder style to normal style, as textChanged doesn't fire.

I was really asking if there is an equivalent to on textChanged for when a field text is changed by script. I'm guessing 'no' ;)

Not a biggie by any means (if I set the text and then send exitField to the field it does the job). But if I come back to this in 2 years, I have to remember to include send "exitField" after setting the text programmatically, which I probably won't ;)
Would be nice if the field could handle that automatically on setting text...

Stam

stam
Posts: 2686
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Field with placeholder/hint text

Post by stam » Mon Nov 27, 2023 3:33 am

I've simplified the code keeping it to basic properties.

The lockText fix above fixed the issue on initial selection of the field when it wasn't in focus - however when the field was in focus, the user could still (temporarily) select the placeholder text.

I now set the lockText in setTextStyle which prevents the user from selecting the placeholder text at any point - but this has the side effect of hiding the cursor when the placeholderText is showing (lockText = true) - however the field still receives focus, text can be typed or pasted in and can be set by script, all of which function normally.
On balance I think that would be more correct so I've rolled with that.

It doesn't seem possible to both have the cursor showing and to prevent the user from selecting the hint text (the obviously alternative is to hide the placeholder/hint text when the user opens the field, but as above my requirement is that this is visible whenever the field is empty, regardless of if the user has selected the field or not)

I've updated the controller stack (which allows setting properties visually): https://github.com/stam66/skPlaceholderField

The full field script is below:

Code: Select all

/////////////// PROPERTIES ///////////////
###  Placeholder properties ###
// uPlaceholderText
getProp uPlaceholderText
    if the uPlaceholderText of me is empty then set the uPlaceholderText of me to "Placeholder text"
    return the uPlaceholderText of me
end uPlaceholderText

setProp uPlaceholderText pText
    set the uPlaceholderText of me to pText
    updateVisualControls
end uPlaceholderText

// uPlaceholderTextStyle
getProp uPlaceholderTextStyle
    if the uPlaceholderTextStyle of me is empty then set the uPlaceholderTextStyle of me to "Italic"
    return the uPlaceholderTextStyle of me
end uPlaceholderTextStyle

setProp uPlaceholderTextStyle pStyle
    set the uPlaceholderTextStyle of me to pStyle
    updateVisualControls
end uPlaceholderTextStyle

// uPlaceholderTextColor
getProp uPlaceholderTextColor
    if the uPlaceholderTextColor of me is empty then set the uPlaceholderTextColor of me to "190,190,190"
    return the uPlaceholderTextColor of me
end uPlaceholderTextColor

setProp uPlaceholderTextColor pColor
    set the uPlaceholderTextColor of me to pColor
    updateVisualControls
end uPlaceholderTextColor
###  END Placeholder properties ###

###  Field Properties ###
// uNormalTextStyle
getProp uNormalTextStyle
    if the uNormalTextStyle of me is empty then set the uNormalTextStyle of me to "Plain"
    return the uNormalTextStyle of me
end uNormalTextStyle

setProp uNormalTextStyle pStyle
    set the uNormalTextStyle of me to pStyle
    updateVisualControls
end uNormalTextStyle

// uNormalTextColor
getProp uNormalTextColor
    if the uNormalTextColor of me is empty then set the uNormalTextColor of me to 66,66,66
    return the uNormalTextColor of me
end uNormalTextColor

setProp uNormalTextColor pColor
    set the uNormalTextColor of me to pColor
    updateVisualControls
end uNormalTextColor

// uScaleFactor
getProp uScaleFactor
    if the uScaleFactor of me is empty then set the uScaleFactor of me to 0.4
    return the uScaleFactor of me
end uScaleFactor

setProp uScaleFactor pFactor
    set the uScaleFactor of me to pFactor
    updateVisualControls
end uScaleFactor
###  END Field Properties ###
/////////////  END PROPERTIES  //////////////


///////////////  ACTIONS  ////////////////
private command setTextStyle
    if fieldIsEmpty() then
        set the textStyle of me to the uPlaceholderTextStyle of me
        set the textColor of me to the uPlaceholderTextColor of me
        set the lockText of me to true
    else
        set the textStyle of me to the uNormalTextStyle of me
        set the textColor of me to the uNormalTextColor of me
        set the lockText of me to false
    end if
end setTextStyle

private command updateVisualControls
    setTextStyle
    set the textSize of me to the height of me * the uScaleFactor of me
    centerTextVertically
end updateVisualControls

command resetProps
    set the uPlaceholderText of me to empty
    set the uPlaceholderTextStyle of me to empty
    set the uPlaceholderTextColor of me to empty
    set the uNormalTextStyle of me to empty
    set the uNormalTextColor of me to empty
    set the uScaleFactor of me to empty
    initField
end resetProps
///////////////  END ACTIONS  ///////////////


///////////////  EVENTS /////////////// 
on focusIn
    setTextStyle
    if fieldIsEmpty() then
        select before me
    else
        select the text of me
    end if
end focusIn

on keyDown pKeyName
    set the lockText of me to false
    if the text of me = the uPlaceholderText of me then set the text of me to empty
    pass keydown
end keyDown

on textChanged
    if fieldIsEmpty() then set the text of me to the uPlaceholderText of me
    setTextStyle
end textChanged

on openField
    initField
    setTextStyle
end openField

on exitField
    if fieldIsEmpty() then set the text of me to the uPlaceholderText of me
    setTextStyle
    select empty
    set the lockText of me to true
end exitField

on selectionChanged
    if fieldIsEmpty() then select before me
end selectionChanged

on closeField
    exitField
end closeField

on resizeControl
    updateVisualControls
end resizeControl

on pasteKey // SUSPEND DEV TOOLS IF TESTING IN IDE - works in standalone
    if fieldIsEmpty() then set the text of me to empty
    set the lockText of me to false
    pass pasteKey
end pasteKey
///////////////  END EVENTS /////////////// 


/////////////// HELPERS ///////////////
private function fieldIsEmpty
    return (the text of me is empty or the text of me is the uPlaceholderText of me)
end fieldIsEmpty

# PURPOSE: ensure custom properties are set and accessible in IDE
private command initField
    set the uPlaceholderText of me to the uPlaceholderText of me
    set the uPlaceholderTextStyle of me to the uPlaceholderTextStyle of me
    set the uPlaceholderTextColor of me to the uPlaceholderTextColor of me
    set the uNormalTextStyle of me to the uNormalTextStyle of me
    set the uNormalTextColor of me to the uNormalTextColor of me
    set the uScaleFactor of me to the uScaleFactor of me
end initField

# CENTER VERTICALLY -- based on Bernd's algorithm
private command centerTextVertically
    local tTextHeight, tFieldY, tFormatRect, tFormatheight, tFormatHalfHeight, tCurrFormatTop, tCenterField_To_TopTextDiff
    put the effective textHeight of me into tTextHeight
    put item 2 of the loc of me into tfieldY
    put the formattedRect of line 1 to - 1 of me into tFormatRect
    put item 4 of tFormatRect - item 2 of tFormatRect into tFormatHeight
    put tFormatHeight div 2 into tFormatHalfHeight
    put item 2 of tFormatRect into tCurrFormatTop
    put tfieldY - tCurrFormatTop into tCenterField_To_TopTextDiff
    set the topMargin of me to the topMargin of me + tCenterField_To_TopTextDiff - tFormatHalfHeight
    if the formattedHeight of me > the height of me then 
        set the topMargin of me to 8
    end if 
    exitfield
end centerTextVertically
/////////////// END HELPERS ///////////////

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4003
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: Field with placeholder/hint text

Post by bn » Mon Nov 27, 2023 11:14 am

Hi Stam,

Thanks for putting the new version up on GitHub.

Your interface requirements are somewhat special and I have apparently a hard time getting my head around them.

However I tested your latest version and still find it needs some additions for the way I would like to use the "Field".

I changed handler "focusIn" and added a mouseDown handler. If that does not conform to you interface requirements just forget them.

Code: Select all

on focusIn
   if the mouseLoc is within the rect of me then exit focusIn
   setTextStyle
   set the lockText of me to false
   if fieldIsEmpty() then
      select before me
   else
      select the text of me
   end if
end focusIn

on mouseDown
   if fieldIsEmpty() then
      select before me
   else
      select the text of me
   end if
   set the lockText of me to false
end mouseDown
Kind regards
Bernd

Edit: added the test for mouseLoc within the rect of me to "focusIn" to give "mouseDown" a chance to select before.
If this does not cut it I give up...

stam
Posts: 2686
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Field with placeholder/hint text

Post by stam » Mon Nov 27, 2023 7:11 pm

Thanks Bernd,

I had already tried this / something similar. As soon as lockText is set to false, the placeholder text is selectable which I'm trying to avoid because it looks lame (but has no actual effect because of the selectionChanged handler, which fires on releasing the mouse).

I suspect it's not possible to both have an editable field with cursor showing AND stop the user from hiliting the placeholder text.

Having said that I should clarify that the cursor is only hidden when the placeholder text is shown - otherwise entering/pasting in normal text, it behaves like a normal text entry field.

So to keep the placeholder text showing on entering field and before typing (what I'm trying to achieve), the options are:
1. Revert to allowing temporary selection of placeholder text (similar to your code) - slightly lame that I can hilite the placeholder, but cursor is normal.
2. Follow my most recent code which where everything works exactly as expected but the cursor is hidden when showing placeholder text
3. Use a 2nd field that overlaps with the main field (ie move from a single control to a group).

If I'm honest, I'll probably move to choice 3, as while my current version works perfectly in all intended functions, the lack of a blinking cursor is oddly disconcerting... even though everything now works to spec otherwise.

S.

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4003
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: Field with placeholder/hint text

Post by bn » Mon Nov 27, 2023 7:37 pm

Hi Stam,
3. Use a 2nd field that overlaps with the main field (ie move from a single control to a group).
That sounds like a good idea to me.

Kind regards
Bernd

stam
Posts: 2686
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Field with placeholder/hint text

Post by stam » Tue Nov 28, 2023 11:27 am

bn wrote:
Mon Nov 27, 2023 7:37 pm
That sounds like a good idea to me.
I guess the proof is in the pudding - it was crazy easy to get it working perfectly as a group.

This also allows extra features like animations (eg the placeholder text swiping quickly to the right or bottom, or becoming a label on top of the field instead of in it.

In truth this was always likely to end up being a group, as I was going to add a feature for bulletpoints obscuring text...

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4003
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: Field with placeholder/hint text

Post by bn » Tue Nov 28, 2023 11:45 am

Hi Stam,

While looking at your Placeholder field I did a very rough proof of principle using a label field in a group.

For what it is worth...

Kind regards
Bernd

PS: not offering a blinking cursor to indicate a field ready for input is in my opinion not an option, whatever the interface design.
Attachments
PlaceHolderText2.livecode.zip
(1.42 KiB) Downloaded 54 times

stam
Posts: 2686
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Field with placeholder/hint text

Post by stam » Tue Nov 28, 2023 1:38 pm

Thanks Bernd,

I already did that with a fast dissolve effect that looks pleasing to the eye. I also cater for same field displaying different Label text and Placeholder text as the latter may be more verbose (for example, the label may be "Username" but the placeholder text may be "Enter your username").

I considered this because I'd seen examples of this in UI/UX websites and it looked cool.
The only problem then is that some fields may have a label and some not, which is almost as bad as not having a blinking cursor.

A different animation that seems to work well is to have the placeholder label move in time. With a short delay (as it's a blocking effect) there is no appreciable delay in typing. For example:

Code: Select all

move field "label" of me to 3 * item 1 of the loc of field "text" of me, item 2 of the loc of field "text" of me in 100 milliseconds
has the effect of the placeholder text zooming out of the group to the right when typing, which is probably a better animation that moving it to the label position (for consistency).

In the end I felt all this was a bit too flashy and I've just gone back to show/hiding the placeholder ;)
I'll probably implement both these animation options as options for whoever uses this, but default to no animation. Who knows, maybe I'll need the flashy stuff in the future.

I'm currently implementing a text-obscuring function (for passwords), so that it will be an option to set this to be a password field or not - and I've realised I can do it better than I'd done before (I'm now using unicode 0x2022 instead of imageSource and an image of a bulletpoint, which is what I'd used in a much older version of this I'd put on Sample Stacks - hence won't need an image now \o/). I've also included an iOS-style "show the letter for a very short interval then obscure with bulletpoint" functionality. Coming along well...

I'll post a further version as I go along...
Thanks as always
Stam

stam
Posts: 2686
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Field with placeholder/hint text

Post by stam » Sun Dec 03, 2023 4:16 pm

Just in way of update, for anyone that may have use of this, I've updated this to a group and have included functions to optionally use this as a password field. Optionally, a subtle animation can be applied to the placeholder text.
skPlaceholderFieldGroup.jpg

I've updated the controller stack so it automatically detects when an skPlaceholderFieldGroup is selected to enable modifying properties of existing groups - if none selected, it defaults to the prototype field with the stack (which can be copied into a topLevel stack). Works very well as a plugin.
controller.jpg

More detail and download from my GitHub: https://github.com/stam66/skPlaceholderField
(MIT licence)

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4003
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: Field with placeholder/hint text

Post by bn » Tue Dec 05, 2023 9:04 pm

Stam,

thank your making version 1.3 of your placeholder field available. Blinking cursor is back. Hoorah.

In its default it works very well:
Tabbing, clicking, deleting text etc.
It also works well if you choose "animatatedPlaceholder" which is a nice touch.

Some problems appear (recursions) if you change the delays for the animation of the placeholder if animatedPlaceholder is turned on.
The same goes for changing the bullet delay for the passwordfield.

Trying to set the placeholder text takes the focus away from the field after each key entered, necessitating a manual selection of the text and entering another key and so on.
Same for the "normal" text.

That seems to result from handler
command setProperties which has a focus on nothing.

handler selectionChanged in script of group "skPlaceholderFields" emits what is probably a debugging message to the message box "-->" tCharCount

Especially the recursions are bothersome. Might be a setProp recursion because properties are set after setting a property via setProp. I did not figure it out because the whole thing is pretty complex now. And you can get it into a state where only a couple of resets (often needs 2) brings everything back.

I think the good news is that in the basic configuration the thing works.

Kind regards
Bernd

stam
Posts: 2686
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Field with placeholder/hint text

Post by stam » Wed Dec 06, 2023 5:48 am

Thanks as always Bernd,
bn wrote:
Tue Dec 05, 2023 9:04 pm
Some problems appear (recursions) if you change the delays for the animation of the placeholder if animatedPlaceholder is turned on.
The same goes for changing the bullet delay for the passwordfield.
Thank you for spotting this - I didn't test enough it seems. It's not true recursion (hence doesn't trigger the recursion warning) but my code was a bit sloppy inasmuch as it didn't check if the state needed to change and kept changing this every time it was being checked causing repeated visual changes.
I've added a check and it now showHidePlaceholder only acts if the state needs to change and this has got rid of this 'visual' recursion.

bn wrote:
Tue Dec 05, 2023 9:04 pm
Trying to set the placeholder text takes the focus away from the field after each key entered, necessitating a manual selection of the text and entering another key and so on.
Same for the "normal" text.
This must be a regression bug which I've now fixed. The code was needed to update both the text and appearance of the field in question (i.e. if changing the placeholder text in an empty field, what was the placeholder would suddenly show as normal text).

Regarding the 'normal' text field, I used this to keep an eye on what text is being stored when obscured when used as a password field; it's not meant for user entry - the group is there for that - so I've removed this. Thank you also for spotting the debug statement that was putting text in the msgBox.


Actually my biggest issue was the animation - while I really like the move animation, it's a blocking action and can completely screw up text entry no matter how short the duration (so that the 2nd typed char appears first, or if you type quickly the 3rd char appears before the second which is before the first etc). I can't see a way around this.

I found that 'unlock with visual effect' is not blocking and can be used freely. The animation isn't as nice but it works, so I've used a wipe right/left animation in place of move right/left and seems like the next best thing. It's just a pity 'move' is a blocking action!

I dont' know if "I'm doing it wrong" or if I'm misunderstanding the utility, but

Code: Select all

lock Screen for visual effect in rect (the rect of me)
hide field "placeholder" of me
unlock screen with visual effect "push" very fast
does not seem to limit the visual effect to the rect in question but to the card, so other than 'wipe', effects like push, scroll etc are unsuitable as they make it look like the whole group moves across the card instead of just the placeholder text within the group.

I'll update in coming days and hopefully test properly this time!
Many thanks for your patience ;)

stam
Posts: 2686
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: Field with placeholder/hint text

Post by stam » Mon Dec 11, 2023 4:58 pm

In way of update, this has been improved significantly - in no small part to due Bernd's excellent input on the move command's other form ('without waiting' -- who knew!?!?!). By default placeholder text is now animated and works with obscured password text as well.

The controller stack/plugin has been improved significantly as well.
skPlaceholderField.jpg
The field also emits a 'fieldAction' message that can be managed at parent level (eg to check username/password combos etc).

More detail and download on GitHub:
https://github.com/stam66/skPlaceholderField

Stam

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4003
Joined: Sun Jan 07, 2007 9:12 pm
Location: Bochum, Germany

Re: Field with placeholder/hint text

Post by bn » Tue Dec 12, 2023 12:32 pm

Hi Stam,

Version 1.4 is a very nice improvement. I like that you can now place the Placeholder group on a stack and configure it via the controller stack.
Also of course the animation but I am a bit biased here.

For those not familiar with gitHub:
Follow Stam's link, look for 'skPlaceholderField.livecode' and right-click to download.

Kind regards
Bernd

Post Reply

Return to “Talking LiveCode”