+ currentLine: function() { // Deprecated, but still there for backward compatibility
+ return this.lineNumber(this.cursorLine());
+ },
+ cursorLine: function() {
+ return this.cursorPosition().line;
+ },
+ cursorCoords: function(start) {return this.editor.cursorCoords(start);},
+
+ activateLineNumbers: function() {
+ var frame = this.frame, win = frame.contentWindow, doc = win.document, body = doc.body,
+ nums = this.lineNumbers, scroller = nums.firstChild, self = this;
+ var barWidth = null;
+
+ function sizeBar() {
+ if (frame.offsetWidth == 0) return;
+ for (var root = frame; root.parentNode; root = root.parentNode);
+ if (!nums.parentNode || root != document || !win.Editor) {
+ // Clear event handlers (their nodes might already be collected, so try/catch)
+ try{clear();}catch(e){}
+ clearInterval(sizeInterval);
+ return;
+ }
+
+ /*if (nums.offsetWidth != barWidth) {
+ barWidth = nums.offsetWidth;
+ frame.parentNode.style.paddingLeft = barWidth + "px";
+ }*/
+ }
+ function doScroll() {
+ nums.scrollTop = body.scrollTop || doc.documentElement.scrollTop || 0;
+ }
+ // Cleanup function, registered by nonWrapping and wrapping.
+ var clear = function(){};
+ sizeBar();
+ var sizeInterval = setInterval(sizeBar, 500);
+
+ function ensureEnoughLineNumbers(fill) {
+ var lineHeight = scroller.firstChild.offsetHeight;
+ if (lineHeight == 0) return;
+ var targetHeight = 50 + Math.max(body.offsetHeight, Math.max(frame.offsetHeight, body.scrollHeight || 0)),
+ lastNumber = Math.ceil(targetHeight / lineHeight);
+ for (var i = scroller.childNodes.length; i <= lastNumber; i++) {
+ var div = document.createElement("DIV");
+ div.appendChild(document.createTextNode(fill ? String(i + 1) : "\u00a0"));
+ scroller.appendChild(div);
+ }
+ }
+
+ function nonWrapping() {
+ function update() {
+ ensureEnoughLineNumbers(true);
+ doScroll();
+ }
+ self.updateNumbers = update;
+ var onScroll = win.addEventHandler(win, "scroll", doScroll, true),
+ onResize = win.addEventHandler(win, "resize", update, true);
+ clear = function(){
+ onScroll(); onResize();
+ if (self.updateNumbers == update) self.updateNumbers = null;
+ };
+ update();
+ }
+
+ function wrapping() {
+ var node, lineNum, next, pos, changes = [], styleNums = self.options.styleNumbers;
+
+ function setNum(n, node) {
+ // Does not typically happen (but can, if you mess with the
+ // document during the numbering)
+ if (!lineNum) lineNum = scroller.appendChild(document.createElement("DIV"));
+ if (styleNums) styleNums(lineNum, node, n);
+ // Changes are accumulated, so that the document layout
+ // doesn't have to be recomputed during the pass
+ changes.push(lineNum); changes.push(n);
+ pos = lineNum.offsetHeight + lineNum.offsetTop;
+ lineNum = lineNum.nextSibling;
+ }
+ function commitChanges() {
+ for (var i = 0; i < changes.length; i += 2)
+ changes[i].innerHTML = changes[i + 1];
+ changes = [];
+ }
+ function work() {
+ if (!scroller.parentNode || scroller.parentNode != self.lineNumbers) return;
+
+ var endTime = new Date().getTime() + self.options.lineNumberTime;
+ while (node) {
+ setNum(next++, node.previousSibling);
+ for (; node && !win.isBR(node); node = node.nextSibling) {
+ var bott = node.offsetTop + node.offsetHeight;
+ while (scroller.offsetHeight && bott - 3 > pos) setNum(" ");
+ }
+ if (node) node = node.nextSibling;
+ if (new Date().getTime() > endTime) {
+ commitChanges();
+ pending = setTimeout(work, self.options.lineNumberDelay);
+ return;
+ }
+ }
+ while (lineNum) setNum(next++);
+ commitChanges();
+ doScroll();
+ }
+ function start(firstTime) {
+ doScroll();
+ ensureEnoughLineNumbers(firstTime);
+ node = body.firstChild;
+ lineNum = scroller.firstChild;
+ pos = 0;
+ next = 1;
+ work();
+ }
+
+ start(true);
+ var pending = null;
+ function update() {
+ if (pending) clearTimeout(pending);
+ if (self.editor.allClean()) start();
+ else pending = setTimeout(update, 200);
+ }
+ self.updateNumbers = update;
+ var onScroll = win.addEventHandler(win, "scroll", doScroll, true),
+ onResize = win.addEventHandler(win, "resize", update, true);
+ clear = function(){
+ if (pending) clearTimeout(pending);
+ if (self.updateNumbers == update) self.updateNumbers = null;
+ onScroll();
+ onResize();
+ };
+ }
+ (this.options.textWrapping || this.options.styleNumbers ? wrapping : nonWrapping)();
+ },
+
+ setDynamicHeight: function() {
+ var self = this, activity = self.options.cursorActivity, win = self.win, body = win.document.body,
+ lineHeight = null, timeout = null, vmargin = 2 * self.frame.offsetTop;
+ body.style.overflowY = "hidden";
+ win.document.documentElement.style.overflowY = "hidden";
+ this.frame.scrolling = "no";
+
+ function updateHeight() {
+ for (var span = body.firstChild, sawBR = false; span; span = span.nextSibling)
+ if (win.isSpan(span) && span.offsetHeight) {
+ lineHeight = span.offsetHeight;
+ if (!sawBR) vmargin = 2 * (self.frame.offsetTop + span.offsetTop + body.offsetTop + (internetExplorer ? 10 : 0));
+ break;
+ }
+ if (lineHeight)
+ self.wrapping.style.height = Math.max(vmargin + lineHeight * (body.getElementsByTagName("BR").length + 1),
+ self.options.minHeight) + "px";
+ }
+ setTimeout(updateHeight, 100);
+ self.options.cursorActivity = function(x) {
+ if (activity) activity(x);
+ clearTimeout(timeout);
+ timeout = setTimeout(updateHeight, 200);
+ };