diff --git a/lib/widget.js b/lib/widget.js index cbc5683..e39447b 100644 --- a/lib/widget.js +++ b/lib/widget.js @@ -439,7 +439,9 @@ Screen.prototype._listenMouse = function(el) { // if (self.grabKeys && self.focused !== el // && !el.hasAncestor(self.focused)) continue; - ret = el.lpos; + // Need to use _getCoords() over lpos for when the + // element is obfuscated by a scrollable parent. + ret = el._getCoords(); if (!ret) continue; left = ret.xi; top = ret.yi; @@ -1777,8 +1779,8 @@ Element.prototype.onScreenEvent = function(type, listener) { Element.prototype.hide = function() { if (this.hidden) return; - this.hidden = true; this.clearPos(); + this.hidden = true; this.emit('hide'); var below = this.screen.history[this.screen.history.length-2]; if (below && this.screen.focused === this) below.focus(); @@ -1833,9 +1835,9 @@ Element.prototype._focus = function() { }; Element.prototype.setContent = function(content, noClear) { + if (!noClear) this.clearPos(); this.content = content || ''; this.parseContent(); - if (!noClear) this.clearPos(); }; Element.prototype.parseContent = function() { @@ -1950,10 +1952,20 @@ Element.prototype._wrapContent = function(content, width) { , margin = 0 , rtof = [] , ftor = [] - , fake = []; + , fake = [] + , out = [] + , no = 0 + , line + , align + , cap + , total + , i + , part + , esc + , j + , lines; - var lines = content.split('\n') - , out = []; + lines = content.split('\n'); if (!content) { out.push(content); @@ -1968,9 +1980,15 @@ Element.prototype._wrapContent = function(content, width) { if (this.type === 'textarea') margin++; if (width > margin) width -= margin; - lines.forEach(function(line, no) { - var align = state - , cap; + for (; no < lines.length; no++) { + line = lines[no]; + align = state; + //cap = null; + //total = null; + //i = null; + //part = null; + //esc = null; + //j = null; ftor.push([]); @@ -2000,11 +2018,6 @@ Element.prototype._wrapContent = function(content, width) { } } - var total - , i - , part - , esc; - if (!wrap && line.length > width) { line = line.slice(0, width); } @@ -2018,7 +2031,7 @@ Element.prototype._wrapContent = function(content, width) { if (++total === width) { // Try to find a space to break on: if (line[i] !== ' ') { - var j = i; + j = i; while (j > i - 10 && j > 0 && line[j] !== ' ') j--; if (line[j] === ' ') i = j + 1; else i++; @@ -2050,19 +2063,19 @@ Element.prototype._wrapContent = function(content, width) { // Make sure we didn't wrap the line to the very end, otherwise // we get a pointless empty line after a newline. - if (line === '') return; + if (line === '') continue; } // If only an escape code got cut off, at it to `part`. if (/^(?:\x1b[\[\d;]*m)+$/.test(line)) { out[out.length-1] += line; - return; + continue; } out.push(self._align(line, width, align)); ftor[no].push(out.length - 1); rtof.push(no); - }); + } out.rtof = rtof; out.ftor = ftor; @@ -2103,14 +2116,16 @@ Element.prototype.removeKey = function() { }; Element.prototype.clearPos = function() { - // if (this.lpos && !this.lpos.cleared) { - // // optimize by making sure we only clear once. - // this.lpos.cleared = true; - // this.screen.clearRegion( - // this.lpos.xi, this.lpos.xl, - // this.lpos.yi, this.lpos.yl); - // } if (this.detached) return; + // Need to use _getCoords() over lpos here to avoid clearing + // elements which are obfuscated by a scrollable parent. + + // NOTE: COULD USE THIS MULTIPLE PLACES - explanation: + // We could use this.lpos because we don't want + // to clear coordinates that may have changed and may + // not be what/where is actually rendered. + // var lpos = this._getCoords() && this.lpos; + var lpos = this._getCoords(); if (!lpos) return; this.screen.clearRegion( @@ -3298,7 +3313,11 @@ ScrollableBox.prototype.scroll = function(offset, always) { , d , p , t - , b; + , b + , i + , max + , emax + , l; if (this.alwaysScroll || always) { // Semi-workaround @@ -3328,15 +3347,7 @@ ScrollableBox.prototype.scroll = function(offset, always) { // Find max "bottom" value for // content and descendant elements. // Scroll the content if necessary. - var diff = this.childBase - base - , w - , i - , max - , emax - , t - , l; - - if (diff === 0) { + if (this.childBase === base) { return this.emit('scroll'); } @@ -3351,7 +3362,6 @@ ScrollableBox.prototype.scroll = function(offset, always) { if (emax < 0) emax = 0; this.childBase = Math.min(this.childBase, Math.max(emax, max)); - diff = this.childBase - base; if (this.childBase < 0) { this.childBase = 0; @@ -3359,20 +3369,26 @@ ScrollableBox.prototype.scroll = function(offset, always) { this.childBase = this.baseLimit; } - if (diff > 0) { + if (this.childBase > base) { l = Math.min(this.childBase, this._clines.length); for (i = base; i < l; i++) { this.contentIndex += this._clines[i].length + 1; } - } else { + } else if (this.childBase < base) { + b = Math.min(base, this._clines.length); l = Math.min(this.childBase, this._clines.length); - for (i = base - 1; i >= l; i--) { + for (i = b - 1; i >= l; i--) { this.contentIndex -= this._clines[i].length + 1; } } // Optimize scrolling with CSR + IL/DL. p = this.lpos; + // Only really need _getCoords() if we want + // to allow nestable scrolling elements... + // or if we **really** want shrinkable + // scrolling elements. + // p = this._getCoords(); if (this.childBase !== base && this.screen.cleanSides(this)) { t = p.yi + this.itop; b = p.yl - this.ibottom - 1; @@ -4013,8 +4029,6 @@ Textbox.prototype.type = 'textbox'; Textbox.prototype.updateCursor = function() { if (this.screen.focused !== this) return; - //this.screen.program.cup(this.top + this.itop, - // this.left + this.ileft + this.value.length); var lpos = this._getCoords(); if (!lpos) return; this.screen.program.cup(lpos.yi + this.itop, @@ -5329,8 +5343,11 @@ Listbar.prototype.render = function() { }; Listbar.prototype.select = function(offset) { + var lpos = this._getCoords(); + if (!lpos) return; + var self = this - , width = this.lpos ? this.lpos.xl - this.lpos.xi : this.width + , width = lpos.xl - lpos.xi , drawn = 0 , visible = 0 , el; @@ -5345,7 +5362,9 @@ Listbar.prototype.select = function(offset) { this.items.forEach(function(el, i) { if (i < self.leftBase) return; - drawn += (el.lpos ? el.lpos.xl - el.lpos.xi : el.width) + 3; + var lpos = el._getCoords(); + if (!lpos) return; + drawn += (lpos.xl - lpos.xi) + 3; if (drawn <= width) visible++; });