mirror of
https://github.com/flynx/pWiki.git
synced 2025-10-28 17:40:07 +00:00
Compare commits
3 Commits
ea9e521e91
...
ada5c33665
| Author | SHA1 | Date | |
|---|---|---|---|
| ada5c33665 | |||
| 2c2257b603 | |||
| 0d0fbadc2f |
@ -1,265 +1,266 @@
|
|||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
Element.prototype.visibleInViewport = function(partial=false){
|
// XXX add something like .closeToViewport(..)
|
||||||
var { top, left, bottom, right } = this.getBoundingClientRect()
|
Element.prototype.visibleInViewport = function(partial=false){
|
||||||
var { innerHeight, innerWidth } = window
|
var { top, left, bottom, right } = this.getBoundingClientRect()
|
||||||
return partial
|
var { innerHeight, innerWidth } = window
|
||||||
? ((top > 0
|
return partial
|
||||||
&& top < innerHeight)
|
? ((top > 0
|
||||||
|| (bottom > 0
|
&& top < innerHeight)
|
||||||
&& bottom < innerHeight))
|
|| (bottom > 0
|
||||||
&& ((left > 0
|
&& bottom < innerHeight))
|
||||||
&& left < innerWidth)
|
&& ((left > 0
|
||||||
|| (right > 0
|
&& left < innerWidth)
|
||||||
&& right < innerWidth))
|
|| (right > 0
|
||||||
: (top >= 0
|
&& right < innerWidth))
|
||||||
&& left >= 0
|
: (top >= 0
|
||||||
&& bottom <= innerHeight
|
&& left >= 0
|
||||||
&& right <= innerWidth) }
|
&& bottom <= innerHeight
|
||||||
|
&& right <= innerWidth) }
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
// XXX should these be here???
|
|
||||||
HTMLElement.encode = function(str){
|
// XXX should these be here???
|
||||||
var span = document.createElement('span')
|
HTMLElement.encode = function(str){
|
||||||
// XXX
|
var span = document.createElement('span')
|
||||||
return str
|
// XXX
|
||||||
.replace(/&/g, '&')
|
return str
|
||||||
.replace(/</g, '<')
|
.replace(/&/g, '&')
|
||||||
.replace(/>/g, '>') }
|
.replace(/</g, '<')
|
||||||
/*/
|
.replace(/>/g, '>') }
|
||||||
span.innerText = str
|
/*/
|
||||||
return span.innerHTML }
|
span.innerText = str
|
||||||
//*/
|
return span.innerHTML }
|
||||||
// XXX this does not convert <br> back to \n...
|
//*/
|
||||||
HTMLElement.decode = function(str){
|
// XXX this does not convert <br> back to \n...
|
||||||
var span = document.createElement('span')
|
HTMLElement.decode = function(str){
|
||||||
// XXX
|
var span = document.createElement('span')
|
||||||
return str
|
// XXX
|
||||||
.replace(/</g, '<')
|
return str
|
||||||
.replace(/>/g, '>')
|
.replace(/</g, '<')
|
||||||
.replace(/&/g, '&') }
|
.replace(/>/g, '>')
|
||||||
/*/
|
.replace(/&/g, '&') }
|
||||||
span.innerHTML = str
|
/*/
|
||||||
return span.innerText }
|
span.innerHTML = str
|
||||||
//*/
|
return span.innerText }
|
||||||
|
//*/
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
HTMLTextAreaElement.prototype.updateSize = function(){
|
|
||||||
// NOTE: this is set to 0px to negate the effects of external/inherited
|
HTMLTextAreaElement.prototype.updateSize = function(){
|
||||||
// height settings...
|
// NOTE: this is set to 0px to negate the effects of external/inherited
|
||||||
this.style.height = '0px'
|
// height settings...
|
||||||
this.style.height = this.scrollHeight + 'px'
|
this.style.height = '0px'
|
||||||
return this }
|
this.style.height = this.scrollHeight + 'px'
|
||||||
HTMLTextAreaElement.prototype.autoUpdateSize = function(){
|
return this }
|
||||||
var that = this
|
HTMLTextAreaElement.prototype.autoUpdateSize = function(){
|
||||||
this.addEventListener('input',
|
var that = this
|
||||||
function(evt){
|
this.addEventListener('input',
|
||||||
that.updateSize() })
|
function(evt){
|
||||||
return this }
|
that.updateSize() })
|
||||||
|
return this }
|
||||||
|
|
||||||
var cloneAsOffscreenSpan = function(elem){
|
|
||||||
var style = getComputedStyle(elem)
|
var cloneAsOffscreenSpan = function(elem){
|
||||||
var s = {}
|
var style = getComputedStyle(elem)
|
||||||
for(var i=0; i < style.length; i++){
|
var s = {}
|
||||||
var k = style[i]
|
for(var i=0; i < style.length; i++){
|
||||||
if(k.startsWith('font')
|
var k = style[i]
|
||||||
|| k.startsWith('line')
|
if(k.startsWith('font')
|
||||||
|| k.startsWith('white-space')){
|
|| k.startsWith('line')
|
||||||
s[k] = style[k] } }
|
|| k.startsWith('white-space')){
|
||||||
var span = document.createElement('span')
|
s[k] = style[k] } }
|
||||||
Object.assign(span.style, {
|
var span = document.createElement('span')
|
||||||
...s,
|
Object.assign(span.style, {
|
||||||
|
...s,
|
||||||
position: 'fixed',
|
|
||||||
display: 'block',
|
position: 'fixed',
|
||||||
/* DEBUG...
|
display: 'block',
|
||||||
top: '0px',
|
/* DEBUG...
|
||||||
left: '0px',
|
top: '0px',
|
||||||
/*/
|
left: '0px',
|
||||||
top: '-100%',
|
/*/
|
||||||
left: '-100%',
|
top: '-100%',
|
||||||
//*/
|
left: '-100%',
|
||||||
width: style.width,
|
//*/
|
||||||
height: style.height,
|
width: style.width,
|
||||||
|
height: style.height,
|
||||||
padding: style.padding,
|
|
||||||
|
padding: style.padding,
|
||||||
boxSizing: style.boxSizing,
|
|
||||||
whiteSpace: style.whiteSpace,
|
boxSizing: style.boxSizing,
|
||||||
|
whiteSpace: style.whiteSpace,
|
||||||
outline: 'solid 1px red',
|
|
||||||
|
outline: 'solid 1px red',
|
||||||
pointerEvents: 'none',
|
|
||||||
})
|
pointerEvents: 'none',
|
||||||
return span }
|
})
|
||||||
|
return span }
|
||||||
HTMLTextAreaElement.prototype.getTextGeometry = function(func){
|
|
||||||
var offset = this.selectionStart
|
HTMLTextAreaElement.prototype.getTextGeometry = function(func){
|
||||||
var text = this.value
|
var offset = this.selectionStart
|
||||||
|
var text = this.value
|
||||||
// get the relevant styles...
|
|
||||||
var style = getComputedStyle(this)
|
// get the relevant styles...
|
||||||
var paddingV = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)
|
var style = getComputedStyle(this)
|
||||||
|
var paddingV = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)
|
||||||
var caret = document.createElement('span')
|
|
||||||
caret.innerText = '|'
|
var caret = document.createElement('span')
|
||||||
caret.style.margin = '0px'
|
caret.innerText = '|'
|
||||||
caret.style.padding = '0px'
|
caret.style.margin = '0px'
|
||||||
|
caret.style.padding = '0px'
|
||||||
var span = cloneAsOffscreenSpan(this)
|
|
||||||
span.append(
|
var span = cloneAsOffscreenSpan(this)
|
||||||
text.slice(0, offset),
|
span.append(
|
||||||
caret,
|
text.slice(0, offset),
|
||||||
// NOTE: wee need the rest of the text for the caret to be typeset
|
caret,
|
||||||
// to the correct line...
|
// NOTE: wee need the rest of the text for the caret to be typeset
|
||||||
text.slice(offset))
|
// to the correct line...
|
||||||
document.body.append(span)
|
text.slice(offset))
|
||||||
|
document.body.append(span)
|
||||||
var res = {
|
|
||||||
length: text.length,
|
var res = {
|
||||||
|
length: text.length,
|
||||||
lines: Math.floor(
|
|
||||||
(this.offsetHeight - paddingV)
|
lines: Math.floor(
|
||||||
/ caret.offsetHeight),
|
(this.offsetHeight - paddingV)
|
||||||
line: Math.floor(caret.offsetTop / caret.offsetHeight),
|
/ caret.offsetHeight),
|
||||||
|
line: Math.floor(caret.offsetTop / caret.offsetHeight),
|
||||||
caretHeight: caret.offsetHeight,
|
|
||||||
|
caretHeight: caret.offsetHeight,
|
||||||
offset: offset,
|
|
||||||
offsetLeft: caret.offsetLeft,
|
offset: offset,
|
||||||
offsetTop: caret.offsetTop,
|
offsetLeft: caret.offsetLeft,
|
||||||
}
|
offsetTop: caret.offsetTop,
|
||||||
|
}
|
||||||
if(typeof(func) == 'function'){
|
|
||||||
res = func(res, span) }
|
if(typeof(func) == 'function'){
|
||||||
|
res = func(res, span) }
|
||||||
span.remove()
|
|
||||||
|
span.remove()
|
||||||
return res }
|
|
||||||
|
return res }
|
||||||
HTMLTextAreaElement.prototype.getTextOffsetAt = function(x, y){
|
|
||||||
var that = this
|
HTMLTextAreaElement.prototype.getTextOffsetAt = function(x, y){
|
||||||
var text = this.value
|
var that = this
|
||||||
|
var text = this.value
|
||||||
// cleanup cached span...
|
|
||||||
this.__getTextOffsetAt_timeout
|
// cleanup cached span...
|
||||||
&& clearTimeout(this.__getTextOffsetAt_timeout)
|
this.__getTextOffsetAt_timeout
|
||||||
this.__getTextOffsetAt_timeout = setTimeout(function(){
|
&& clearTimeout(this.__getTextOffsetAt_timeout)
|
||||||
delete that.__getTextOffsetAt_timeout
|
this.__getTextOffsetAt_timeout = setTimeout(function(){
|
||||||
that.__getTextOffsetAt_clone.remove()
|
delete that.__getTextOffsetAt_timeout
|
||||||
delete that.__getTextOffsetAt_clone }, 50)
|
that.__getTextOffsetAt_clone.remove()
|
||||||
|
delete that.__getTextOffsetAt_clone }, 50)
|
||||||
// create/get clone span...
|
|
||||||
if(this.__getTextOffsetAt_clone == null){
|
// create/get clone span...
|
||||||
var span =
|
if(this.__getTextOffsetAt_clone == null){
|
||||||
this.__getTextOffsetAt_clone =
|
var span =
|
||||||
cloneAsOffscreenSpan(this)
|
this.__getTextOffsetAt_clone =
|
||||||
span.append(text)
|
cloneAsOffscreenSpan(this)
|
||||||
document.body.append(span)
|
span.append(text)
|
||||||
} else {
|
document.body.append(span)
|
||||||
var span = this.__getTextOffsetAt_clone }
|
} else {
|
||||||
|
var span = this.__getTextOffsetAt_clone }
|
||||||
var r = document.createRange()
|
|
||||||
var t = span.firstChild
|
var r = document.createRange()
|
||||||
|
var t = span.firstChild
|
||||||
var clone = span.getBoundingClientRect()
|
|
||||||
var target = this.getBoundingClientRect()
|
var clone = span.getBoundingClientRect()
|
||||||
|
var target = this.getBoundingClientRect()
|
||||||
var ox = x - target.x
|
|
||||||
var oy = y - target.y
|
var ox = x - target.x
|
||||||
|
var oy = y - target.y
|
||||||
var rect, prev
|
|
||||||
var cursor_line
|
var rect, prev
|
||||||
var col
|
var cursor_line
|
||||||
for(var i=0; i <= t.length; i++){
|
var col
|
||||||
r.setStart(t, i)
|
for(var i=0; i <= t.length; i++){
|
||||||
r.setEnd(t, i)
|
r.setStart(t, i)
|
||||||
prev = rect
|
r.setEnd(t, i)
|
||||||
rect = r.getBoundingClientRect()
|
prev = rect
|
||||||
// line change...
|
rect = r.getBoundingClientRect()
|
||||||
if(prev && prev.y != rect.y){
|
// line change...
|
||||||
// went off the cursor line
|
if(prev && prev.y != rect.y){
|
||||||
if(cursor_line
|
// went off the cursor line
|
||||||
// cursor above block
|
if(cursor_line
|
||||||
|| oy <= prev.y - clone.y){
|
// cursor above block
|
||||||
// end of prev line...
|
|| oy <= prev.y - clone.y){
|
||||||
return col
|
// end of prev line...
|
||||||
?? i - 1 }
|
return col
|
||||||
// reset col
|
?? i - 1 }
|
||||||
col = undefined }
|
// reset col
|
||||||
// cursor line...
|
col = undefined }
|
||||||
cursor_line =
|
// cursor line...
|
||||||
oy >= rect.y - clone.y
|
cursor_line =
|
||||||
&& oy <= rect.bottom - clone.y
|
oy >= rect.y - clone.y
|
||||||
// cursor col -- set once per line...
|
&& oy <= rect.bottom - clone.y
|
||||||
if(col == null
|
// cursor col -- set once per line...
|
||||||
&& ox <= rect.x - clone.x){
|
if(col == null
|
||||||
col = (ox > 0
|
&& ox <= rect.x - clone.x){
|
||||||
|| i == 0) ?
|
col = (ox > 0
|
||||||
i
|
|| i == 0) ?
|
||||||
: i - 1
|
i
|
||||||
if(cursor_line){
|
: i - 1
|
||||||
return col } } }
|
if(cursor_line){
|
||||||
// below or right of the block -> return last col or last char...
|
return col } } }
|
||||||
return col
|
// below or right of the block -> return last col or last char...
|
||||||
?? i }
|
return col
|
||||||
|
?? i }
|
||||||
// calculate number of lines in text area (both wrapped and actual lines)
|
|
||||||
Object.defineProperty(HTMLTextAreaElement.prototype, 'heightLines', {
|
// calculate number of lines in text area (both wrapped and actual lines)
|
||||||
enumerable: false,
|
Object.defineProperty(HTMLTextAreaElement.prototype, 'heightLines', {
|
||||||
get: function(){
|
enumerable: false,
|
||||||
var style = getComputedStyle(this)
|
get: function(){
|
||||||
return Math.floor(
|
var style = getComputedStyle(this)
|
||||||
(this.scrollHeight
|
return Math.floor(
|
||||||
- parseFloat(style.paddingTop)
|
(this.scrollHeight
|
||||||
- parseFloat(style.paddingBottom))
|
- parseFloat(style.paddingTop)
|
||||||
/ (parseFloat(style.lineHeight)
|
- parseFloat(style.paddingBottom))
|
||||||
|| parseFloat(style.fontSize))) }, })
|
/ (parseFloat(style.lineHeight)
|
||||||
Object.defineProperty(HTMLTextAreaElement.prototype, 'lines', {
|
|| parseFloat(style.fontSize))) }, })
|
||||||
enumerable: false,
|
Object.defineProperty(HTMLTextAreaElement.prototype, 'lines', {
|
||||||
get: function(){
|
enumerable: false,
|
||||||
return this.value
|
get: function(){
|
||||||
.split(/\n/g)
|
return this.value
|
||||||
.length }, })
|
.split(/\n/g)
|
||||||
// XXX this does not account for wrapping...
|
.length }, })
|
||||||
Object.defineProperty(HTMLTextAreaElement.prototype, 'caretLine', {
|
// XXX this does not account for wrapping...
|
||||||
enumerable: false,
|
Object.defineProperty(HTMLTextAreaElement.prototype, 'caretLine', {
|
||||||
get: function(){
|
enumerable: false,
|
||||||
var offset = this.selectionStart
|
get: function(){
|
||||||
return offset != null ?
|
var offset = this.selectionStart
|
||||||
this.value
|
return offset != null ?
|
||||||
.slice(0, offset)
|
this.value
|
||||||
.split(/\n/g)
|
.slice(0, offset)
|
||||||
.length
|
.split(/\n/g)
|
||||||
: undefined }, })
|
.length
|
||||||
|
: undefined }, })
|
||||||
|
|
||||||
Object.defineProperty(HTMLTextAreaElement.prototype, 'caretOffset', {
|
|
||||||
enumerable: false,
|
Object.defineProperty(HTMLTextAreaElement.prototype, 'caretOffset', {
|
||||||
get: function(){
|
enumerable: false,
|
||||||
var offset = this.selectionStart
|
get: function(){
|
||||||
var r = document.createRange()
|
var offset = this.selectionStart
|
||||||
r.setStart(this, offset)
|
var r = document.createRange()
|
||||||
r.setEnd(this, offset)
|
r.setStart(this, offset)
|
||||||
var rect = r.getBoundingClientRect()
|
r.setEnd(this, offset)
|
||||||
return {
|
var rect = r.getBoundingClientRect()
|
||||||
top: rect.top,
|
return {
|
||||||
left: rect.left,
|
top: rect.top,
|
||||||
} },
|
left: rect.left,
|
||||||
})
|
} },
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
* vim:set ts=4 sw=4 : */
|
/**********************************************************************
|
||||||
|
* vim:set ts=4 sw=4 : */
|
||||||
|
|||||||
@ -752,4 +752,4 @@ var setup = function(){
|
|||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
<!-- vim:set ts=4 sw=4 : -->
|
<!-- vim:set ts=4 sw=4 nowrap : -->
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user