Jump to content
Sign in to follow this  
DavidRM

Enable User Selection of Text

Recommended Posts

THis is what I have:

type
  TPBTScrollItem = class(TW3CustomControl)
  protected
    FItemText: string;
    procedure InitializeItem; virtual;
    procedure SetItemText(aValue: string);
  public
    function CreationFlags: TW3CreationFlags; override;
    procedure UpdateDisplay; virtual;
    property ItemText: string read FItemText write SetItemText;
  end;


// TPBTScrollItem
procedure TPBTScrollItem.InitializeItem;
begin
  SetContentSelectionMode(tsmAuto);
end;

procedure TPBTScrollItem.SetItemText(aValue: string);
begin
  if aValue <> FItemText then
  begin
    FItemText := aValue;
    UpdateDisplay;
  end;
end;

function TPBTScrollItem.CreationFlags: TW3CreationFlags;
begin
  inherited;
  Include(Result, cfAllowSelection);
end;

procedure TPBTScrollItem.UpdateDisplay;
begin
  InnerHTML := Format('<span>%s</span>', [TString.EncodeTags(FItemText)]);
end;

 

But the user can never actually click-and-drag to select the content.

Why?

And: How do I get around whatever silly reason is the "Why?"

Thanks!

-David

Share this post


Link to post
Share on other sites

A quick test :

procedure TForm1.InitializeForm;
begin
  inherited;
  // this is a good place to initialize components

  Panel1 := TW3Panel.Create(self);
  Panel1.SetBounds(20,20,300,300);
  Panel1.InnerHTML := 'text to select';

  //select either one of the following lines :

  //Panel1.SetContentSelectionMode(tsmText);                  //text not selectable
  //Panel1.Handle.style['user-select'] := 'text';             //text not selectable
  //Panel1.Handle.style['-webkit-user-select'] := 'text';     //text selectable

end;

Executing in the IDE the only way to select the panel text is the third line

Executing from file : Chrome accepts line 2 or 3, Edge and FireFox accept line 3 only. Internally these browsers then do their own optimisation Edge uses the -ms prefix, FireFox the -moz prefix and in Chrome the -webkit prefix is omitted altogether.

As to the why : not sure. You've probably seen an old post from Jon about this subject. 

Looks like there is still some inconsistency somewhere.

Share this post


Link to post
Share on other sites

@DavidRM This works, if you don't use a span inside InnerHTML. I marked the changed lines.

  TPBTScrollItem = class(TW3CustomControl)
  protected
    FItemText: string;
    procedure InitializeObject; override; //<<<<<<<<<<<<<<<<<<<<
    procedure SetItemText(aValue: string);
  public
    function CreationFlags: TW3CreationFlags; override;
    procedure UpdateDisplay; virtual;
    property ItemText: string read FItemText write SetItemText;
  end;


procedure TPBTScrollItem.InitializeObject; //<<<<<<<
begin
  inherited; //<<<<<<<
  SetContentSelectionMode(tsmAuto);
end;

procedure TPBTScrollItem.SetItemText(aValue: string);
begin
  if aValue <> FItemText then
  begin
    FItemText := aValue;
    UpdateDisplay;
  end;
end;

function TPBTScrollItem.CreationFlags: TW3CreationFlags;
begin
  inherited;
  Include(Result, cfAllowSelection);
end;

procedure TPBTScrollItem.UpdateDisplay;
begin
  InnerHTML := TString.EncodeTags(FItemText); //<<<<<<<
end;

Edit: You may also want to use tmsText instead of tmsAuto.

Share this post


Link to post
Share on other sites

@lynkfs In your example, the call to SetContentSelectionMode does not work as the RTL prevents it:

procedure TW3TagObj.SetContentSelectionMode(const NewMode: TW3ContentSelectionMode);
begin
  if (cfAllowSelection in CreationFlags) then
  begin
    var LValue := _Selection_Mode_Names[NewMode];
    Handle.style['user-select'] := LValue;
    Handle.style['-moz-user-select'] := LValue;
    Handle.style['-webkit-user-select'] := LValue;
    Handle.style['-ms-user-select'] := LValue;
    Handle.style["-khtml-user-select"] := LValue;
  end;
end;

Pretty much all the components are created without cfAllowSelection, including TW3Panel and TW3DivHtmlElement. To be honest, I don't know why the RTL should make switching this on so hard. IMHO, we could remove that flag check from SetContentSelectionMode as that'd not magically let everything be selectable. What are your thoughts?

Share this post


Link to post
Share on other sites
1 hour ago, lynkfs said:

yep, this flag check looks like overkill.

Is there a reason to create components default non-selectable ? Text on most if not all websites / apps is default selectable

I don't know. Maybe because text in Delphi apps is not selectable as default?

Anyway, I'd propose changing this so, that we don't prevent ContentSelectionMode even if cfAllowSelections is missing. And if cfAllowSelection is in creation flags, we could set ContentSelectionMode automatically to tmsAuto. What do you guys think?

Share this post


Link to post
Share on other sites

@jarto That did it, yup. Thanks! And, yes, I had to use tmsText.

Also, I was able to get the span to work by doing this:

  InnerHTML := Format('<span style="color:%s;user-select:text;-moz-user-select:text;-webkit-user-select:text;-ms-user-select:text;-khtml-user-select:text"><b>%s</b>: %s</span>',
    [ColorToWebStr(FChatColor), TString.EncodeTags(FChatHeader), TString.EncodeTags(FChatText)]);

Not sure why the <span> didn't just inherit the item's user-select, though.

Thanks!

-David

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  

×