How a button get selectedText and replace it with something?

Hi,
Sorry for the newbie questions, but I’ve searched the forum and the sparse documentation for a long time and haven’t found any answers.

I’m trying to create an add-on for editing card by adding media created by some text and external programs (this part is ok). I figured out how to add a button to the edit toolbar with aqt.gui_hooks.editor_did_init_buttons.append, but I didn’t find out how to get the selected text and replace it with something by clicking on the button I created. I couldn’t find a way to get selectedText() with the editor parameter given to my callback function or something else. Then, there is the problem with replacing the selected text with what my program has generated.

I don’t understand how I could use JavaScript for that purpose (if it’s possible only with python, I would prefer it, because it feels messy to me to mix two paradigms for the same use).

Thank you!
Luca

Depending on your goal, maybe something like this will work for you as a pure Python solution (not tested):

text = editor.web.selectedText()
editor.note[editor.currentField] = text.replace('foo', 'bar')
editor.loadNoteKeepingFocus()

I think you have to use JavaScript if you want an accurate solution that actually only modifies selected text. Anki mostly only provides a wrap(before, after) JS function for wrapping selected text. You’ll need to get your hands dirty with DOM manipulations with JS for most cases.

Thank you, @abdo, for your answer.

The first line worked (I should have worked it out on my own :sweat_smile:), and I get the selected text, but the second line doesn’t work. I think I didn’t set up correctly PyCahrm (or it’s because I don’t use the typing system of python, I’m not familiar with it), because I couldn’t always get the clues when I write something (if it’s at top level I get the clues, but ).

I tried to debug a little, but it seems that editor.note[editor.currentField] gives an error, even without the assignation with text.replace(... , ...). I couldn’t fine a way to “stringify” a note to see if it’s what it is supposed to be (Note.data seems to be empty, and there isn’t a method like toString() or getThing()).

Otherwise, editor.currentField seems to work: it gives 0 for the first field and 1 for the second, so I reckon it’s right.

Below is the debugging info:

Anki 2.1.66 (70506aeb) Python 3.9.15 Qt 6.5.0 PyQt 6.5.0
Platform: Linux-5.15.0-88-generic-x86_64-with-glibc2.35
Flags: frz=True ao=True sv=2
Add-ons, last update check: 2023-11-14 08:08:47
Greffons possiblement impliqués : <U+2068>lilypond-anki<U+2069>

Caught exception:
Traceback (most recent call last):
  File "anki.notes", line 154, in _field_index
KeyError: 0

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "aqt.webview", line 46, in cmd
  File "aqt.webview", line 153, in _onCmd
  File "aqt.webview", line 665, in _onBridgeCmd
  File "aqt.editor", line 477, in onBridgeCmd
  File "/home/luca/.local/share/Anki2/addons21/lilypond-anki/__init__.py", line 101, in your_python_function
    encf=editor.note[editor.currentField]
  File "anki.notes", line 159, in __getitem__
  File "anki.notes", line 156, in _field_index
KeyError: 0

The problem is maybe because Note don’t accept integers as keys… If I do showInfo(str(editor.note.keys())), I get "['Recto', 'Verso']". I’ll try with that…

1 Like

I found the way :smiley:. In your example code, the second line should be:

editor.note[editor.note.keys()[editor.currentField]]=text.replace('foo', 'bar')

I think, I don’t need to mess with DOM, because my add-on needs only to replace text with [sound] or (and it seems that the way you showed me it’s like dealing with .innerHTMLin JavaScript).

Thank you for your help @abdo !

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.