TextInput widget - make event oninput available to user #539
Replies: 2 comments 7 replies
-
I have an Even if it does, I've noticed that you have some warnings in places that, IIRC, |
Beta Was this translation helpful? Give feedback.
-
Hello @johnperry-math , Thanks to your effort. I reworked your ExtendedTextInput this way to keep the previous logic and to add the oninput functionality. I tested it and it seems to work for single and multiline. class TextInput(Widget, _MixinTextualWidget):
"""Editable multiline/single_line text area widget. You can set the content by means of the function set_text or
retrieve its content with get_text.
"""
@property
@editor_attribute_decorator("WidgetSpecific",'''Defines the maximum text content length.''', int, {'possible_values': '', 'min': 0, 'max': 10000, 'default': 0, 'step': 1})
def attr_maxlength(self): return self.attributes.get('maxlength', '0')
@attr_maxlength.setter
def attr_maxlength(self, value): self.attributes['maxlength'] = str(value)
@attr_maxlength.deleter
def attr_maxlength(self): del self.attributes['maxlength']
def __init__(self, single_line=True, hint='', *args, **kwargs):
"""
Args:
single_line (bool): Determines if the TextInput have to be single_line. A multiline TextInput have a gripper
that allows the resize.
hint (str): Sets a hint using the html placeholder attribute.
kwargs: See Widget.__init__()
"""
super(TextInput, self).__init__(*args, **kwargs)
self.type = 'textarea'
self.single_line = single_line
self.attributes['single_line'] = 'false'
if single_line:
self.style['resize'] = 'none'
self.attributes['rows'] = '1'
self.attributes['single_line'] = 'true'
self.set_value('')
if hint:
self.attributes['placeholder'] = hint
self.attributes['autocomplete'] = 'off'
self.attributes[Widget.EVENT_ONCHANGE] = \
"var params={};params['new_value']=document.getElementById('%(emitter_identifier)s').value;" \
"remi.sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);"% \
{'emitter_identifier': str(self.identifier), 'event_name': Widget.EVENT_ONCHANGE}
def set_value(self, text):
"""Sets the text content.
Args:
text (str): The string content that have to be appended as standard child identified by the key 'text'
"""
if self.single_line:
text = text.replace('\n', '')
self.set_text(text)
def get_value(self):
"""
Returns:
str: The text content of the TextInput. You can set the text content with set_text(text).
"""
return self.get_text()
@decorate_set_on_listener("(self, emitter, new_value)")
@decorate_event_js("""
var is_single_line = (parseInt(document.getElementById('%(emitter_identifier)s').getAttribute('rows')) < 2);
var elem = document.getElementById('%(emitter_identifier)s');
var enter_pressed = (elem.value.indexOf('\\n') > -1);
if(enter_pressed && is_single_line){
elem.value = elem.value.split('\\n').join('');
}
var params={};
params['new_value']=elem.value;
params['enter_pressed']=enter_pressed;
remi.sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);
""")
def oninput(self, new_value, enter_pressed):
enter_pressed = enter_pressed in ('True', 'true')
if self.single_line and enter_pressed:
self.onchange(new_value)
return (new_value,)
@decorate_set_on_listener("(self, emitter, new_value)")
@decorate_event_js("""
var params={};
params['new_value']=document.getElementById('%(emitter_identifier)s').value;
remi.sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);""")
def onchange(self, new_value):
"""Called when the user changes the TextInput content.
With single_line=True it fires in case of focus lost and Enter key pressed.
With single_line=False it fires at each key released.
Args:
new_value (str): the new string content of the TextInput.
"""
self.disable_update()
self.set_value(new_value)
self.enable_update()
return (new_value, )
@decorate_set_on_listener("(self, emitter, new_value, keycode)")
@decorate_event_js("""var elem=document.getElementById('%(emitter_identifier)s');
var params={};params['new_value']=elem.value;params['keycode']=(event.which||event.keyCode);
remi.sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);""")
def onkeyup(self, new_value, keycode):
"""Called when user types and releases a key into the TextInput
Note: This event can't be registered together with Widget.onchange.
Args:
new_value (str): the new string content of the TextInput
keycode (str): the numeric char code
"""
return (new_value, keycode)
@decorate_set_on_listener("(self, emitter, new_value, keycode)")
@decorate_event_js("""var elem=document.getElementById('%(emitter_identifier)s');
var params={};params['new_value']=elem.value;params['keycode']=(event.which||event.keyCode);
remi.sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);""")
def onkeydown(self, new_value, keycode):
"""Called when the user types a key into the TextInput.
Note: This event can't be registered together with Widget.onchange.
Args:
new_value (str): the new string content of the TextInput.
keycode (str): the numeric char code
"""
return (new_value, keycode) Have a wonderful day, |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Actually the oninput event is internally used to manage ENTER key confirmation, this is related to single-line / multiline editing.
We should be able to achieve the same behaviour and expose the event to the user.
Beta Was this translation helpful? Give feedback.
All reactions