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