AnvilAugment: Hover, Focus, Key Bindings Dependency

Availble as part of anvil_extras:

 from anvil_extras import augment

Or as a standalone dependency, which mirrors anvil_extras
Both available as Third Party Dependencies:

  • anvil_extras - C6ZZPAPN4YYF5NVJ
  • AnvilAugment - 223FMU5UYH5T2XSA

Documentation: Augmentation — Anvil Extras documentation


EDIT: updated version below

or at github


I thought I’d make a little add_on to allow anvil components to have events like hover and focus so that you can then run python code

Inspired by the questions:

Adding hover and focus effects

Can't set focus on button

onHover event for Label?

dV2zTilbmC

13 Likes

You keep making such awesome add ons!

1 Like

Nice!

Update

I’ve updated this dependency - The new dependency and example can be found here:
(i’ve left the original post in place in case someone stumbles across this and prefers the first version)

https://anvil.works/build#clone:36T6RN2OO6KLBGV7=4LZ35S57ODPL7ORIUJ2AH6KY

Changes:

  • you can now use standard anvil event handler function syntax (namely **event_args)
  • keydown, keyup etc supported
  • hover takes 1 function - distinguish between mouseenter and mouseleave from the event_args
  • works with BlankPanel forms and not just HTML Forms :smile:
  • two provided functions - augment.add_event, augment.set_event_handler
  • any ‘augmented’ component will also have a trigger method

Revised examples:

from AnvilAugment import augment
augment.set_event_handler(self.link, 'hover', self.link_hover)
# equivalent to
# augment.set_event_handler(self.link, 'mouseenter', self.link_hover)
# augment.set_event_handler(self.link, 'mouseleave', self.link_hover)
# or 
# augment.set_event_handler(self.link, 'mouseenter mouseleave', self.link_hover)

def link_hover(self, **event_args):
  if 'enter' in event_args['event_type']:
    self.link.text = 'hover'
  else: 
    self.link.text = 'hover_out'

#================================================
# augment.set_event_handler equivalent to
augment.add_event(self.button, 'focus')
self.button.set_event_handler('focus', self.button_focus)

def button_focus(self, **event_args):
 self.button.text = 'Focus'
 self.button.role =  'secondary-color'


need a trigger method?

# 'augment' the component by adding any event... 
augment.add_event(self.textbox, 'select')
# augment.add_event(self.textbox, 'custom')
# augment.add_event(self.textbox, '')

def button_click(self, **event_args):
  self.textbox.trigger('select')

Keydown example

augment.set_event_handler(self.text_box, 'keydown', self.text_box_keydown)

def text_box_keydown(self, **event_args):
  key_code = event_args.get('key_code')
  key = event_args.get('key')
  if key_code == 13:
    print(key, key_code)

advanced feature - you can prevent default behaviour of an event by returning a value in the event handler function - example use case

augment.set_event_handler(self.text_area, 'keydown', self.text_area_keydown)

def text_area_keydown(self, **event_args):
  key = event_args.get('key')
  if key.lower() == 'enter':
    # prevent the standard enter new line behaviour
    # prevent default
    return True

If you end up using this dependency and want any extra features feel free to ask!
I’ve only implemented what i’ve needed for a project I was working on…

8 Likes

Just using this for the first time. Nice work!

Is there a way to capture any keypress regardless of what component has focus? (I have a form with no text boxes - just some buttons and a canvas - and I’d like to bind some keys to the buttons).

At the moment, I’m using a text box that’s ‘invisible’ because of its colour and I move the focus to that whenever anything happens so I can then catch key presses - but it’s a nasty hack!

Good question - I don’t think so - it will only works where the the component supports the jquery event. (I don’t think a general form would support a keypress event out of the box).

For a document level event - something like this would work I think

Native Libraries

<script>
$(document).on('keypress', (e) => {
  anvil.call($('.content'), 'keypress', e.key)
})
</script>

Client Side

  def keypress(self, key):
    if key is 'a':
      # do a thing

Here’s a clone

https://anvil.works/build#clone:CUK6QTBXGX6ARR4T=BGUXMPH3FDHMMAOZIFJQK637

1 Like

Yep - that does the job nicely. Thank you!

I had to use ‘keydown’ instead of ‘keypress’ because I wanted to detect the arrow keys and I still need the ‘hidden’ text box so can call its .focus() method in the form’s .show method, but this is much cleaner.

1 Like

I must be failing to do something quite basic, when I try to run this example with augment as a dependency, I get this:

image

Is that from the first posted links? I’m actually not maintaining that version. I’ll amend the first post to be in line with the 4th post, which I am maintaining, and should work just fine.

Context: the original version was directly accessing skulpt objects, and skulpt has had some changes since I posted it - hence the error you’re seeing. The updated version uses anvil.js.window exclusively and is all written in python :grinning_face_with_smiling_eyes:

2 Likes

On that note I’ve just updated the dependency to fix a bug that @owen.campbell found.

There are a couple of ways to update this dependency.
Since the dependency is one module - you could go to the source code in Github and copy the code from this file into your version:

If you have a git workflow you can also do the following (the first time):

  1. clone your version of the app locally
  2. git remote add upstream git@github.com:s-cork/AnvilAugment.git
  3. git fetch upstream
  4. git reset --hard upstream/master
  5. git push origin master -f

subsequent times:

  1. git pull upstream
  2. git push -f origin master
2 Likes

A post was split to a new topic: KeyError sender

PSA: This add-on is now a part of Anvil Extras, and the most up-to-date version can be found there.

1 Like

2 posts were split to a new topic: Augment - remove event handler

A post was split to a new topic: Augment - keypress event