Detect word click

I want to display a long sentence (in some component) and detect which word was clicked.
Even better if I could also highlight each word as hovered.

Hi @paul.k.pallaghy and welcome to the forum,

This will touch on a lot of anvil concepts.

Here’s one way you could do it.

For a component with a click handler it would make sense to use a Link component for each word.
To display the sentence as a sentence you’ll probably want a flow panel.

class Form1(Form1Template):

  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)

    text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eleifend feugiat blandit. Aenean ornare lacus nec imperdiet consequat. Vivamus vitae sem convallis, volutpat nisl vitae, posuere massa. Quisque vel orci.'
    # Any code you write here will run when the form opens.
    
    for t in text.split():
      l = Link(text=t, foreground='black', role='word')
      self.flow_panel_1.add_component(l)
      l.set_event_handler('click', self.text_click)
      
  def text_click(self, **event_args):
    print(event_args['sender'].text)

For the hover I used the role above and added the following to theme.css


.anvil-role-word:hover {
    font-weight:bold;
}

Here’s the clone

https://anvil.works/build#clone:UANGCJ7SCTVK4CB5=FUDLFHU447FWAHXJDUY3S6RZ

7 Likes

How can I detect control or command key during word click (I want to select multiple words sometimes)?

Off the top of my head I can’t think that there is a native way to detect the command key. You can use anvil.js to use native javascript events and detect the cmd key.

editing the solution above

import anvil.js

    for t in text.split():
      l = Link(text=t, foreground='black', role='word')
      dom_node = anvil.js.get_dom_node(l)
      dom_node.addEventListener('click', get_click_handler(l))
      self.flow_panel_1.add_component(l)
    
def get_click_handler(link):
  def js_handler(e):
    print('cmd key:', e.metaKey, link.text)
  return js_handler

I’ve adjusted the clone link above so you can see it in action.

2 Likes

@stucork
How do I get the command key state BACK INTO the Form1 class text handlers I’m using?
I’ve tried but failed . .

I want to return the command key state to the Form1 class.
As a global or anyway I can SOMEHOW access it from within the Form1 class where I am tracking the current list of sentences.

Really nice solution BTW.

Instead of defining get_click_handler as a function in the namespace, you could define it as a method in the class definition for the form - then the first argument is self.

That way you have a reference to self in the js_handler function.

1 Like

Thnx, I’d just assumed it wouldn’t work there . .

1 Like

@stucork
I’ve made some mods but I don’t get the print in def js_handler(e) occuring.
Only my text_click handler.

    import anvil.js

    class Form1(Form1Template):

      # Globals
      sentences = []
      parent = ''
      
      def __init__(self, **properties):
        # Set Form properties and Data Bindings.
        self.init_components(**properties)

      def get_click_handler(self, link):
        def js_handler(e):
          key = e.metaKey
          print('cmd key:', e.metaKey, link.text)
        return
      
      def display_parent(self):
        if self.parent in self.sentences:
            self.sentences.remove(self.parent)
        if len(self.sentences) > 0:
          self.parent = self.sentences[0]
          self.flow_panel_1.clear()
          for t in self.parent.split():
            l = Link(text=t, foreground='black', role='word')
            self.flow_panel_1.add_component(l)
            dom_node = anvil.js.get_dom_node(l)
            dom_node.addEventListener('click', self.get_click_handler(l))
            l.set_event_handler('click', self.text_click)             
        else:
          self.flow_panel_1.clear()     
      
      def text_click(self, **event_args):

You’re not returning the js_handler

1 Like

This mix of Anvil and js is like black magic to me . .
Thnx. Works now of course!

2 Likes

@paul.k.pallaghy an update on this post - we’ve added support for keys in anvil click event

def link_click(self, **event_args):
    print(event_args['keys']['meta'])

That should work for Link and Button components and should make the implementation above slightly easier.