Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(730)

Side by Side Diff: Source/devtools/front_end/cm/codemirror.js

Issue 273763003: DevTools: [CodeMirror] roll codemirror to @687fb51 (Closed) Base URL: https://chromium.googlesource.com/chromium/blink@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // CodeMirror 4.1.1, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
3
1 // This is CodeMirror (http://codemirror.net), a code editor 4 // This is CodeMirror (http://codemirror.net), a code editor
2 // implemented in JavaScript on top of the browser's DOM. 5 // implemented in JavaScript on top of the browser's DOM.
3 // 6 //
4 // You can find some technical background for some of the code below 7 // You can find some technical background for some of the code below
5 // at http://marijnhaverbeke.nl/blog/#cm-internals . 8 // at http://marijnhaverbeke.nl/blog/#cm-internals .
6 9
7 (function(mod) { 10 (function(mod) {
8 if (typeof exports == "object" && typeof module == "object") // CommonJS 11 if (typeof exports == "object" && typeof module == "object") // CommonJS
9 module.exports = mod(); 12 module.exports = mod();
10 else if (typeof define == "function" && define.amd) // AMD 13 else if (typeof define == "function" && define.amd) // AMD
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edit s in readInput 89 pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edit s in readInput
87 draggingText: false, 90 draggingText: false,
88 highlight: new Delayed() // stores highlight worker timeout 91 highlight: new Delayed() // stores highlight worker timeout
89 }; 92 };
90 93
91 // Override magic textarea content restore that IE sometimes does 94 // Override magic textarea content restore that IE sometimes does
92 // on our hidden textarea on reload 95 // on our hidden textarea on reload
93 if (ie_upto10) setTimeout(bind(resetInput, this, true), 20); 96 if (ie_upto10) setTimeout(bind(resetInput, this, true), 20);
94 97
95 registerEventHandlers(this); 98 registerEventHandlers(this);
99 ensureGlobalHandlers();
96 100
97 var cm = this; 101 var cm = this;
98 runInOp(this, function() { 102 runInOp(this, function() {
99 cm.curOp.forceUpdate = true; 103 cm.curOp.forceUpdate = true;
100 attachDoc(cm, doc); 104 attachDoc(cm, doc);
101 105
102 if ((options.autofocus && !mobile) || activeElt() == display.input) 106 if ((options.autofocus && !mobile) || activeElt() == display.input)
103 setTimeout(bind(onFocus, cm), 20); 107 setTimeout(bind(onFocus, cm), 20);
104 else 108 else
105 onBlur(cm); 109 onBlur(cm);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 // can be kept static when scrolling. 227 // can be kept static when scrolling.
224 d.maxLine = null; 228 d.maxLine = null;
225 d.maxLineLength = 0; 229 d.maxLineLength = 0;
226 d.maxLineChanged = false; 230 d.maxLineChanged = false;
227 231
228 // Used for measuring wheel scrolling granularity 232 // Used for measuring wheel scrolling granularity
229 d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; 233 d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
230 234
231 // True when shift is held down. 235 // True when shift is held down.
232 d.shift = false; 236 d.shift = false;
237
238 // Used to track whether anything happened since the context menu
239 // was opened.
240 d.selForContextMenu = null;
233 } 241 }
234 242
235 // STATE UPDATES 243 // STATE UPDATES
236 244
237 // Used to get the editor into a consistent state again when options change. 245 // Used to get the editor into a consistent state again when options change.
238 246
239 function loadMode(cm) { 247 function loadMode(cm) {
240 cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); 248 cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
241 resetModeState(cm); 249 resetModeState(cm);
242 } 250 }
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 on(d.scrollbarH, "mousedown", barMouseDown); 456 on(d.scrollbarH, "mousedown", barMouseDown);
449 } 457 }
450 cm.state.checkedOverlayScrollbar = true; 458 cm.state.checkedOverlayScrollbar = true;
451 } 459 }
452 } 460 }
453 461
454 // Compute the lines that are visible in a given viewport (defaults 462 // Compute the lines that are visible in a given viewport (defaults
455 // the the current scroll position). viewPort may contain top, 463 // the the current scroll position). viewPort may contain top,
456 // height, and ensure (see op.scrollToPos) properties. 464 // height, and ensure (see op.scrollToPos) properties.
457 function visibleLines(display, doc, viewPort) { 465 function visibleLines(display, doc, viewPort) {
458 var top = viewPort && viewPort.top != null ? viewPort.top : display.scroller .scrollTop; 466 var top = viewPort && viewPort.top != null ? Math.max(0, viewPort.top) : dis play.scroller.scrollTop;
459 top = Math.floor(top - paddingTop(display)); 467 top = Math.floor(top - paddingTop(display));
460 var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + d isplay.wrapper.clientHeight; 468 var bottom = viewPort && viewPort.bottom != null ? viewPort.bottom : top + d isplay.wrapper.clientHeight;
461 469
462 var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); 470 var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
463 // Ensure is a {from: {line, ch}, to: {line, ch}} object, and 471 // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
464 // forces those lines into the viewport (if possible). 472 // forces those lines into the viewport (if possible).
465 if (viewPort && viewPort.ensure) { 473 if (viewPort && viewPort.ensure) {
466 var ensureFrom = viewPort.ensure.from.line, ensureTo = viewPort.ensure.to. line; 474 var ensureFrom = viewPort.ensure.from.line, ensureTo = viewPort.ensure.to. line;
467 if (ensureFrom < from) 475 if (ensureFrom < from)
468 return {from: ensureFrom, 476 return {from: ensureFrom,
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 display.sizer.style.minWidth = minWidth + "px"; 660 display.sizer.style.minWidth = minWidth + "px";
653 if (maxScrollLeft < cm.doc.scrollLeft) 661 if (maxScrollLeft < cm.doc.scrollLeft)
654 setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), tr ue); 662 setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), tr ue);
655 } 663 }
656 664
657 function setDocumentHeight(cm, measure) { 665 function setDocumentHeight(cm, measure) {
658 cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = measu re.docHeight + "px"; 666 cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = measu re.docHeight + "px";
659 cm.display.gutters.style.height = Math.max(measure.docHeight, measure.client Height - scrollerCutOff) + "px"; 667 cm.display.gutters.style.height = Math.max(measure.docHeight, measure.client Height - scrollerCutOff) + "px";
660 } 668 }
661 669
662
663 function checkForWebkitWidthBug(cm, measure) { 670 function checkForWebkitWidthBug(cm, measure) {
664 // Work around Webkit bug where it sometimes reserves space for a 671 // Work around Webkit bug where it sometimes reserves space for a
665 // non-existing phantom scrollbar in the scroller (Issue #2420) 672 // non-existing phantom scrollbar in the scroller (Issue #2420)
666 if (cm.display.sizer.offsetWidth + cm.display.gutters.offsetWidth < cm.displ ay.scroller.clientWidth - 1) { 673 if (cm.display.sizer.offsetWidth + cm.display.gutters.offsetWidth < cm.displ ay.scroller.clientWidth - 1) {
667 cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = "0p x"; 674 cm.display.sizer.style.minHeight = cm.display.heightForcer.style.top = "0p x";
668 cm.display.gutters.style.height = measure.docHeight + "px"; 675 cm.display.gutters.style.height = measure.docHeight + "px";
669 } 676 }
670 } 677 }
671 678
672 // Read the actual heights of the rendered lines, and update their 679 // Read the actual heights of the rendered lines, and update their
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after
1614 while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mS tart + end))) ++end; 1621 while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mS tart + end))) ++end;
1615 if (ie_upto8 && start == 0 && end == mEnd - mStart) { 1622 if (ie_upto8 && start == 0 && end == mEnd - mStart) {
1616 rect = node.parentNode.getBoundingClientRect(); 1623 rect = node.parentNode.getBoundingClientRect();
1617 } else if (ie && cm.options.lineWrapping) { 1624 } else if (ie && cm.options.lineWrapping) {
1618 var rects = range(node, start, end).getClientRects(); 1625 var rects = range(node, start, end).getClientRects();
1619 if (rects.length) 1626 if (rects.length)
1620 rect = rects[bias == "right" ? rects.length - 1 : 0]; 1627 rect = rects[bias == "right" ? rects.length - 1 : 0];
1621 else 1628 else
1622 rect = nullRect; 1629 rect = nullRect;
1623 } else { 1630 } else {
1624 rect = range(node, start, end).getBoundingClientRect(); 1631 rect = range(node, start, end).getBoundingClientRect() || nullRect;
1625 } 1632 }
1626 } else { // If it is a widget, simply get the box for the whole widget. 1633 } else { // If it is a widget, simply get the box for the whole widget.
1627 if (start > 0) collapse = bias = "right"; 1634 if (start > 0) collapse = bias = "right";
1628 var rects; 1635 var rects;
1629 if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) 1636 if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
1630 rect = rects[bias == "right" ? rects.length - 1 : 0]; 1637 rect = rects[bias == "right" ? rects.length - 1 : 0];
1631 else 1638 else
1632 rect = node.getBoundingClientRect(); 1639 rect = node.getBoundingClientRect();
1633 } 1640 }
1634 if (ie_upto8 && !start && (!rect || !rect.left && !rect.right)) { 1641 if (ie_upto8 && !start && (!rect || !rect.left && !rect.right)) {
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
1915 op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || 1922 op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
1916 op.scrollToPos.to.line >= display.viewTo) || 1923 op.scrollToPos.to.line >= display.viewTo) ||
1917 display.maxLineChanged && cm.options.lineWrapping) { 1924 display.maxLineChanged && cm.options.lineWrapping) {
1918 var updated = updateDisplay(cm, {top: op.scrollTop, ensure: op.scrollToPos }, op.forceUpdate); 1925 var updated = updateDisplay(cm, {top: op.scrollTop, ensure: op.scrollToPos }, op.forceUpdate);
1919 if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroll er.scrollTop; 1926 if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroll er.scrollTop;
1920 } 1927 }
1921 // If no update was run, but the selection changed, redraw that. 1928 // If no update was run, but the selection changed, redraw that.
1922 if (!updated && op.selectionChanged) updateSelection(cm); 1929 if (!updated && op.selectionChanged) updateSelection(cm);
1923 if (!updated && op.startHeight != cm.doc.height) updateScrollbars(cm); 1930 if (!updated && op.startHeight != cm.doc.height) updateScrollbars(cm);
1924 1931
1932 // Abort mouse wheel delta measurement, when scrolling explicitly
1933 if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
1934 display.wheelStartX = display.wheelStartY = null;
1935
1925 // Propagate the scroll position to the actual DOM scroller 1936 // Propagate the scroll position to the actual DOM scroller
1926 if (op.scrollTop != null && display.scroller.scrollTop != op.scrollTop) { 1937 if (op.scrollTop != null && display.scroller.scrollTop != op.scrollTop) {
1927 var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scr oller.clientHeight, op.scrollTop)); 1938 var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scr oller.clientHeight, op.scrollTop));
1928 display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top; 1939 display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top;
1929 } 1940 }
1930 if (op.scrollLeft != null && display.scroller.scrollLeft != op.scrollLeft) { 1941 if (op.scrollLeft != null && display.scroller.scrollLeft != op.scrollLeft) {
1931 var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scr oller.clientWidth, op.scrollLeft)); 1942 var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scr oller.clientWidth, op.scrollLeft));
1932 display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLe ft = left; 1943 display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLe ft = left;
1933 alignHorizontally(cm); 1944 alignHorizontally(cm);
1934 } 1945 }
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
2128 if (n < 0) return null; 2139 if (n < 0) return null;
2129 var view = cm.display.view; 2140 var view = cm.display.view;
2130 for (var i = 0; i < view.length; i++) { 2141 for (var i = 0; i < view.length; i++) {
2131 n -= view[i].size; 2142 n -= view[i].size;
2132 if (n < 0) return i; 2143 if (n < 0) return i;
2133 } 2144 }
2134 } 2145 }
2135 2146
2136 function viewCuttingPoint(cm, oldN, newN, dir) { 2147 function viewCuttingPoint(cm, oldN, newN, dir) {
2137 var index = findViewIndex(cm, oldN), diff, view = cm.display.view; 2148 var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
2138 if (!sawCollapsedSpans) return {index: index, lineN: newN}; 2149 if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
2150 return {index: index, lineN: newN};
2139 for (var i = 0, n = cm.display.viewFrom; i < index; i++) 2151 for (var i = 0, n = cm.display.viewFrom; i < index; i++)
2140 n += view[i].size; 2152 n += view[i].size;
2141 if (n != oldN) { 2153 if (n != oldN) {
2142 if (dir > 0) { 2154 if (dir > 0) {
2143 if (index == view.length - 1) return null; 2155 if (index == view.length - 1) return null;
2144 diff = (n + view[index].size) - oldN; 2156 diff = (n + view[index].size) - oldN;
2145 index++; 2157 index++;
2146 } else { 2158 } else {
2147 diff = n - oldN; 2159 diff = n - oldN;
2148 } 2160 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
2239 // Work around nonsensical selection resetting in IE9/10 2251 // Work around nonsensical selection resetting in IE9/10
2240 if (ie && !ie_upto8 && cm.display.inputHasSelection === text) { 2252 if (ie && !ie_upto8 && cm.display.inputHasSelection === text) {
2241 resetInput(cm); 2253 resetInput(cm);
2242 return false; 2254 return false;
2243 } 2255 }
2244 2256
2245 var withOp = !cm.curOp; 2257 var withOp = !cm.curOp;
2246 if (withOp) startOperation(cm); 2258 if (withOp) startOperation(cm);
2247 cm.display.shift = false; 2259 cm.display.shift = false;
2248 2260
2261 if (text.charCodeAt(0) == 0x200b && doc.sel == cm.display.selForContextMenu && !prevInput)
2262 prevInput = "\u200b";
2249 // Find the part of the input that is actually new 2263 // Find the part of the input that is actually new
2250 var same = 0, l = Math.min(prevInput.length, text.length); 2264 var same = 0, l = Math.min(prevInput.length, text.length);
2251 while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++sa me; 2265 while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++sa me;
2252 var inserted = text.slice(same), textLines = splitLines(inserted); 2266 var inserted = text.slice(same), textLines = splitLines(inserted);
2253 2267
2254 // When pasing N lines into N selections, insert one line per selection 2268 // When pasing N lines into N selections, insert one line per selection
2255 var multiPaste = cm.state.pasteIncoming && textLines.length > 1 && doc.sel.r anges.length == textLines.length; 2269 var multiPaste = cm.state.pasteIncoming && textLines.length > 1 && doc.sel.r anges.length == textLines.length;
2256 2270
2257 // Normal behavior is to insert the new text into every selection 2271 // Normal behavior is to insert the new text into every selection
2258 for (var i = doc.sel.ranges.length - 1; i >= 0; i--) { 2272 for (var i = doc.sel.ranges.length - 1; i >= 0; i--) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2338 function registerEventHandlers(cm) { 2352 function registerEventHandlers(cm) {
2339 var d = cm.display; 2353 var d = cm.display;
2340 on(d.scroller, "mousedown", operation(cm, onMouseDown)); 2354 on(d.scroller, "mousedown", operation(cm, onMouseDown));
2341 // Older IE's will not fire a second mousedown for a double click 2355 // Older IE's will not fire a second mousedown for a double click
2342 if (ie_upto10) 2356 if (ie_upto10)
2343 on(d.scroller, "dblclick", operation(cm, function(e) { 2357 on(d.scroller, "dblclick", operation(cm, function(e) {
2344 if (signalDOMEvent(cm, e)) return; 2358 if (signalDOMEvent(cm, e)) return;
2345 var pos = posFromMouse(cm, e); 2359 var pos = posFromMouse(cm, e);
2346 if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return ; 2360 if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return ;
2347 e_preventDefault(e); 2361 e_preventDefault(e);
2348 var word = findWordAt(cm.doc, pos); 2362 var word = findWordAt(cm, pos);
2349 extendSelection(cm.doc, word.anchor, word.head); 2363 extendSelection(cm.doc, word.anchor, word.head);
2350 })); 2364 }));
2351 else 2365 else
2352 on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preven tDefault(e); }); 2366 on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preven tDefault(e); });
2353 // Prevent normal selection in the editor (we handle our own) 2367 // Prevent normal selection in the editor (we handle our own)
2354 on(d.lineSpace, "selectstart", function(e) { 2368 on(d.lineSpace, "selectstart", function(e) {
2355 if (!eventInWidget(d, e)) e_preventDefault(e); 2369 if (!eventInWidget(d, e)) e_preventDefault(e);
2356 }); 2370 });
2357 // Some browsers fire contextmenu *after* opening the menu, at 2371 // Some browsers fire contextmenu *after* opening the menu, at
2358 // which point we can't mess with it anymore. Context menu is 2372 // which point we can't mess with it anymore. Context menu is
(...skipping 20 matching lines...) Expand all
2379 on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);}); 2393 on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
2380 on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);}); 2394 on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
2381 2395
2382 // Prevent clicks in the scrollbars from killing focus 2396 // Prevent clicks in the scrollbars from killing focus
2383 function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); } 2397 function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
2384 on(d.scrollbarH, "mousedown", reFocus); 2398 on(d.scrollbarH, "mousedown", reFocus);
2385 on(d.scrollbarV, "mousedown", reFocus); 2399 on(d.scrollbarV, "mousedown", reFocus);
2386 // Prevent wrapper from ever scrolling 2400 // Prevent wrapper from ever scrolling
2387 on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollL eft = 0; }); 2401 on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollL eft = 0; });
2388 2402
2389 // When the window resizes, we need to refresh active editors.
2390 var resizeTimer;
2391 function onResize() {
2392 if (resizeTimer == null) resizeTimer = setTimeout(function() {
2393 resizeTimer = null;
2394 // Might be a text scaling operation, clear size caches.
2395 d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = knownScrollb arWidth = null;
2396 cm.setSize();
2397 }, 100);
2398 }
2399 on(window, "resize", onResize);
2400 // The above handler holds on to the editor and its data
2401 // structures. Here we poll to unregister it when the editor is no
2402 // longer in the document, so that it can be garbage-collected.
2403 function unregister() {
2404 if (contains(document.body, d.wrapper)) setTimeout(unregister, 5000);
2405 else off(window, "resize", onResize);
2406 }
2407 setTimeout(unregister, 5000);
2408
2409 on(d.input, "keyup", operation(cm, onKeyUp)); 2403 on(d.input, "keyup", operation(cm, onKeyUp));
2410 on(d.input, "input", function() { 2404 on(d.input, "input", function() {
2411 if (ie && !ie_upto8 && cm.display.inputHasSelection) cm.display.inputHasSe lection = null; 2405 if (ie && !ie_upto8 && cm.display.inputHasSelection) cm.display.inputHasSe lection = null;
2412 fastPoll(cm); 2406 fastPoll(cm);
2413 }); 2407 });
2414 on(d.input, "keydown", operation(cm, onKeyDown)); 2408 on(d.input, "keydown", operation(cm, onKeyDown));
2415 on(d.input, "keypress", operation(cm, onKeyPress)); 2409 on(d.input, "keypress", operation(cm, onKeyPress));
2416 on(d.input, "focus", bind(onFocus, cm)); 2410 on(d.input, "focus", bind(onFocus, cm));
2417 on(d.input, "blur", bind(onBlur, cm)); 2411 on(d.input, "blur", bind(onBlur, cm));
2418 2412
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2475 on(d.input, "cut", prepareCopyCut); 2469 on(d.input, "cut", prepareCopyCut);
2476 on(d.input, "copy", prepareCopyCut); 2470 on(d.input, "copy", prepareCopyCut);
2477 2471
2478 // Needed to handle Tab key in KHTML 2472 // Needed to handle Tab key in KHTML
2479 if (khtml) on(d.sizer, "mouseup", function() { 2473 if (khtml) on(d.sizer, "mouseup", function() {
2480 if (activeElt() == d.input) d.input.blur(); 2474 if (activeElt() == d.input) d.input.blur();
2481 focusInput(cm); 2475 focusInput(cm);
2482 }); 2476 });
2483 } 2477 }
2484 2478
2479 // Called when the window resizes
2480 function onResize(cm) {
2481 // Might be a text scaling operation, clear size caches.
2482 var d = cm.display;
2483 d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
2484 cm.setSize();
2485 }
2486
2485 // MOUSE EVENTS 2487 // MOUSE EVENTS
2486 2488
2487 // Return true when the given mouse event happened in a widget 2489 // Return true when the given mouse event happened in a widget
2488 function eventInWidget(display, e) { 2490 function eventInWidget(display, e) {
2489 for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { 2491 for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
2490 if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display. mover) return true; 2492 if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display. mover) return true;
2491 } 2493 }
2492 } 2494 }
2493 2495
2494 // Given a mouse event, find the corresponding position. If liberal 2496 // Given a mouse event, find the corresponding position. If liberal
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2622 } else { 2624 } else {
2623 ourRange = doc.sel.primary(); 2625 ourRange = doc.sel.primary();
2624 } 2626 }
2625 2627
2626 if (e.altKey) { 2628 if (e.altKey) {
2627 type = "rect"; 2629 type = "rect";
2628 if (!addNew) ourRange = new Range(start, start); 2630 if (!addNew) ourRange = new Range(start, start);
2629 start = posFromMouse(cm, e, true, true); 2631 start = posFromMouse(cm, e, true, true);
2630 ourIndex = -1; 2632 ourIndex = -1;
2631 } else if (type == "double") { 2633 } else if (type == "double") {
2632 var word = findWordAt(doc, start); 2634 var word = findWordAt(cm, start);
2633 if (cm.display.shift || doc.extend) 2635 if (cm.display.shift || doc.extend)
2634 ourRange = extendRange(doc, ourRange, word.anchor, word.head); 2636 ourRange = extendRange(doc, ourRange, word.anchor, word.head);
2635 else 2637 else
2636 ourRange = word; 2638 ourRange = word;
2637 } else if (type == "triple") { 2639 } else if (type == "triple") {
2638 var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0))); 2640 var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));
2639 if (cm.display.shift || doc.extend) 2641 if (cm.display.shift || doc.extend)
2640 ourRange = extendRange(doc, ourRange, line.anchor, line.head); 2642 ourRange = extendRange(doc, ourRange, line.anchor, line.head);
2641 else 2643 else
2642 ourRange = line; 2644 ourRange = line;
(...skipping 25 matching lines...) Expand all
2668 var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol ); 2670 var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol );
2669 for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLi ne(), Math.max(start.line, pos.line)); 2671 for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLi ne(), Math.max(start.line, pos.line));
2670 line <= end; line++) { 2672 line <= end; line++) {
2671 var text = getLine(doc, line).text, leftPos = findColumn(text, left, t abSize); 2673 var text = getLine(doc, line).text, leftPos = findColumn(text, left, t abSize);
2672 if (left == right) 2674 if (left == right)
2673 ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); 2675 ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));
2674 else if (text.length > leftPos) 2676 else if (text.length > leftPos)
2675 ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); 2677 ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
2676 } 2678 }
2677 if (!ranges.length) ranges.push(new Range(start, start)); 2679 if (!ranges.length) ranges.push(new Range(start, start));
2678 setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex). concat(ranges), ourIndex), sel_mouse); 2680 setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex). concat(ranges), ourIndex),
2681 {origin: "*mouse", scroll: false});
2682 cm.scrollIntoView(pos);
2679 } else { 2683 } else {
2680 var oldRange = ourRange; 2684 var oldRange = ourRange;
2681 var anchor = oldRange.anchor, head = pos; 2685 var anchor = oldRange.anchor, head = pos;
2682 if (type != "single") { 2686 if (type != "single") {
2683 if (type == "double") 2687 if (type == "double")
2684 var range = findWordAt(doc, pos); 2688 var range = findWordAt(cm, pos);
2685 else 2689 else
2686 var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))); 2690 var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
2687 if (cmp(range.anchor, anchor) > 0) { 2691 if (cmp(range.anchor, anchor) > 0) {
2688 head = range.head; 2692 head = range.head;
2689 anchor = minPos(oldRange.from(), range.anchor); 2693 anchor = minPos(oldRange.from(), range.anchor);
2690 } else { 2694 } else {
2691 head = range.anchor; 2695 head = range.anchor;
2692 anchor = maxPos(oldRange.to(), range.head); 2696 anchor = maxPos(oldRange.to(), range.head);
2693 } 2697 }
2694 } 2698 }
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
3375 change.origin = type; 3379 change.origin = type;
3376 if (filter && !filterChange(doc, change, false)) { 3380 if (filter && !filterChange(doc, change, false)) {
3377 source.length = 0; 3381 source.length = 0;
3378 return; 3382 return;
3379 } 3383 }
3380 3384
3381 antiChanges.push(historyChangeFromChange(doc, change)); 3385 antiChanges.push(historyChangeFromChange(doc, change));
3382 3386
3383 var after = i ? computeSelAfterChange(doc, change, null) : lst(source); 3387 var after = i ? computeSelAfterChange(doc, change, null) : lst(source);
3384 makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); 3388 makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
3385 if (doc.cm) ensureCursorVisible(doc.cm); 3389 if (!i && doc.cm) doc.cm.scrollIntoView(change);
3386 var rebased = []; 3390 var rebased = [];
3387 3391
3388 // Propagate to the linked documents 3392 // Propagate to the linked documents
3389 linkedDocs(doc, function(doc, sharedHist) { 3393 linkedDocs(doc, function(doc, sharedHist) {
3390 if (!sharedHist && indexOf(rebased, doc.history) == -1) { 3394 if (!sharedHist && indexOf(rebased, doc.history) == -1) {
3391 rebaseHist(doc.history, change); 3395 rebaseHist(doc.history, change);
3392 rebased.push(doc.history); 3396 rebased.push(doc.history);
3393 } 3397 }
3394 makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); 3398 makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
3395 }); 3399 });
3396 } 3400 }
3397 } 3401 }
3398 3402
3399 // Sub-views need their line numbers shifted when text is added 3403 // Sub-views need their line numbers shifted when text is added
3400 // above or below them in the parent document. 3404 // above or below them in the parent document.
3401 function shiftDoc(doc, distance) { 3405 function shiftDoc(doc, distance) {
3406 if (distance == 0) return;
3402 doc.first += distance; 3407 doc.first += distance;
3403 doc.sel = new Selection(map(doc.sel.ranges, function(range) { 3408 doc.sel = new Selection(map(doc.sel.ranges, function(range) {
3404 return new Range(Pos(range.anchor.line + distance, range.anchor.ch), 3409 return new Range(Pos(range.anchor.line + distance, range.anchor.ch),
3405 Pos(range.head.line + distance, range.head.ch)); 3410 Pos(range.head.line + distance, range.head.ch));
3406 }), doc.sel.primIndex); 3411 }), doc.sel.primIndex);
3407 if (doc.cm) regChange(doc.cm, doc.first, doc.first - distance, distance); 3412 if (doc.cm) {
3413 regChange(doc.cm, doc.first, doc.first - distance, distance);
3414 for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
3415 regLineChange(doc.cm, l, "gutter");
3416 }
3408 } 3417 }
3409 3418
3410 // More lower-level change function, handling only a single document 3419 // More lower-level change function, handling only a single document
3411 // (not linked ones). 3420 // (not linked ones).
3412 function makeChangeSingleDoc(doc, change, selAfter, spans) { 3421 function makeChangeSingleDoc(doc, change, selAfter, spans) {
3413 if (doc.cm && !doc.cm.curOp) 3422 if (doc.cm && !doc.cm.curOp)
3414 return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans ); 3423 return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans );
3415 3424
3416 if (change.to.line < doc.first) { 3425 if (change.to.line < doc.first) {
3417 shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line) ); 3426 shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line) );
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
3489 if (changeHandler || changesHandler) { 3498 if (changeHandler || changesHandler) {
3490 var obj = { 3499 var obj = {
3491 from: from, to: to, 3500 from: from, to: to,
3492 text: change.text, 3501 text: change.text,
3493 removed: change.removed, 3502 removed: change.removed,
3494 origin: change.origin 3503 origin: change.origin
3495 }; 3504 };
3496 if (changeHandler) signalLater(cm, "change", cm, obj); 3505 if (changeHandler) signalLater(cm, "change", cm, obj);
3497 if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).pu sh(obj); 3506 if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).pu sh(obj);
3498 } 3507 }
3508 cm.display.selForContextMenu = null;
3499 } 3509 }
3500 3510
3501 function replaceRange(doc, code, from, to, origin) { 3511 function replaceRange(doc, code, from, to, origin) {
3502 if (!to) to = from; 3512 if (!to) to = from;
3503 if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; } 3513 if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
3504 if (typeof code == "string") code = splitLines(code); 3514 if (typeof code == "string") code = splitLines(code);
3505 makeChange(doc, {from: from, to: to, text: code, origin: origin}); 3515 makeChange(doc, {from: from, to: to, text: code, origin: origin});
3506 } 3516 }
3507 3517
3508 // SCROLLING THINGS INTO VIEW 3518 // SCROLLING THINGS INTO VIEW
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
3756 else ch = dir < 0 ? lineObj.text.length : 0; 3766 else ch = dir < 0 ? lineObj.text.length : 0;
3757 } else return (possible = false); 3767 } else return (possible = false);
3758 } else ch = next; 3768 } else ch = next;
3759 return true; 3769 return true;
3760 } 3770 }
3761 3771
3762 if (unit == "char") moveOnce(); 3772 if (unit == "char") moveOnce();
3763 else if (unit == "column") moveOnce(true); 3773 else if (unit == "column") moveOnce(true);
3764 else if (unit == "word" || unit == "group") { 3774 else if (unit == "word" || unit == "group") {
3765 var sawType = null, group = unit == "group"; 3775 var sawType = null, group = unit == "group";
3776 var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
3766 for (var first = true;; first = false) { 3777 for (var first = true;; first = false) {
3767 if (dir < 0 && !moveOnce(!first)) break; 3778 if (dir < 0 && !moveOnce(!first)) break;
3768 var cur = lineObj.text.charAt(ch) || "\n"; 3779 var cur = lineObj.text.charAt(ch) || "\n";
3769 var type = isWordChar(cur) ? "w" 3780 var type = isWordChar(cur, helper) ? "w"
3770 : group && cur == "\n" ? "n" 3781 : group && cur == "\n" ? "n"
3771 : !group || /\s/.test(cur) ? null 3782 : !group || /\s/.test(cur) ? null
3772 : "p"; 3783 : "p";
3773 if (group && !first && !type) type = "s"; 3784 if (group && !first && !type) type = "s";
3774 if (sawType && sawType != type) { 3785 if (sawType && sawType != type) {
3775 if (dir < 0) {dir = 1; moveOnce();} 3786 if (dir < 0) {dir = 1; moveOnce();}
3776 break; 3787 break;
3777 } 3788 }
3778 3789
3779 if (type) sawType = type; 3790 if (type) sawType = type;
(...skipping 19 matching lines...) Expand all
3799 for (;;) { 3810 for (;;) {
3800 var target = coordsChar(cm, x, y); 3811 var target = coordsChar(cm, x, y);
3801 if (!target.outside) break; 3812 if (!target.outside) break;
3802 if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; } 3813 if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
3803 y += dir * 5; 3814 y += dir * 5;
3804 } 3815 }
3805 return target; 3816 return target;
3806 } 3817 }
3807 3818
3808 // Find the word at the given position (as returned by coordsChar). 3819 // Find the word at the given position (as returned by coordsChar).
3809 function findWordAt(doc, pos) { 3820 function findWordAt(cm, pos) {
3810 var line = getLine(doc, pos.line).text; 3821 var doc = cm.doc, line = getLine(doc, pos.line).text;
3811 var start = pos.ch, end = pos.ch; 3822 var start = pos.ch, end = pos.ch;
3812 if (line) { 3823 if (line) {
3824 var helper = cm.getHelper(pos, "wordChars");
3813 if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end; 3825 if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
3814 var startChar = line.charAt(start); 3826 var startChar = line.charAt(start);
3815 var check = isWordChar(startChar) ? isWordChar 3827 var check = isWordChar(startChar, helper)
3828 ? function(ch) { return isWordChar(ch, helper); }
3816 : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} 3829 : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
3817 : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; 3830 : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
3818 while (start > 0 && check(line.charAt(start - 1))) --start; 3831 while (start > 0 && check(line.charAt(start - 1))) --start;
3819 while (end < line.length && check(line.charAt(end))) ++end; 3832 while (end < line.length && check(line.charAt(end))) ++end;
3820 } 3833 }
3821 return new Range(Pos(pos.line, start), Pos(pos.line, end)); 3834 return new Range(Pos(pos.line, start), Pos(pos.line, end));
3822 } 3835 }
3823 3836
3824 // EDITOR METHODS 3837 // EDITOR METHODS
3825 3838
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after
4610 spaces.push(new Array(tabSize - col % tabSize + 1).join(" ")); 4623 spaces.push(new Array(tabSize - col % tabSize + 1).join(" "));
4611 } 4624 }
4612 cm.replaceSelections(spaces); 4625 cm.replaceSelections(spaces);
4613 }, 4626 },
4614 defaultTab: function(cm) { 4627 defaultTab: function(cm) {
4615 if (cm.somethingSelected()) cm.indentSelection("add"); 4628 if (cm.somethingSelected()) cm.indentSelection("add");
4616 else cm.execCommand("insertTab"); 4629 else cm.execCommand("insertTab");
4617 }, 4630 },
4618 transposeChars: function(cm) { 4631 transposeChars: function(cm) {
4619 runInOp(cm, function() { 4632 runInOp(cm, function() {
4620 var ranges = cm.listSelections(); 4633 var ranges = cm.listSelections(), newSel = [];
4621 for (var i = 0; i < ranges.length; i++) { 4634 for (var i = 0; i < ranges.length; i++) {
4622 var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; 4635 var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
4623 if (cur.ch > 0 && cur.ch < line.length - 1) 4636 if (line) {
4624 cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1), 4637 if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
4625 Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1) ); 4638 if (cur.ch > 0) {
4639 cur = new Pos(cur.line, cur.ch + 1);
4640 cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
4641 Pos(cur.line, cur.ch - 2), cur, "+transpose");
4642 } else if (cur.line > cm.doc.first) {
4643 var prev = getLine(cm.doc, cur.line - 1).text;
4644 if (prev)
4645 cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1),
4646 Pos(cur.line - 1, prev.length - 1), Pos(cur.line , 1), "+transpose");
4647 }
4648 }
4649 newSel.push(new Range(cur, cur));
4626 } 4650 }
4651 cm.setSelections(newSel);
4627 }); 4652 });
4628 }, 4653 },
4629 newlineAndIndent: function(cm) { 4654 newlineAndIndent: function(cm) {
4630 runInOp(cm, function() { 4655 runInOp(cm, function() {
4631 var len = cm.listSelections().length; 4656 var len = cm.listSelections().length;
4632 for (var i = 0; i < len; i++) { 4657 for (var i = 0; i < len; i++) {
4633 var range = cm.listSelections()[i]; 4658 var range = cm.listSelections()[i];
4634 cm.replaceRange("\n", range.anchor, range.head, "+input"); 4659 cm.replaceRange("\n", range.anchor, range.head, "+input");
4635 cm.indentLine(range.from().line + 1, null, true); 4660 cm.indentLine(range.from().line + 1, null, true);
4636 ensureCursorVisible(cm); 4661 ensureCursorVisible(cm);
(...skipping 939 matching lines...) Expand 10 before | Expand all | Expand 10 after
5576 } 5601 }
5577 5602
5578 function callBlankLine(mode, state) { 5603 function callBlankLine(mode, state) {
5579 if (mode.blankLine) return mode.blankLine(state); 5604 if (mode.blankLine) return mode.blankLine(state);
5580 if (!mode.innerMode) return; 5605 if (!mode.innerMode) return;
5581 var inner = CodeMirror.innerMode(mode, state); 5606 var inner = CodeMirror.innerMode(mode, state);
5582 if (inner.mode.blankLine) return inner.mode.blankLine(inner.state); 5607 if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
5583 } 5608 }
5584 5609
5585 function readToken(mode, stream, state) { 5610 function readToken(mode, stream, state) {
5586 var style = mode.token(stream, state); 5611 for (var i = 0; i < 10; i++) {
5587 if (stream.pos <= stream.start) 5612 var style = mode.token(stream, state);
5588 throw new Error("Mode " + mode.name + " failed to advance stream."); 5613 if (stream.pos > stream.start) return style;
5589 return style; 5614 }
5615 throw new Error("Mode " + mode.name + " failed to advance stream.");
5590 } 5616 }
5591 5617
5592 // Run the given mode's parser over a line, calling f for each token. 5618 // Run the given mode's parser over a line, calling f for each token.
5593 function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) { 5619 function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
5594 var flattenSpans = mode.flattenSpans; 5620 var flattenSpans = mode.flattenSpans;
5595 if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; 5621 if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
5596 var curStart = 0, curStyle = null; 5622 var curStart = 0, curStyle = null;
5597 var stream = new StringStream(text, cm.options.tabSize), style; 5623 var stream = new StringStream(text, cm.options.tabSize), style;
5598 if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses); 5624 if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
5599 while (!stream.eol()) { 5625 while (!stream.eol()) {
(...skipping 1445 matching lines...) Expand 10 before | Expand all | Expand 10 after
7045 target[prop] = obj[prop]; 7071 target[prop] = obj[prop];
7046 return target; 7072 return target;
7047 } 7073 }
7048 7074
7049 function bind(f) { 7075 function bind(f) {
7050 var args = Array.prototype.slice.call(arguments, 1); 7076 var args = Array.prototype.slice.call(arguments, 1);
7051 return function(){return f.apply(null, args);}; 7077 return function(){return f.apply(null, args);};
7052 } 7078 }
7053 7079
7054 var nonASCIISingleCaseWordChar = /[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4d b5\u4e00-\u9fcc\uac00-\ud7af]/; 7080 var nonASCIISingleCaseWordChar = /[\u00df\u3040-\u309f\u30a0-\u30ff\u3400-\u4d b5\u4e00-\u9fcc\uac00-\ud7af]/;
7055 var isWordChar = CodeMirror.isWordChar = function(ch) { 7081 var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
7056 return /\w/.test(ch) || ch > "\x80" && 7082 return /\w/.test(ch) || ch > "\x80" &&
7057 (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(c h)); 7083 (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(c h));
7058 }; 7084 };
7085 function isWordChar(ch, helper) {
7086 if (!helper) return isWordCharBasic(ch);
7087 if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true;
7088 return helper.test(ch);
7089 }
7059 7090
7060 function isEmpty(obj) { 7091 function isEmpty(obj) {
7061 for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false; 7092 for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
7062 return true; 7093 return true;
7063 } 7094 }
7064 7095
7065 // Extending unicode characters. A series of a non-extending char + 7096 // Extending unicode characters. A series of a non-extending char +
7066 // any number of extending chars is treated as a single unit as far 7097 // any number of extending chars is treated as a single unit as far
7067 // as editing and measuring is concerned. This is not fully correct, 7098 // as editing and measuring is concerned. This is not fully correct,
7068 // since some scripts/fonts/browsers also treat other configurations 7099 // since some scripts/fonts/browsers also treat other configurations
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
7130 function addClass(node, cls) { 7161 function addClass(node, cls) {
7131 if (!classTest(cls).test(node.className)) node.className += " " + cls; 7162 if (!classTest(cls).test(node.className)) node.className += " " + cls;
7132 } 7163 }
7133 function joinClasses(a, b) { 7164 function joinClasses(a, b) {
7134 var as = a.split(" "); 7165 var as = a.split(" ");
7135 for (var i = 0; i < as.length; i++) 7166 for (var i = 0; i < as.length; i++)
7136 if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i]; 7167 if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i];
7137 return b; 7168 return b;
7138 } 7169 }
7139 7170
7171 // WINDOW-WIDE EVENTS
7172
7173 // These must be handled carefully, because naively registering a
7174 // handler for each editor will cause the editors to never be
7175 // garbage collected.
7176
7177 function forEachCodeMirror(f) {
7178 if (!document.body.getElementsByClassName) return;
7179 var byClass = document.body.getElementsByClassName("CodeMirror");
7180 for (var i = 0; i < byClass.length; i++) {
7181 var cm = byClass[i].CodeMirror;
7182 if (cm) f(cm);
7183 }
7184 }
7185
7186 var globalsRegistered = false;
7187 function ensureGlobalHandlers() {
7188 if (globalsRegistered) return;
7189 registerGlobalHandlers();
7190 globalsRegistered = true;
7191 }
7192 function registerGlobalHandlers() {
7193 // When the window resizes, we need to refresh active editors.
7194 var resizeTimer;
7195 on(window, "resize", function() {
7196 if (resizeTimer == null) resizeTimer = setTimeout(function() {
7197 resizeTimer = null;
7198 knownScrollbarWidth = null;
7199 forEachCodeMirror(onResize);
7200 }, 100);
7201 });
7202 // When the window loses focus, we want to show the editor as blurred
7203 on(window, "blur", function() {
7204 forEachCodeMirror(onBlur);
7205 });
7206 }
7207
7140 // FEATURE DETECTION 7208 // FEATURE DETECTION
7141 7209
7142 // Detect drag-and-drop 7210 // Detect drag-and-drop
7143 var dragAndDrop = function() { 7211 var dragAndDrop = function() {
7144 // There is *some* kind of drag-and-drop support in IE6-8, but I 7212 // There is *some* kind of drag-and-drop support in IE6-8, but I
7145 // couldn't get it to work yet. 7213 // couldn't get it to work yet.
7146 if (ie_upto8) return false; 7214 if (ie_upto8) return false;
7147 var div = elt('div'); 7215 var div = elt('div');
7148 return "draggable" in div || "dragDrop" in div; 7216 return "draggable" in div || "dragDrop" in div;
7149 }(); 7217 }();
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
7516 return order; 7584 return order;
7517 }; 7585 };
7518 })(); 7586 })();
7519 7587
7520 // THE END 7588 // THE END
7521 7589
7522 CodeMirror.version = "4.1.1"; 7590 CodeMirror.version = "4.1.1";
7523 7591
7524 return CodeMirror; 7592 return CodeMirror;
7525 }); 7593 });
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698