Clean up webelem.text/set_text

webelem.text() was only used without use_js=True from webelem.__str__.
Now we instead default to the use_js=True behavior and renamed the
method from text() to value().

The old behavior is instead directly implemented in __str__.

This changes how webelem.value (aka text) handles elements for which
is_content_editable() returns True, but I haven't found any cases where
this makes a difference.

This also fixes getting existing text from elements with QtWebEngine,
which closes #1957.
This commit is contained in:
Florian Bruhin 2016-11-16 12:15:43 +01:00
parent 5e53f230ee
commit 25358bb5fc
6 changed files with 40 additions and 51 deletions

View File

@ -1486,7 +1486,7 @@ class CommandDispatcher:
message.error("Focused element is not editable!")
return
text = elem.text(use_js=True)
text = elem.value()
ed = editor.ExternalEditor(self._tabbed_browser)
ed.editing_finished.connect(functools.partial(
self.on_editing_finished, elem))
@ -1513,7 +1513,7 @@ class CommandDispatcher:
text: The new text to insert.
"""
try:
elem.set_text(text, use_js=True)
elem.set_value(text)
except webelem.Error as e:
raise cmdexc.CommandError(str(e))

View File

@ -87,7 +87,7 @@ class AbstractWebElement(collections.abc.MutableMapping):
raise NotImplementedError
def __str__(self):
return self.text()
raise NotImplementedError
def __getitem__(self, key):
raise NotImplementedError
@ -138,24 +138,12 @@ class AbstractWebElement(collections.abc.MutableMapping):
"""Get the full HTML representation of this element."""
raise NotImplementedError
def text(self, *, use_js=False):
"""Get the plain text content for this element.
Args:
use_js: Whether to use javascript if the element isn't
content-editable.
"""
# FIXME:qtwebengine what to do about use_js with WebEngine?
def value(self):
"""Get the value attribute for this element."""
raise NotImplementedError
def set_text(self, text, *, use_js=False):
"""Set the given plain text.
Args:
use_js: Whether to use javascript if the element isn't
content-editable.
"""
# FIXME:qtwebengine what to do about use_js with WebEngine?
def set_value(self, value):
"""Set the element value."""
raise NotImplementedError
def insert_text(self, text):

View File

@ -37,6 +37,9 @@ class WebEngineElement(webelem.AbstractWebElement):
self._id = js_dict['id']
self._js_dict = js_dict
def __str__(self):
return self._js_dict.get('text', '')
def __eq__(self, other):
if not isinstance(other, WebEngineElement):
return NotImplemented
@ -87,27 +90,11 @@ class WebEngineElement(webelem.AbstractWebElement):
"""Get the full HTML representation of this element."""
return self._js_dict['outer_xml']
def text(self, *, use_js=False):
"""Get the plain text content for this element.
def value(self):
return self._js_dict['value']
Args:
use_js: Whether to use javascript if the element isn't
content-editable.
"""
if use_js:
# FIXME:qtwebengine what to do about use_js with WebEngine?
log.stub('with use_js=True')
return self._js_dict.get('text', '')
def set_text(self, text, *, use_js=False):
"""Set the given plain text.
Args:
use_js: Whether to use javascript if the element isn't
content-editable.
"""
# FIXME:qtwebengine what to do about use_js with WebEngine?
js_code = javascript.assemble('webelem', 'set_text', self._id, text)
def set_value(self, value):
js_code = javascript.assemble('webelem', 'set_value', self._id, value)
self._tab.run_js_async(js_code)
def insert_text(self, text):

View File

@ -46,6 +46,10 @@ class WebKitElement(webelem.AbstractWebElement):
raise IsNullError('{} is a null element!'.format(elem))
self._elem = elem
def __str__(self):
self._check_vanished()
return self._elem.toPlainText()
def __eq__(self, other):
if not isinstance(other, WebKitElement):
return NotImplemented
@ -116,22 +120,19 @@ class WebKitElement(webelem.AbstractWebElement):
self._check_vanished()
return self._elem.toOuterXml()
def text(self, *, use_js=False):
def value(self):
self._check_vanished()
if self.is_content_editable() or not use_js:
return self._elem.toPlainText()
else:
return self._elem.evaluateJavaScript('this.value')
return self._elem.evaluateJavaScript('this.value')
def set_text(self, text, *, use_js=False):
def set_value(self, value):
self._check_vanished()
if self.is_content_editable() or not use_js:
if self.is_content_editable():
log.webelem.debug("Filling {!r} via set_text.".format(self))
self._elem.setPlainText(text)
self._elem.setPlainText(value)
else:
log.webelem.debug("Filling {!r} via javascript.".format(self))
text = javascript.string_escape(text)
self._elem.evaluateJavaScript("this.value='{}'".format(text))
value = javascript.string_escape(value)
self._elem.evaluateJavaScript("this.value='{}'".format(value))
def insert_text(self, text):
self._check_vanished()

View File

@ -34,6 +34,7 @@ window._qutebrowser.webelem = (function() {
var out = {
"id": id,
"text": elem.text,
"value": elem.value,
"tag_name": elem.tagName,
"outer_xml": elem.outerHTML,
"class_name": elem.className,
@ -129,8 +130,8 @@ window._qutebrowser.webelem = (function() {
return serialize_elem(elem);
};
funcs.set_text = function(id, text) {
elements[id].value = text;
funcs.set_value = function(id, value) {
elements[id].value = value;
};
funcs.insert_text = function(id, text) {

View File

@ -93,3 +93,15 @@ Feature: Opening external editors
And I wait for "Read back: foobar" in the log
And I run :click-element id qute-button
Then the javascript message "text: foobar" should be logged
Scenario: Spawning an editor with existing text
When I set up a fake editor replacing "foo" by "bar"
And I open data/editor.html
And I run :click-element id qute-textarea
And I wait for "Clicked editable element!" in the log
And I run :insert-text foo
And I wait for "Inserting text into element *" in the log
And I run :open-editor
And I wait for "Read back: bar" in the log
And I run :click-element id qute-button
Then the javascript message "text: bar" should be logged