Another small update: The theme settings are now also exposed as window.prodigy.theme and the {{theme}} variable within the HTML template. This includes the default colours and settings, and/or any modifications made by the user via the customTheme config.
I thought this could be pretty nice, because it’ll let you style custom interfaces more consistently, and keep all theming variables in one place. You can also add your own properties to the custom theme, e.g. "customTheme": {"customColor": "blue"}.
Example use case 1: in HTML
<mark style="background: {{theme.bgHighlight}}">{{label}}</mark>
I want to implement something to help me be quicker for text classification. Simply, I just want to highlight certain keywords so I can visually jump to them for the classification of a long sentence or multiple sentences.
I tried generating the HTML in my data file, but the data is shown as-is (no rendering). I then added a column for the word to highlight, so I could modify it after the page loaded using a little Javascript, but turns out templates can’t be used inside the javascript config.
Any suggestions?
(I realize however that maybe I can chop my data records up a little more, that might be the way I’ll go, but curious about what else could be done here without changing the data processing part.)
@hadsed If you just want to highlight certain words, you might not even need a custom template. You could simply add a "spans" property to the annotation tasks (just like when you’re annotating named entities). For example:
The only thing that’s important here is that you need to know the character offsets of your keywords – but those should be pretty easy to generate. If a text classification task has spans assigned, Prodigy will highlight those inline. You could even add a "label" to the span.
That said, if you do want to use a custom template for more flexibility, make sure to set 'view_id': 'html' in your (custom) recipe, and add the HTML as the task’s "html" key. You can still add a "text" key that contains the plain text – this makes sense if you’re annotating with a model in the loop, or later want to use the annotations to train a model. The text classifier for example will then be trained on the "text" (not the HTML containing your custom markup).
Btw, the custom JavaScript examples I outlined in this thread already work! They’re just not documented yet, because they’re very experimental. So if you have a look at my examples above, you can see how to add custom JavaScript (via the recipe’s "javascript" config setting) and how to access the current task data and UI actions from within your script.
Thanks – I'll double check that. I might have already fixed this internally, actually. In the meantime, stopping the key event from propagating in the textbox should probably work. Kinda like this:
Btw, quick update on the thread topic: Custom JS for all interfaces and a global CSS setting is already implemented and will be shipped with the next version
Hi I am trying to implement your solution to user inputs for a machine translation annotation task. While I was able to successfully create my own user input button while following your template, I am struggling to get Prodigy to save the user inputted text into the final exported annotations. Any advice would be appreciated.
@jlanday Could you share your current script? The update method is exposed as window.prodigy.update. It takes an object of properties and will update the current task by performing a shallow update. So when you want to update the task (e.g. on the input’s onchange event or when the user clicks a button), you can do something like this:
This is cool stuff and works really well I guess as soon as you use a html_template, you can only use the html interface? Like is there an obvious way to combine this with presets like the choice interface or NER annotations in the text?
@SofieVL Yay, that's nice to hear! And yes, the html_template is currently limited to the html – although I think you can kinda trick the app into using it to render the content in interfaces like choice or classification by passing it an empty "html" property in the task.
Custom CSS and JavaScript are now supported for all interfaces, so you can always do something like this and append elements to the annotation card:
However it looks like you can't actually type in the box. Because as soon as your mouse goes there and selects the box, the radio button is selected instead, and focus moves aways from the text box.
Ah yeah, the choice options weren't really designed to have interactive content in them. So you probbly want to just add the field at the bottom below the options (instead of actually making it an option itself).
Hi @ines,
my window.prodigy.content is pointing to the wrong content when using view_id blocks.
My html_template consist of buttons and the js_templates holds the onClick functions. The OnClick are supposed to highlight some words. I planned on doing this by appending Spans to window.prodigy.content.spans and then updating it. However, it is not showing on the text visualization of the ner_manual block. May I know where I was wrong?
Thanks!
Hi! The ner_manual interface currently keeps its own copy of the spans – calling update does update the task content, but it doesn't necessarily trigger a re-render of a built-in component. I do want to change this, though, since use cases like the one you describe are pretty cool. It's just not implemented yet.
Hi @ines,
Thanks! I understand!
As a temporary workaround, may I ask if there is any way for me to trigger React to re-render? Perhaps using a pseudo state change?
Ah, good idea! It's hacky, but you could make it think that it's receiving a new task by updating the _task_hash of the current task. Just tested it and the following works for me:
Just make sure to reset it to its original value again – otherwise, you'll end up with bad task hashes in your dataset (which impacts what Prodigy considers duplicates etc.). Maybe also try it with a test dataset first to check that there are no unintended side-effects on the client.
I am able to confirm that the custom javascript is correctly logging the selected label, but I'm not sure how to actually set the selected label in prodigy, since I don't see any examples of updating the selected label in the window.prodigy interface.
The .update() call in my custom JS was a wild guess, and sure enough, it didn't work (it's just using the first item in the dropdown, which is NO_LABEL in the below screenshot):
So, in summary, my question is: Is it possible to update the label from a custom HTML interface like this?
Thanks in advance!
-Luc
P.S. The reason I'm using a custom dropdown is that the default dropdown for a list of labels provided by the --dropdown prodigy option is not flexible enough for our image_manual use case, which requires using several <optgroup>'s in the select bar.
The window.prodigy.update function will update the current task dictionary with whatever data you pass in. So in your code, you're adding the top-level property "label" to the dictionary – but I think that's not what you want, right? You'd want the label to be added to the entry in the "spans" that was just added.