Changeset 4932
- Timestamp:
- 10/29/09 11:40:27 (4 weeks ago)
- Location:
- branches/greyhound
- Files:
-
- 12 modified
-
mt-static/codemirror/css/docs.css (modified) (1 diff)
-
mt-static/codemirror/index.html (modified) (2 diffs)
-
mt-static/codemirror/js/codemirror.js (modified) (10 diffs)
-
mt-static/codemirror/js/editor.js (modified) (31 diffs)
-
mt-static/codemirror/js/mirrorframe.js (modified) (1 diff)
-
mt-static/codemirror/js/parsejavascript.js (modified) (3 diffs)
-
mt-static/codemirror/js/select.js (modified) (13 diffs)
-
mt-static/codemirror/js/tokenizejavascript.js (modified) (1 diff)
-
mt-static/codemirror/js/undo.js (modified) (3 diffs)
-
mt-static/codemirror/js/util.js (modified) (2 diffs)
-
mt-static/codemirror/manual.html (modified) (7 diffs)
-
tmpl/cms/edit_template.tmpl (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/greyhound/mt-static/codemirror/css/docs.css
r4158 r4932 16 16 h2 { 17 17 font-size: 14pt; 18 } 19 20 h3 { 21 font-size: 12pt; 18 22 } 19 23 -
branches/greyhound/mt-static/codemirror/index.html
r4587 r4932 60 60 <li><a href="contrib/python/index.html">Python</a> (courtesy of <a href="contrib/python/LICENSE">Timothy Farrell</a>)</li> 61 61 <li><a href="contrib/lua/index.html">Lua</a> (courtesy of <a href="http://francio.pl/">Franciszek Wawrzak</a>)</li> 62 <li><a href="http://stuff.hantl.cz/ruby-in-codemirror/">Ruby</a> (by Michal Hantl, <a href="http://github.com/hakunin/ruby-in-codemirror/tree/master">unfinished</a>)</li> 62 <li><a href="http://d.hantl.cz/d/ruby-in-codemirror/">Ruby</a> (by Michal Hantl, <a href="http://github.com/hakunin/ruby-in-codemirror/tree/master">unfinished</a>)</li> 63 <li><a href="contrib/sql/index.html">SQL</a> (courtesy of John Benediktsson)</li> 63 64 </ul> 64 65 … … 78 79 <h2>Releases</h2> 79 80 81 <p class="rel"><em>23-09-2009</em>: <a 82 href="http://marijn.haverbeke.nl/codemirror/codemirror-0.64.zip">Version 83 0.64</a>: Solves some issues introduced by the paste-handling changes 84 from the previous release. Adds <code>setSpellcheck</code>, 85 <code>setTextWrapping</code>, <code>setIndentUnit</code>, 86 <code>setUndoDepth</code>, <code>setTabMode</code>, and 87 <code>setLineNumbers</code> to customise a running editor. Introduces 88 an <a href="contrib/sql/index.html">SQL</a> parser. Fixes a few small 89 problems in the <a href="contrib/python/index.html">Python</a> parser. 90 And, as usual, add workarounds for various newly discovered browser 91 incompatibilities.</p> 92 80 93 <p class="rel"><em>31-08-2009</em>: <a 81 94 href="http://marijn.haverbeke.nl/codemirror/codemirror-0.63.zip">Version 82 95 0.63</a>: Overhaul of paste-handling (less fragile), fixes for several 83 96 serious IE8 issues (cursor jumping, end-of-document bugs) and a number 84 of small problems. 85 86 Introduces <a href="contrib/python/index.html">Python</a> 87 and <a href="contrib/lua/index.html">Lua</a> parsers. Add 88 <code>setParser</code> (on-the-fly mode changing) and 89 <code>clearHistory</code> methods. Make parsing passes time-based 90 instead of lines-based (see the <code>passTime</code> option).</p> 97 of small problems.</p> 91 98 92 99 <p class="rel"><em>30-05-2009</em>: <a -
branches/greyhound/mt-static/codemirror/js/codemirror.js
r4587 r4932 27 27 // their meaning. 28 28 setDefaults(CodeMirrorConfig, { 29 lang: "en", 29 30 stylesheet: "", 30 31 path: "", … … 54 55 }); 55 56 56 function wrapLineNumberDiv(place) { 57 return function(node) { 58 var container = document.createElement("DIV"), 59 nums = document.createElement("DIV"), 60 scroller = document.createElement("DIV"); 61 container.style.position = "relative"; 62 nums.style.position = "absolute"; 63 nums.style.height = "100%"; 64 if (nums.style.setExpression) { 65 try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");} 66 catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions 67 } 68 nums.style.top = "0px"; 69 nums.style.overflow = "hidden"; 70 place(container); 71 container.appendChild(node); 72 container.appendChild(nums); 73 scroller.className = "CodeMirror-line-numbers"; 74 nums.appendChild(scroller); 75 } 76 } 77 78 function applyLineNumbers(frame) { 57 function addLineNumberDiv(container) { 58 var nums = document.createElement("DIV"), 59 scroller = document.createElement("DIV"); 60 nums.style.position = "absolute"; 61 nums.style.height = "100%"; 62 if (nums.style.setExpression) { 63 try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");} 64 catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions 65 } 66 nums.style.top = "0px"; 67 nums.style.overflow = "hidden"; 68 container.appendChild(nums); 69 scroller.className = "CodeMirror-line-numbers"; 70 nums.appendChild(scroller); 71 return nums; 72 } 73 74 function activateLineNumbers(frame, nums) { 79 75 var win = frame.contentWindow, doc = win.document, 80 nums = frame.nextSibling,scroller = nums.firstChild;76 scroller = nums.firstChild; 81 77 82 78 var nextNum = 1, barWidth = null; 83 79 function sizeBar() { 84 if (!frame.offsetWidth || !win.Editor) {85 for (var cur = frame; cur.parentNode; cur = cur.parentNode) {86 if (cur != document) {87 clearInterval(sizeInterval);88 return;89 }90 }80 for (var root = frame; root.parentNode; root = root.parentNode); 81 if (!nums.parentNode || root != document || !win.Editor) { 82 // Clear event handlers (their nodes might already be collected, so try/catch) 83 try{onScroll();}catch(e){} 84 try{onResize();}catch(e){} 85 clearInterval(sizeInterval); 86 return; 91 87 } 92 88 … … 105 101 nums.scrollTop = doc.body.scrollTop || doc.documentElement.scrollTop || 0; 106 102 } 103 var onScroll = win.addEventHandler(win, "scroll", update, true), 104 onResize = win.addEventHandler(win, "resize", update, true), 105 sizeInterval = setInterval(sizeBar, 500); 107 106 sizeBar(); 108 107 update(); 109 win.addEventHandler(win, "scroll", update);110 win.addEventHandler(win, "resize", update);111 var sizeInterval = setInterval(sizeBar, 500);112 108 } 113 109 … … 132 128 frame.style.display = "block"; 133 129 134 if (place.appendChild) { 135 var node = place; 136 place = function(n){node.appendChild(n);}; 137 } 138 if (options.lineNumbers) place = wrapLineNumberDiv(place); 139 place(frame); 130 var div = this.wrapping = document.createElement("DIV"); 131 div.style.position = "relative"; 132 div.className = "CodeMirror-wrapping"; 133 if (place.appendChild) place.appendChild(div); 134 else place(div); 135 div.appendChild(frame); 136 if (options.lineNumbers) this.lineNumbers = addLineNumberDiv(div); 140 137 141 138 // Link back to this object, so that the editor can fetch options … … 149 146 options.stylesheet = [options.stylesheet]; 150 147 151 var html = ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html ><head>"];148 var html = ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html lang="+options.lang+"><head>"]; 152 149 // Hack to work around a bunch of IE8-specific problems. 153 150 html.push("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=EmulateIE7\"/>"); … … 156 153 }); 157 154 forEach(options.basefiles.concat(options.parserfile), function(file) { 158 html.push("<script type=\"text/javascript\" src=\"" + options.path + file + "\">< /script>");155 html.push("<script type=\"text/javascript\" src=\"" + options.path + file + "\"><" + "/script>"); 159 156 }); 160 157 html.push("</head><body style=\"border-width: 0;\" class=\"editbox\" spellcheck=\"" + … … 170 167 init: function() { 171 168 if (this.options.initCallback) this.options.initCallback(this); 172 if (this. options.lineNumbers) applyLineNumbers(this.frame);169 if (this.lineNumbers) activateLineNumbers(this.frame, this.lineNumbers); 173 170 if (this.options.reindentOnLoad) this.reindent(); 174 171 }, … … 176 173 getCode: function() {return this.editor.getCode();}, 177 174 setCode: function(code) {this.editor.importCode(code);}, 178 selection: function() { return this.editor.selectedText();},175 selection: function() {this.focusIfIE(); return this.editor.selectedText();}, 179 176 reindent: function() {this.editor.reindent();}, 180 reindentSelection: function() {this.editor.reindentSelection(null);}, 181 177 reindentSelection: function() {this.focusIfIE(); this.editor.reindentSelection(null);}, 178 179 focusIfIE: function() { 180 // in IE, a lot of selection-related functionality only works when the frame is focused 181 if (this.win.select.ie_selection) this.focus(); 182 }, 182 183 focus: function() { 183 184 this.win.focus(); 184 185 if (this.editor.selectionSnapshot) // IE hack 185 this.win.select.se lectCoords(this.win, this.editor.selectionSnapshot);186 this.win.select.setBookmark(this.win.document.body, this.editor.selectionSnapshot); 186 187 }, 187 188 replaceSelection: function(text) { … … 193 194 this.editor.replaceChars(text, start, end); 194 195 }, 195 getSearchCursor: function(string, fromCursor ) {196 return this.editor.getSearchCursor(string, fromCursor );196 getSearchCursor: function(string, fromCursor, caseFold) { 197 return this.editor.getSearchCursor(string, fromCursor, caseFold); 197 198 }, 198 199 … … 206 207 207 208 setParser: function(name) {this.editor.setParser(name);}, 208 209 cursorPosition: function(start) { 210 if (this.win.select.ie_selection) this.focus(); 211 return this.editor.cursorPosition(start); 212 }, 209 setSpellcheck: function(on) {this.win.document.body.spellcheck = on;}, 210 setTextWrapping: function(on) {this.win.document.body.style.whiteSpace = on ? "" : "nowrap";}, 211 setIndentUnit: function(unit) {this.win.indentUnit = unit;}, 212 setUndoDepth: function(depth) {this.editor.history.maxDepth = depth;}, 213 setTabMode: function(mode) {this.options.tabMode = mode;}, 214 setLineNumbers: function(on) { 215 if (on && !this.lineNumbers) { 216 this.lineNumbers = addLineNumberDiv(this.wrapping); 217 activateLineNumbers(this.frame, this.lineNumbers); 218 } 219 else if (!on && this.lineNumbers) { 220 this.wrapping.removeChild(this.lineNumbers); 221 this.wrapping.style.marginLeft = ""; 222 this.lineNumbers = null; 223 } 224 }, 225 226 cursorPosition: function(start) {this.focusIfIE(); return this.editor.cursorPosition(start);}, 213 227 firstLine: function() {return this.editor.firstLine();}, 214 228 lastLine: function() {return this.editor.lastLine();}, -
branches/greyhound/mt-static/codemirror/js/editor.js
r4587 r4932 81 81 result.push(node); 82 82 } 83 else if ( node.nodeName == "BR"&& node.childNodes.length == 0) {83 else if (isBR(node) && node.childNodes.length == 0) { 84 84 leaving = true; 85 85 result.push(node); … … 87 87 else { 88 88 forEach(node.childNodes, simplifyNode); 89 if (!leaving && newlineElements.hasOwnProperty(node.nodeName )) {89 if (!leaving && newlineElements.hasOwnProperty(node.nodeName.toUpperCase())) { 90 90 leaving = true; 91 91 if (!atEnd || !top) … … 176 176 return yield(node.currentText, c); 177 177 } 178 else if ( node.nodeName == "BR") {178 else if (isBR(node)) { 179 179 nodeQueue.push(node); 180 180 return yield("\n", c); … … 196 196 // Determine the text size of a processed node. 197 197 function nodeSize(node) { 198 if (node.nodeName == "BR") 199 return 1; 200 else 201 return node.currentText.length; 198 return isBR(node) ? 1 : node.currentText.length; 202 199 } 203 200 … … 205 202 // the start of the frame. 206 203 function startOfLine(node) { 207 while (node && node.nodeName != "BR") node = node.previousSibling;204 while (node && !isBR(node)) node = node.previousSibling; 208 205 return node; 209 206 } 210 207 function endOfLine(node, container) { 211 208 if (!node) node = container.firstChild; 212 else if ( node.nodeName == "BR") node = node.nextSibling;213 214 while (node && node.nodeName != "BR") node = node.nextSibling;209 else if (isBR(node)) node = node.nextSibling; 210 211 while (node && !isBR(node)) node = node.nextSibling; 215 212 return node; 216 213 } … … 224 221 // skip to the next find. Use the select and replace methods to 225 222 // actually do something with the found locations. 226 function SearchCursor(editor, string, fromCursor ) {223 function SearchCursor(editor, string, fromCursor, caseFold) { 227 224 this.editor = editor; 225 this.caseFold = caseFold; 226 if (caseFold) string = string.toLowerCase(); 228 227 this.history = editor.history; 229 228 this.history.commit(); … … 253 252 // indexOf on the current line. 254 253 function() { 255 var match = cleanText(self.history.textAfter(self.line).slice(self.offset)).indexOf(string); 254 var line = cleanText(self.history.textAfter(self.line).slice(self.offset)); 255 var match = (self.caseFold ? line.toLowerCase() : line).indexOf(string); 256 256 if (match > -1) 257 257 return {from: {node: self.line, offset: self.offset + match}, … … 263 263 function() { 264 264 var firstLine = cleanText(self.history.textAfter(self.line).slice(self.offset)); 265 var match = firstLine.lastIndexOf(target[0]);265 var match = (self.caseFold ? firstLine.toLowerCase() : firstLine).lastIndexOf(target[0]); 266 266 if (match == -1 || match != firstLine.length - target[0].length) 267 267 return false; … … 270 270 var line = self.history.nodeAfter(self.line); 271 271 for (var i = 1; i < target.length - 1; i++) { 272 if (cleanText(self.history.textAfter(line)) != target[i]) 272 var line = cleanText(self.history.textAfter(line)); 273 if ((self.caseFold ? line.toLowerCase() : line) != target[i]) 273 274 return false; 274 275 line = self.history.nodeAfter(line); 275 276 } 276 277 277 if (cleanText(self.history.textAfter(line)).indexOf(target[target.length - 1]) != 0) 278 var lastLine = cleanText(self.history.textAfter(line)); 279 if ((self.caseFold ? lastLine.toLowerCase() : lastLine).indexOf(target[target.length - 1]) != 0) 278 280 return false; 279 281 … … 367 369 if (options.content) 368 370 this.importCode(options.content); 369 else // FF acts weird when the editable document is completely empty370 container.appendChild(this.doc.createElement("BR"));371 371 372 372 if (!options.readOnly) { … … 403 403 404 404 addEventHandler(document, "keydown", method(this, "keyDown")); 405 addEventHandler(document, "keypress", method(this, "keyPress")); 406 addEventHandler(document, "keyup", method(this, "keyUp")); 405 407 406 408 function cursorActivity() {self.cursorActivity(false);} … … 418 420 if (text !== null) { 419 421 self.replaceSelection(text); 422 select.scrollToCursor(this.container); 420 423 event.stop(); 421 424 } 422 425 }); 423 424 addEventHandler(document.body, "beforepaste", method(this, "reroutePasteEvent"));425 426 426 427 if (this.options.autoMatchParens) … … 505 506 var accum = []; 506 507 for (line = line ? line.nextSibling : this.container.firstChild; 507 line && line.nodeName != "BR"; line = line.nextSibling)508 line && !isBR(line); line = line.nextSibling) 508 509 accum.push(nodeText(line)); 509 510 return cleanText(accum.join("")); … … 530 531 break; 531 532 } 532 var text = (cur.innerText || cur.textContent || cur.nodeValue || "");533 var text = nodeText(cur); 533 534 if (text.length > position) { 534 535 before = cur.nextSibling; … … 587 588 var te = parent.document.createElement("TEXTAREA"); 588 589 te.style.position = "absolute"; 589 te.style.left = "- 500px";590 te.style.left = "-10000px"; 590 591 te.style.width = "10px"; 591 592 te.style.top = nodeTop(frameElement) + "px"; 592 parent.document.body.appendChild(te);593 window.frameElement.CodeMirror.wrapping.appendChild(te); 593 594 parent.focus(); 594 595 te.focus(); … … 599 600 self.win.focus(); 600 601 if (self.selectionSnapshot) // IE hack 601 self.win.select.se lectCoords(self.win, self.selectionSnapshot);602 self.win.select.setBookmark(self.container, self.selectionSnapshot); 602 603 var text = te.value; 603 if (text) self.replaceSelection(text); 604 if (text) { 605 self.replaceSelection(text); 606 select.scrollToCursor(self.container); 607 } 604 608 removeElement(te); 605 609 }, 10); … … 617 621 }, 618 622 619 getSearchCursor: function(string, fromCursor ) {620 return new SearchCursor(this, string, fromCursor );623 getSearchCursor: function(string, fromCursor, caseFold) { 624 return new SearchCursor(this, string, fromCursor, caseFold); 621 625 }, 622 626 … … 698 702 } 699 703 else if (code == 36 && !event.shiftKey && !event.ctrlKey) { // home 700 if (this.home()) 701 event.stop(); 704 if (this.home()) event.stop(); 705 } 706 else if (code == 35 && !event.shiftKey && !event.ctrlKey) { // end 707 if (this.end()) event.stop(); 702 708 } 703 709 else if ((code == 219 || code == 221) && event.ctrlKey && !event.altKey) { // [, ] … … 728 734 this.options.saveFunction(); 729 735 event.stop(); 736 } 737 else if (internetExplorer && code == 86) { 738 this.reroutePasteEvent(); 730 739 } 731 740 } … … 840 849 }, 841 850 851 // Custom home behaviour that doesn't land the cursor in front of 852 // leading whitespace unless pressed twice. 842 853 home: function() { 843 854 var cur = select.selectionTopNode(this.container, true), start = cur; 844 if (cur === false || !(!cur || cur.isPart || cur.nodeName == "BR") || !this.container.firstChild)855 if (cur === false || !(!cur || cur.isPart || isBR(cur)) || !this.container.firstChild) 845 856 return false; 846 857 847 while (cur && cur.nodeName != "BR") cur = cur.previousSibling;858 while (cur && !isBR(cur)) cur = cur.previousSibling; 848 859 var next = cur ? cur.nextSibling : this.container.firstChild; 849 860 if (next && next != start && next.isPart && hasClass(next, "whitespace")) … … 852 863 select.focusAfterNode(cur, this.container); 853 864 865 select.scrollToCursor(this.container); 866 return true; 867 }, 868 869 // Some browsers (Opera) don't manage to handle the end key 870 // properly in the face of vertical scrolling. 871 end: function() { 872 var cur = select.selectionTopNode(this.container, true); 873 if (cur === false) return false; 874 cur = endOfLine(cur, this.container); 875 if (!cur) return false; 876 select.focusAfterNode(cur.previousSibling, this.container); 854 877 select.scrollToCursor(this.container); 855 878 return true; … … 900 923 var stack = [], ch, ok = true;; 901 924 for (var runner = cursor; runner; runner = dir ? runner.nextSibling : runner.previousSibling) { 902 if (runner.className == className && runner.nodeName == "SPAN"&& (ch = paren(runner))) {925 if (runner.className == className && isSpan(runner) && (ch = paren(runner))) { 903 926 if (forward(ch) == dir) 904 927 stack.push(ch); … … 909 932 if (!stack.length) break; 910 933 } 911 else if (runner.dirty || runner.nodeName != "SPAN" && runner.nodeName != "BR") {934 else if (runner.dirty || !isSpan(runner) && !isBR(runner)) { 912 935 return {node: runner, status: "dirty"}; 913 936 } … … 945 968 // the cursor is on so that it is indented properly. 946 969 indentAtCursor: function(direction) { 970 return; 947 971 if (!this.container.firstChild) return; 948 972 // The line has to have up-to-date lexical information, so we 949 973 // highlight it first. 950 974 if (!this.highlightAtCursor()) return; 951 // prevent indent for now.952 return;953 975 var cursor = select.selectionTopNode(this.container, false); 954 976 // If we couldn't determine the place of the cursor, … … 969 991 indentRegion: function(start, end, direction) { 970 992 var current = (start = startOfLine(start)), before = start && startOfLine(start.previousSibling); 971 if ( end.nodeName != "BR") end = endOfLine(end, this.container);993 if (!isBR(end)) end = endOfLine(end, this.container); 972 994 973 995 do { … … 986 1008 if (internetExplorer) { 987 1009 this.container.createTextRange().execCommand("unlink"); 988 this.selectionSnapshot = select. selectionCoords(this.win);1010 this.selectionSnapshot = select.getBookmark(this.container); 989 1011 } 990 1012 … … 996 1018 if (activity) activity(cursor); 997 1019 if (!safe) { 998 this.scheduleHighlight();1020 // this.scheduleHighlight(); 999 1021 this.addDirtyNode(cursor); 1000 1022 } … … 1128 1150 // parse stored. 1129 1151 while (from && (!from.parserFromHere || from.dirty)) { 1130 if (maxBacktrack != null && from.nodeName == "BR"&& (--maxBacktrack) < 0)1152 if (maxBacktrack != null && isBR(from) && (--maxBacktrack) < 0) 1131 1153 return false; 1132 1154 from = from.previousSibling; … … 1209 1231 // for the FF cursor bug workaround (see select.js, 1210 1232 // insertNewlineAtCursor). 1211 while (part && part.nodeName == "SPAN"&& part.currentText == "") {1233 while (part && isSpan(part) && part.currentText == "") { 1212 1234 var old = part; 1213 1235 this.remove(); … … 1231 1253 // The idea of the two streams actually staying synchronized 1232 1254 // is such a long shot that we explicitly check. 1233 if ( part.nodeName != "BR")1255 if (!isBR(part)) 1234 1256 throw "Parser out of sync. Expected BR."; 1235 1257 … … 1259 1281 } 1260 1282 else { 1261 if ( part.nodeName != "SPAN")1283 if (!isSpan(part)) 1262 1284 throw "Parser out of sync. Expected SPAN."; 1263 1285 if (part.dirty) -
branches/greyhound/mt-static/codemirror/js/mirrorframe.js
r4158 r4932 37 37 var first = true; 38 38 do { 39 var cursor = this.mirror.getSearchCursor(text, first );39 var cursor = this.mirror.getSearchCursor(text, first, true); 40 40 first = false; 41 41 while (cursor.findNext()) { -
branches/greyhound/mt-static/codemirror/js/parsejavascript.js
r4158 r4932 11 11 // Token types that can be considered to be atoms. 12 12 var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; 13 // Setting that can be used to have JSON data indent properly. 14 var json = false; 13 15 // Constructor for the lexical context objects. 14 16 function JSLexical(indented, column, type, align, prev, info) { … … 231 233 else if (type == "keyword a") cont(pushlex("form"), expression, statement, poplex); 232 234 else if (type == "keyword b") cont(pushlex("form"), statement, poplex); 235 else if (type == "{" && json) cont(pushlex("}"), commasep(objprop, "}"), poplex); 233 236 else if (type == "{") cont(pushlex("}"), block, poplex); 234 237 else if (type == "function") cont(functiondef); … … 338 341 } 339 342 340 return {make: parseJS, electricChars: "{}:"}; 343 return { 344 make: parseJS, 345 electricChars: "{}:", 346 configure: function(obj) { 347 if (obj.json != null) json = obj.json; 348 } 349 }; 341 350 })(); -
branches/greyhound/mt-static/codemirror/js/select.js
r4587 r4932 38 38 || !element.nextSibling.nextSibling.nextSibling; 39 39 // In Opera (and recent Webkit versions), BR elements *always* 40 // have a scrollTop property of zero.40 // have a offsetTop property of zero. 41 41 var compensateHack = 0; 42 42 while (element && !element.offsetTop) { … … 53 53 y += pos.offsetTop; 54 54 // Don't count X offset for <br> nodes 55 if ( pos.nodeName != "BR")55 if (!isBR(pos)) 56 56 x += pos.offsetLeft; 57 57 pos = pos.offsetParent; … … 248 248 if (cur) { 249 249 try{range.moveToElementText(cur);} 250 catch(e){ }250 catch(e){return false;} 251 251 range.collapse(false); 252 252 } … … 254 254 if (count) range.move("character", count); 255 255 } 256 else range.moveToElementText(node); 256 else { 257 try{range.moveToElementText(node);} 258 catch(e){return false;} 259 } 260 return true; 257 261 } 258 262 … … 263 267 var middle = Math.ceil((end + start) / 2), node = container.childNodes[middle]; 264 268 if (!node) return false; // Don't ask. IE6 manages this sometimes. 265 moveToNodeStart(range2, node);269 if (!moveToNodeStart(range2, node)) return false; 266 270 if (range.compareEndPoints("StartToStart", range2) == 1) 267 271 start = middle; … … 315 319 316 320 var topNode = select.selectionTopNode(container, start); 317 while (topNode && topNode.nodeName != "BR")321 while (topNode && !isBR(topNode)) 318 322 topNode = topNode.previousSibling; 319 323 … … 357 361 358 362 // Some hacks for storing and re-storing the selection when the editor loses and regains focus. 359 select.selectionCoords = function (win) { 360 var selection = win.document.selection; 361 if (!selection) return null; 362 var start = selection.createRange(), end = start.duplicate(); 363 start.collapse(true); 364 end.collapse(false); 365 366 var body = win.document.body; 367 return {start: {x: start.boundingLeft + body.scrollLeft - 1, 368 y: start.boundingTop + body.scrollTop}, 369 end: {x: end.boundingLeft + body.scrollLeft - 1, 370 y: end.boundingTop + body.scrollTop}}; 363 select.getBookmark = function (container) { 364 var from = select.cursorPos(container, true), to = select.cursorPos(container, false); 365 if (from && to) return {from: from, to: to}; 371 366 }; 372 367 373 368 // Restore a stored selection. 374 select.selectCoords = function(win, coords) { 375 if (!coords) return; 376 377 var range1 = win.document.body.createTextRange(), range2 = range1.duplicate(); 378 // This can fail for various hard-to-handle reasons. 379 try { 380 range1.moveToPoint(coords.start.x, coords.start.y); 381 range2.moveToPoint(coords.end.x, coords.end.y); 382 range1.setEndPoint("EndToStart", range2); 383 range1.select(); 384 } catch(e) {} 369 select.setBookmark = function(container, mark) { 370 if (!mark) return; 371 select.setCursorPos(container, mark.from, mark.to); 385 372 }; 386 373 } … … 408 395 // until a 'leaf' is reached (or is it *up* the DOM tree?). 409 396 function normalize(point){ 410 while (point.node.nodeType != 3 && point.node.nodeName != "BR") {397 while (point.node.nodeType != 3 && !isBR(point.node)) { 411 398 var newNode = point.node.childNodes[point.offset] || point.node.nextSibling; 412 399 point.offset = 0; … … 426 413 427 414 select.selectMarked = function () { 428 if (!currentSelection || !currentSelection.changed) return; 429 var win = currentSelection.window, range = win.document.createRange(); 415 var cs = currentSelection; 416 if (!(cs && (cs.changed || (webkit && cs.start.node == cs.end.node)))) return; 417 var win = cs.window, range = win.document.createRange(); 430 418 431 419 function setPoint(point, which) { … … 443 431 } 444 432 445 setPoint(c urrentSelection.end, "End");446 setPoint(c urrentSelection.start, "Start");433 setPoint(cs.end, "End"); 434 setPoint(cs.start, "Start"); 447 435 selectRange(range, win); 448 436 }; … … 472 460 // Work around (yet another) bug in Opera's selection model. 473 461 if (window.opera && !start && range.endContainer == container && range.endOffset == range.startOffset + 1 && 474 container.childNodes[range.startOffset] && container.childNodes[range.startOffset].nodeName == "BR")462 container.childNodes[range.startOffset] && isBR(container.childNodes[range.startOffset])) 475 463 offset--; 476 464 … … 487 475 // selection. If the offset is 0, we take the start of the frame 488 476 // ('after null'), otherwise, we take the last node. 489 else if (node.nodeName == "HTML") {477 else if (node.nodeName.toUpperCase() == "HTML") { 490 478 return (offset == 1 ? null : container.lastChild); 491 479 } … … 558 546 559 547 var topNode = select.selectionTopNode(container, start); 560 while (topNode && topNode.nodeName != "BR")548 while (topNode && !isBR(topNode)) 561 549 topNode = topNode.previousSibling; 562 550 -
branches/greyhound/mt-static/codemirror/js/tokenizejavascript.js
r4158 r4932 49 49 50 50 // Some helper regexps 51 var isOperatorChar = /[+\-*&% \/=<>!?|]/;51 var isOperatorChar = /[+\-*&%=<>!?|]/; 52 52 var isHexDigit = /[0-9A-Fa-f]/; 53 53 var isWordChar = /[\w\$_]/; -
branches/greyhound/mt-static/codemirror/js/undo.js
r4587 r4932 110 110 } 111 111 this.pushChains([chain], from == null && to == null); 112 if (this.onChange) this.onChange(); 112 113 }, 113 114 … … 251 252 var text = []; 252 253 for (var cur = node ? node.nextSibling : self.container.firstChild; 253 cur && cur.nodeName != "BR"; cur = cur.nextSibling)254 cur && !isBR(cur); cur = cur.nextSibling) 254 255 if (cur.currentText) text.push(cur.currentText); 255 256 return {from: node, to: cur, text: cleanText(text.join(""))}; … … 276 277 function nextBR(node, dir) { 277 278 var link = dir + "Sibling", search = node[link]; 278 while (search && search.nodeName != "BR")279 while (search && !isBR(search)) 279 280 search = search[link]; 280 281 return search; -
branches/greyhound/mt-static/codemirror/js/util.js
r4587 r4932 113 113 114 114 function nodeText(node) { 115 return node. innerText || node.textContent || node.nodeValue || "";115 return node.textContent || node.innerText || node.nodeValue || ""; 116 116 } 117 117 … … 124 124 return top; 125 125 } 126 127 function isBR(node) { 128 var nn = node.nodeName; 129 return nn == "BR" || nn == "br"; 130 } 131 function isSpan(node) { 132 var nn = node.nodeName; 133 return nn == "SPAN" || nn == "span"; 134 } -
branches/greyhound/mt-static/codemirror/manual.html
r4587 r4932 234 234 235 235 <dt><code>undoDepth</code></dt><dd>Maximum length of the undo 236 history. Default is 50.</dd> 236 history. Default is 50. This setting is changeable with the 237 <code>setUndoDepth(depth)</code> method on CodeMirror 238 instances.</dd> 237 239 238 240 <dt><code>onChange</code></dt><dd>An optional function of zero … … 252 254 disable spell-checking on browsers that support it (Firefox 2+). 253 255 Default is <code>true</code>, since for most code spell-checking 254 is useless.</dd> 256 is useless. Can be changed with the 257 <code>setSpellCheck(on)</code> method.</dd> 255 258 256 259 <dt><code>textWrapping</code></dt><dd>Can be used to disable or 257 260 enable text-wrapping in the editor frame. Default is 258 <code>true</code>.</dd> 261 <code>true</code>. Changeable with the 262 <code>setTextWrapping(on)</code> method.</dd> 259 263 260 264 <dt><code>lineNumbers</code></dt><dd>Show line numbers to the … … 268 272 <code>false</code>. When enabling this, you have to disable 269 273 <code>textWrapping</code>, since the line numbers don't take 270 wrapped lines into account.</dd> 274 wrapped lines into account. Changeable with the 275 <code>setLineNumbers(on)</code> method.</dd> 271 276 272 277 <dt><code>indentUnit</code></dt><dd>An integer that specifies 273 278 the amount of spaces one 'level' of indentation should add. 274 Default is <code>2</code>.</dd> 279 Default is <code>2</code>. Changeable in a running editor using 280 the <code>setIndentUnit(spaces)</code> method.</dd> 275 281 276 282 <dt><code>tabMode</code></dt><dd>Determines what the effect of … … 290 296 deeper, pressing shift-tab or ctrl-tab (whichever your browser 291 297 does not interfere with), un-indents it.</dd> 292 </dl></dd> 298 </dl> 299 This option can be changed at run-time using the 300 <code>setTabMode(mode)</code> method.</dd> 293 301 294 302 <dt><code>reindentOnLoad</code></dt><dd>When <code>true</code>, … … 356 364 href="jstest.html">demo</a>)</dt><dd>The JavaScript parser. 357 365 Example colours in <code><a 358 href="css/jscolors.css">css/jscolors.css</a></code></dd> 366 href="css/jscolors.css">css/jscolors.css</a></code>. Takes one 367 configuration option, <code>json</code>, that can be set when 368 the editor content is JSON data. It causes every opening brace 369 to be treated as the start of an object, rather than a 370 block.</dd> 359 371 360 372 <dt><code><a href="js/parsecss.js">parsecss.js</a></code> (<a … … 404 416 plain editable field, without any accompanying buttons, bells, and 405 417 whistles. <code>CodeMirror</code> objects do, however, provide a 406 number of methods that make it possible to add extra functionality 407 around the editor. <a 408 href="js/mirrorframe.js"><code>mirrorframe.js</code></a> provides a 409 basic example of their usage.</p> 418 number of methods and properties that make it possible to add 419 extra functionality around the editor. <a 420 href="js/mirrorframe.js"><code>mirrorframe.js</code></a> provides 421 a basic example of their usage.</p> 422 423 <h3>Properties</h3> 410 424 411 425 <dl> 412 426 <dt><code>frame</code></dt><dd>The editable frame.</dd> 427 <dt><code>win</code></dt><dd>The window of the editable frame. 428 Mostly useful for attaching event handlers.</dd> 429 <dt><code>wrapping</code></dt><dd>The <code>DIV</code> element 430 wrapped around the frame. This always has a CSS class of 431 <code>CodeMirror-wrapping</code>.</dd> 432 </dl> 433 434 <h3>Methods</h3> 435 436 <dl> 413 437 <dt><code>getCode()</code> → 414 438 <code>string</code></dt><dd>Returns the current content of the … … 444 468 re-indent the selected lines.</dd> 445 469 446 <dt><code>getSearchCursor(string, atCursor )</code> →447 <code>cursor</code></dt><dd>The first argument indicates the448 string that should be searched for, and the second indicates470 <dt><code>getSearchCursor(string, atCursor, caseFold)</code> 471 → <code>cursor</code></dt><dd>The first argument indicates 472 the string that should be searched for, and the second indicates 449 473 whether searching should start at the cursor (<code>true</code>) 450 or at the start of the document (<code>false</code>). Returns an 451 object that provides an interface for searching. Call its 452 <code>findNext()</code> method to search for an occurrence of 453 the given string. This returns <code>true</code> if something is 454 found, or <code>false</code> if the end of document is reached. 455 When an occurrence has been found, you can call 456 <code>select()</code> to select it, or 474 or at the start of the document (<code>false</code>). When 475 <code>caseFold</code> is true, the search will be 476 case-insensivive. Returns an object that provides an interface 477 for searching. Call its <code>findNext()</code> method to search 478 for an occurrence of the given string. This returns 479 <code>true</code> if something is found, or <code>false</code> 480 if the end of document is reached. When an occurrence has been 481 found, you can call <code>select()</code> to select it, or 457 482 <code>replace(string)</code> to replace it with a given string. 458 483 Note that letting the user change the document, or -
branches/greyhound/tmpl/cms/edit_template.tmpl
r4858 r4932 775 775 tabMode: "default", 776 776 indentUnit: 0, 777 height: "500px" 777 height: "500px", 778 lang: "<mt:var name="language_tag">" 778 779 }); 779 780 /* ]]> */
