click-n-drag selection not works on all elements (expanding elements still need tweaks)...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2023-11-04 22:49:13 +03:00
parent 2f3255b53d
commit 6674ece80e
3 changed files with 97 additions and 19 deletions

View File

@ -50,7 +50,8 @@ var getCharOffset = function(elem, x, y, c){
&& b.y <= y && b.y <= y
&& b.bottom >= y){ && b.bottom >= y){
// get the closest gap between chars to the click... // get the closest gap between chars to the click...
return Math.abs(b.x - x) <= Math.abs(prev.x - x) ? return (!prev
|| Math.abs(b.x - x) <= Math.abs(prev.x - x)) ?
c + i c + i
: c + i - 1 } } : c + i - 1 } }
c += i - 1 c += i - 1
@ -2053,11 +2054,8 @@ var Outline = {
outline.addEventListener('mousemove', outline.addEventListener('mousemove',
function(evt){ function(evt){
// handle selection in element with text offset by markup... // handle selection in element with text offset by markup...
// XXX should there be a timeout???
if(selecting != null){ if(selecting != null){
// XXX need to get offset under cursor... var c = selecting.getTextOffsetAt(evt.clientX, evt.clientY)
var c = getTextAreaOffset(selecting, evt.clientX, evt.clientY)
return
if(c > start){ if(c > start){
selecting.selectionStart = start selecting.selectionStart = start
selecting.selectionEnd = c selecting.selectionEnd = c

View File

@ -63,13 +63,10 @@ HTMLTextAreaElement.prototype.autoUpdateSize = function(){
function(evt){ function(evt){
that.updateSize() }) that.updateSize() })
return this } return this }
HTMLTextAreaElement.prototype.getTextGeometry = function(func){
var offset = this.selectionStart
var text = this.value
// get the relevant styles...
var style = getComputedStyle(this) var cloneAsOffscreenSpan = function(elem){
var paddingV = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom) var style = getComputedStyle(elem)
var s = {} var s = {}
for(var i=0; i < style.length; i++){ for(var i=0; i < style.length; i++){
var k = style[i] var k = style[i]
@ -77,12 +74,6 @@ HTMLTextAreaElement.prototype.getTextGeometry = function(func){
|| k.startsWith('line') || k.startsWith('line')
|| k.startsWith('white-space')){ || k.startsWith('white-space')){
s[k] = style[k] } } s[k] = style[k] } }
var carret = document.createElement('span')
carret.innerText = '|'
carret.style.margin = '0px'
carret.style.padding = '0px'
var span = document.createElement('span') var span = document.createElement('span')
Object.assign(span.style, { Object.assign(span.style, {
...s, ...s,
@ -108,13 +99,28 @@ HTMLTextAreaElement.prototype.getTextGeometry = function(func){
pointerEvents: 'none', pointerEvents: 'none',
}) })
return span }
HTMLTextAreaElement.prototype.getTextGeometry = function(func){
var offset = this.selectionStart
var text = this.value
// get the relevant styles...
var style = getComputedStyle(this)
var paddingV = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)
var carret = document.createElement('span')
carret.innerText = '|'
carret.style.margin = '0px'
carret.style.padding = '0px'
var span = cloneAsOffscreenSpan(this)
span.append( span.append(
text.slice(0, offset), text.slice(0, offset),
carret, carret,
// NOTE: wee need the rest of the text for the carret to be typeset // NOTE: wee need the rest of the text for the carret to be typeset
// to the correct line... // to the correct line...
text.slice(offset)) text.slice(offset))
document.body.append(span) document.body.append(span)
var res = { var res = {
@ -135,6 +141,75 @@ HTMLTextAreaElement.prototype.getTextGeometry = function(func){
return res } return res }
HTMLTextAreaElement.prototype.getTextOffsetAt = function(x, y){
var that = this
var text = this.value
// cleanup cached span...
this.__getTextOffsetAt_timeout
&& clearTimeout(this.__getTextOffsetAt_timeout)
this.__getTextOffsetAt_timeout = setTimeout(function(){
delete that.__getTextOffsetAt_timeout
that.__getTextOffsetAt_clone.remove()
delete that.__getTextOffsetAt_clone }, 50)
// create/get clone span...
if(this.__getTextOffsetAt_clone == null){
var span =
this.__getTextOffsetAt_clone =
cloneAsOffscreenSpan(this)
span.append(text)
document.body.append(span)
} else {
var span = this.__getTextOffsetAt_clone }
var r = document.createRange()
var t = span.firstChild
var clone = span.getBoundingClientRect()
var target = this.getBoundingClientRect()
var ox = x - target.x
var oy = y - target.y
var rect, prev
var cursor_line
var col
for(var i=0; i <= t.length; i++){
r.setStart(t, i)
r.setEnd(t, i)
prev = rect
rect = r.getBoundingClientRect()
// line change...
if(prev && prev.y != rect.y){
// went off the cursor line
if(cursor_line
// cursor above block
|| oy <= prev.y - clone.y){
// end of prev line...
return col
?? i - 1 }
// reset col
col = undefined }
// cursor line...
cursor_line =
oy >= rect.y - clone.y
&& oy <= rect.bottom - clone.y
// cursor col -- set once per line...
if(col == null
&& ox <= rect.x - clone.x){
col = (!prev
|| Math.abs(rect.x - clone.x - x) <= Math.abs(prev.x - clone.x - x)) ?
i
: i - 1
if(cursor_line){
return col } } }
return col
?? i }
// calculate number of lines in text area (both wrapped and actual lines) // calculate number of lines in text area (both wrapped and actual lines)
Object.defineProperty(HTMLTextAreaElement.prototype, 'heightLines', { Object.defineProperty(HTMLTextAreaElement.prototype, 'heightLines', {
enumerable: false, enumerable: false,

View File

@ -56,8 +56,13 @@ var setup = function(){
- side margins are a bit too large (account for toolbat to the right) - side margins are a bit too large (account for toolbat to the right)
- -
- ## ToDo: - ## ToDo:
- DONE selecting expanded code by _click-n-drag_
- # this is a test
string with
some extra words
- BUG: while selecting if the cursor moves to the left far enough (outside parent?) the first char in current line gets toggled...
- custom element / web component - custom element / web component
- BUG: selecting by _click-n-drag_ or _double/triple click_ for some reason does not work... - BUG: select via click-n-drag and double/triple clicks does not work...
- BUG/race: the non-value versions of custom elem seem to sometimes get loaded as empty... - BUG/race: the non-value versions of custom elem seem to sometimes get loaded as empty...
- DONE data interface: - DONE data interface:
collapsed:: true collapsed:: true