I'm making a web application to test regular expressions. I have an input where I enter the regexp and a contenteditable pre element where I enter the text where the matches are found and highlighted.
Example: asuming the regexp is ab, if the user types abcab in the pre element, both regexp and text are sent to an api I implemented which returns
<span style='background-color: lightgreen'>ab</span>c<span style='background-color: lightgreen'>ab</span>
and this string is set as the innerHTML of the pre element
This operation is made each time the user edites the content of the pre element (keyup event to be exact). The problem I have (and I hope you can solve) is that each time the innterHTML is set, the caret is placed at the beginning, and I want it to be placed right after the last character input by de user. Any suggestions on how to know where the caret is placed and how to place it in a desired position? Thanks.
UPDATE For better understanding...A clear case: Regexp is ab and in the contenteditable element we have:
<span style='background-color: lightgreen'>ab</span>c<span style='background-color: lightgreen'>ab</span>
Then I type a c between the first a and the first b, so now we have:
<span style='background-color: lightgreen'>ab</span>c<span style='background-color: lightgreen'>ab</span>
At this moment the caret has returned to the beginning of the contenteditable element, and it should be placed right after the c I typed. That's what I want to achieve, hope now it's more clear.
UPDATE2
<span style='background-color: lightgreen'>ab</span>c<span style='background-color: lightgreen'>ab</span>
acbc<span style='background-color: lightgreen'>ab</span>
答案 0 :(得分:0)
CD: C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3
Current directory: C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3
python "C:\Users\TBMEPYG\Desktop\vamo.py"
Process started >>>
Traceback (most recent call last):
File "C:\Users\TBMEPYG\Desktop\vamo.py", line 8, in <module>
data = driver.find_element_by_name('Dt_Ref')
File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 426, in find_element_by_name
return self.find_element(by=By.NAME, value=name)
File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 832, in find_element
'value': value})['value']
File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 297, in execute
self.error_handler.check_response(response)
File "C:\Users\TBMEPYG\AppData\Local\Continuum\Anaconda3\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 194, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: {"errorMessage":"Unable to find element with name 'Dt_Ref'","request":{"headers":{"Accept":"application/json","Accept-Encoding":"identity","Connection":"close","Content-Length":"89","Content-Type":"application/json;charset=UTF-8","Host":"127.0.0.1:62040","User-Agent":"Python http auth"},"httpVersion":"1.1","method":"POST","post":"{\"using\": \"name\", \"value\": \"Dt_Ref\", \"sessionId\": \"bdd3fc70-8dd0-11e7-aeb1-85b8cfbe0d1c\"}","url":"/element","urlParsed":{"anchor":"","query":"","file":"element","directory":"/","path":"/element","relative":"/element","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/element","queryKey":{},"chunks":["element"]},"urlOriginal":"/session/bdd3fc70-8dd0-11e7-aeb1-85b8cfbe0d1c/element"}}
Screenshot: available via screen
I quickly made this and it places the cursor at the end of the string in the input box. The onclick is for when the user manually clicks on the input and the onfocus is for when the user tabs on the input.
from selenium import webdriver
path_phantom = 'C:\\Users\\TBMEPYG\\AppData\\Local\\Continuum\\Anaconda3\\Lib\\site-packages\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe'
driver = webdriver.PhantomJS(executable_path= path_phantom)
driver.get('http://www.anbima.com.br/reune/reune.asp')
data = driver.find_element_by_name('Dt_Ref')
data.clear()
data.send_keys('21/08/2017')
答案 1 :(得分:0)
Here to make selection easy, I've added another pip install GoogleMaps
tag with nothing in it, and given it a C:\Users\NA401134>pip install GoogleMaps
Collecting GoogleMaps
Using cached googlemaps-2.5.1.tar.gz
Complete output from command python setup.py egg_info:
warning: no files found matching 'NOTICE'
Installed c:\users\na401134\appdata\local\temp\pip-build-y5t07ucg\googlemaps\.eggs\requests-2.18.4-py3.5.egg
Searching for certifi>=2017.4.17
Reading https://pypi.python.org/simple/certifi/
Best match: certifi 2017.7.27.1
Downloading https://pypi.python.org/packages/20/d0/3f7a84b0c5b89e94abbd073a5f00c7176089f526edb056686751d5064cbd/certifi-2017.7.27.1.tar.gz#md5=48e8370da8b370a16e223ee9c7b6b063
Processing certifi-2017.7.27.1.tar.gz
Writing C:\Users\NA401134\AppData\Local\Temp\easy_install-ttda9z_e\certifi-2017.7.27.1\setup.cfg
Running certifi-2017.7.27.1\setup.py -q bdist_egg --dist-dir C:\Users\NA401134\AppData\Local\Temp\easy_install-ttda9z_e\certifi-2017.7.27.1\egg-dist-tmp-k3p_29q4
creating c:\users\na401134\appdata\local\temp\pip-build-y5t07ucg\googlemaps\.eggs\certifi-2017.7.27.1-py3.5.egg
Extracting certifi-2017.7.27.1-py3.5.egg to c:\users\na401134\appdata\local\temp\pip-build-y5t07ucg\googlemaps\.eggs
Installed c:\users\na401134\appdata\local\temp\pip-build-y5t07ucg\googlemaps\.eggs\certifi-2017.7.27.1-py3.5.egg
Searching for urllib3<1.23,>=1.21.1
Reading https://pypi.python.org/simple/urllib3/
Best match: urllib3 1.22
Downloading https://pypi.python.org/packages/ee/11/7c59620aceedcc1ef65e156cc5ce5a24ef87be4107c2b74458464e437a5d/urllib3-1.22.tar.gz#md5=0da7bed3fe94bf7dc59ae37885cc72f7
Processing urllib3-1.22.tar.gz
Writing C:\Users\NA401134\AppData\Local\Temp\easy_install-n_pau25n\urllib3-1.22\setup.cfg
Running urllib3-1.22\setup.py -q bdist_egg --dist-dir C:\Users\NA401134\AppData\Local\Temp\easy_install-n_pau25n\urllib3-1.22\egg-dist-tmp-on1foee6
c:\anaconda\lib\site-packages\setuptools-23.0.0-py3.5.egg\setuptools\dist.py:285: UserWarning: Normalizing '2017.07.27.1' to '2017.7.27.1'
warning: no previously-included files matching '*' found under directory 'docs\_build'
zip_safe flag not set; analyzing archive contents...
urllib3.packages.__pycache__.six.cpython-35: module references __path__
creating c:\users\na401134\appdata\local\temp\pip-build-y5t07ucg\googlemaps\.eggs\urllib3-1.22-py3.5.egg
Extracting urllib3-1.22-py3.5.egg to c:\users\na401134\appdata\local\temp\pip-build-y5t07ucg\googlemaps\.eggs
Installed c:\users\na401134\appdata\local\temp\pip-build-y5t07ucg\googlemaps\.eggs\urllib3-1.22-py3.5.egg
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\NA401134\AppData\Local\Temp\pip-build-y5t07ucg\GoogleMaps\setup.py", line 39, in <module>
'Topic :: Internet',
File "c:\anaconda\lib\distutils\core.py", line 108, in setup
_setup_distribution = dist = klass(attrs)
File "c:\anaconda\lib\site-packages\setuptools-23.0.0-py3.5.egg\setuptools\dist.py", line 269, in __init__
File "c:\anaconda\lib\site-packages\setuptools-23.0.0-py3.5.egg\setuptools\dist.py", line 313, in fetch_build_eggs
File "c:\anaconda\lib\site-packages\setuptools-23.0.0-py3.5.egg\pkg_resources\__init__.py", line 826, in resolve
File "c:\anaconda\lib\site-packages\setuptools-23.0.0-py3.5.egg\pkg_resources\__init__.py", line 1085, in best_match
File "c:\anaconda\lib\site-packages\setuptools-23.0.0-py3.5.egg\pkg_resources\__init__.py", line 695, in find
pkg_resources.VersionConflict: (idna 2.1 (c:\anaconda\lib\site-packages), Requirement.parse('idna<2.7,>=2.5'))
----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in C:\Users\NA401134\AppData\Local\Temp\pip-build-y5t07ucg\GoogleMaps\
attribute to make it easy to select.
I then simply create a range from this and use window.getSelection addRange to apply it.
Update: modified to place caret after the first C:\Users\NA401134>pip freeze
alabaster==0.7.8
anaconda-client==1.4.0
anaconda-navigator==1.2.1
argcomplete==1.0.0
astropy==1.2.1
Babel==2.3.3
backports.shutil-get-terminal-size==1.0.0
beautifulsoup4==4.4.1
bitarray==0.8.1
blaze==0.10.1
bokeh==0.12.0
boto==2.40.0
Bottleneck==1.1.0
cffi==1.6.0
chest==0.2.3
click==6.6
cloudpickle==0.2.1
clyent==1.2.2
colorama==0.3.7
comtypes==1.1.2
conda==4.1.6
conda-build==1.21.3
conda-env==2.5.0a0
configobj==5.0.6
contextlib2==0.5.3
cryptography==1.4
cycler==0.10.0
Cython==0.24
cytoolz==0.8.0
dask==0.10.0
datashape==0.5.2
decorator==4.0.10
dill==0.2.5
docutils==0.12
dynd===c328ab7
et-xmlfile==1.0.1
fastcache==1.0.2
Flask==0.11.1
Flask-Cors==2.1.2
gevent==1.1.1
greenlet==0.4.10
h5py==2.6.0
HeapDict==1.0.0
idna==2.1
imagesize==0.7.1
ipykernel==4.3.1
ipython==4.2.0
ipython-genutils==0.1.0
ipywidgets==4.1.1
itsdangerous==0.24
jdcal==1.2
jedi==0.9.0
Jinja2==2.8
jsonschema==2.5.1
jupyter==1.0.0
jupyter-client==4.3.0
jupyter-console==4.1.1
jupyter-core==4.1.0
llvmlite==0.11.0
locket==0.2.0
lxml==3.6.0
MarkupSafe==0.23
matplotlib==1.5.1
menuinst==1.4.1
mistune==0.7.2
mpmath==0.19
multipledispatch==0.4.8
nb-anacondacloud==1.1.0
nb-conda==1.1.0
nb-conda-kernels==1.0.3
nbconvert==4.2.0
nbformat==4.0.1
nbpresent==3.0.2
networkx==1.11
nltk==3.2.1
nose==1.3.7
notebook==4.2.1
numba==0.26.0
numexpr==2.6.0
numpy==1.11.1
odo==0.5.0
openpyxl==2.3.2
pandas==0.18.1
partd==0.3.4
path.py==0.0.0
pathlib2==2.1.0
patsy==0.4.1
pep8==1.7.0
pickleshare==0.7.2
Pillow==3.2.0
ply==3.8
psutil==4.3.0
py==1.4.31
pyasn1==0.1.9
pycosat==0.6.1
pycparser==2.14
pycrypto==2.6.1
pycurl==7.43.0
pyflakes==1.2.3
Pygments==2.1.3
pyOpenSSL==16.0.0
pyparsing==2.1.4
pyreadline==2.1
pytest==2.9.2
python-dateutil==2.5.3
pytz==2016.4
pywin32==220
PyYAML==3.11
pyzmq==15.2.0
qtconsole==4.2.1
QtPy==1.0.2
requests==2.10.0
rope-py3k==0.9.4.post1
ruamel-yaml===-VERSION
scikit-image==0.12.3
scikit-learn==0.17.1
scipy==0.17.1
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.10.0
snowballstemmer==1.2.1
sockjs-tornado==1.0.3
Sphinx==1.3.1
sphinx-rtd-theme==0.1.9
spyder==2.3.9
SQLAlchemy==1.0.13
statsmodels==0.6.1
sympy==1.0
tables==3.2.2
toolz==0.8.0
tornado==4.3
traitlets==4.2.1
unicodecsv==0.14.1
Werkzeug==0.11.10
xlrd==1.0.0
XlsxWriter==0.9.2
xlwings==0.7.2
xlwt==1.1.2
span
data-end
答案 2 :(得分:0)
从这里获得这些功能的帮助 - &gt;
Add element before/after text selection
我创造了一些我认为你追求的东西。 我基本上将一些临时标签放在当前光标所在的html中。然后我渲染新的HTML,然后用带有data-cpos属性的span替换标记。使用此我然后重新选择光标。
var insertHtmlBeforeSelection, insertHtmlAfterSelection;
(function() {
function createInserter(isBefore) {
return function(html) {
var sel, range, node;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = window.getSelection().getRangeAt(0);
range.collapse(isBefore);
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
}
} else if (document.selection && document.selection.createRange) {
// IE < 9
range = document.selection.createRange();
range.collapse(isBefore);
range.pasteHTML(html);
}
}
}
insertHtmlBeforeSelection = createInserter(true);
insertHtmlAfterSelection = createInserter(false);
})();
function refreshInnerHtml() {
var
tag_start = '⇷', //lets use some unicode chars unlikely to ever use..
tag_end = '⇸',
sel = document.getSelection(),
input = document.getElementById('textInput');
//remove old data-cpos
[].forEach.call(
input.querySelectorAll('[data-cpos]'),
function(e) { e.remove() });
//insert the tags at current cursor position
insertHtmlBeforeSelection(tag_start);
insertHtmlAfterSelection(tag_end);
//now do our replace
let html = input.innerText.replace(/(ab)/g, '<span style="background-color: lightgreen">$1</span>');
input.innerHTML = html.replace(tag_start,'<span data-cpos>').replace(tag_end,'</span>');
//now put cursor back
var e = input.querySelector('[data-cpos]');
if (e) {
var range = document.createRange();
range.setStart(e, 0);
range.setEnd(e, 0);
sel.removeAllRanges();
sel.addRange(range);
}
}
refreshInnerHtml();
Type some text below, with the letters 'ab' somewhere within it. <br>
<pre contenteditable onkeyup="refreshInnerHtml()" id="textInput" style="border: 1px solid black;" >It's about time.. above and beyond</pre>