diff options
author | Chia-liang Kao <clkao@clkao.org> | 2013-06-15 01:37:41 +0800 |
---|---|---|
committer | Chia-liang Kao <clkao@clkao.org> | 2013-06-15 01:38:46 +0800 |
commit | f31db205dafd8a8711db583975b8b2aab568303a (patch) | |
tree | a744fffe021162ab0bb0966485cc86931bd83648 | |
parent | 548f31a46a685860c73376261f39e502d680cedd (diff) | |
download | etherpad-lite-f31db205dafd8a8711db583975b8b2aab568303a.zip |
allow cssmanager to manage outer_ace
-rw-r--r-- | src/static/js/ace.js | 26 | ||||
-rw-r--r-- | src/static/js/ace2_inner.js | 141 | ||||
-rw-r--r-- | src/static/js/cssmanager.js | 32 |
3 files changed, 110 insertions, 89 deletions
diff --git a/src/static/js/ace.js b/src/static/js/ace.js index 83ad9447..db0d596b 100644 --- a/src/static/js/ace.js +++ b/src/static/js/ace.js @@ -1,5 +1,5 @@ /** - * This code is mostly from the old Etherpad. Please help us to comment this code. + * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED */ @@ -86,7 +86,7 @@ function Ace2Editor() }); actionsPendingInit = []; } - + ace2.registry[info.id] = info; // The following functions (prefixed by 'ace_') are exposed by editor, but @@ -97,7 +97,7 @@ function Ace2Editor() 'applyChangesToBase', 'applyPreparedChangesetToBase', 'setUserChangeNotificationCallback', 'setAuthorInfo', 'setAuthorSelectionRange', 'callWithAce', 'execCommand', 'replaceRange']; - + _.each(aceFunctionsPendingInit, function(fnName,i){ var prefix = 'ace_'; var name = prefix + fnName; @@ -105,18 +105,18 @@ function Ace2Editor() info[prefix + fnName].apply(this, arguments); }); }); - + editor.exportText = function() { if (!loaded) return "(awaiting init)\n"; return info.ace_exportText(); }; - + editor.getFrame = function() { return info.frame || null; }; - + editor.getDebugProperty = function(prop) { return info.ace_getDebugProperty(prop); @@ -221,16 +221,16 @@ function Ace2Editor() // calls to these functions ($$INCLUDE_...) are replaced when this file is processed // and compressed, putting the compressed code from the named file directly into the // source here. - // these lines must conform to a specific format because they are passed by the build script: + // these lines must conform to a specific format because they are passed by the build script: var includedCSS = []; var $$INCLUDE_CSS = function(filename) {includedCSS.push(filename)}; $$INCLUDE_CSS("../static/css/iframe_editor.css"); $$INCLUDE_CSS("../static/css/pad.css"); $$INCLUDE_CSS("../static/custom/pad.css"); - + var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path }); includedCSS = includedCSS.concat(additionalCSS); - + pushStyleTagsFor(iframeHTML, includedCSS); if (!Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[KERNEL_SOURCE]) { @@ -304,16 +304,16 @@ window.onload = function () {\n\ $$INCLUDE_CSS("../static/css/iframe_editor.css"); $$INCLUDE_CSS("../static/css/pad.css"); $$INCLUDE_CSS("../static/custom/pad.css"); - - + + var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path }); includedCSS = includedCSS.concat(additionalCSS); - + pushStyleTagsFor(outerHTML, includedCSS); // bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly // (throbs busy while typing) - outerHTML.push('<link rel="stylesheet" type="text/css" href="data:text/css,"/>', scriptTag(outerScript), '</head><body id="outerdocbody"><div id="sidediv"><!-- --></div><div id="linemetricsdiv">x</div><div id="overlaysdiv"><!-- --></div></body></html>'); + outerHTML.push('<style type="text/css" title="dynamicsyntax"></style>', '<link rel="stylesheet" type="text/css" href="data:text/css,"/>', scriptTag(outerScript), '</head><body id="outerdocbody"><div id="sidediv"><!-- --></div><div id="linemetricsdiv">x</div><div id="overlaysdiv"><!-- --></div></body></html>'); var outerFrame = document.createElement("IFRAME"); outerFrame.name = "ace_outer"; diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index f8b266b4..97540191 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -1,5 +1,5 @@ /** - * This code is mostly from the old Etherpad. Please help us to comment this code. + * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED */ @@ -36,10 +36,10 @@ var isNodeText = Ace2Common.isNodeText, htmlPrettyEscape = Ace2Common.htmlPrettyEscape, noop = Ace2Common.noop; var hooks = require('./pluginfw/hooks'); - + function Ace2Inner(){ - + var makeChangesetTracker = require('./changesettracker').makeChangesetTracker; var colorutils = require('./colorutils').colorutils; var makeContentCollector = require('./contentcollector').makeContentCollector; @@ -53,9 +53,9 @@ function Ace2Inner(){ var undoModule = require('./undomodule').undoModule; var makeVirtualLineView = require('./virtual_lines').makeVirtualLineView; var AttributeManager = require('./AttributeManager'); - + var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;" - // changed to false + // changed to false var isSetUp = false; var THE_TAB = ' '; //4 @@ -83,9 +83,9 @@ function Ace2Inner(){ initLineNumbers(); var outsideKeyDown = noop; - + var outsideKeyPress = function(){return true;}; - + var outsideNotifyDirty = noop; // selFocusAtStart -- determines whether the selection extends "backwards", so that the focus @@ -101,7 +101,7 @@ function Ace2Inner(){ alines: [], apool: new AttribPool() }; - + // lines, alltext, alines, and DOM are set up in setup() if (undoModule.enabled) { @@ -113,7 +113,7 @@ function Ace2Inner(){ var doesWrap = true; var hasLineNumbers = true; var isStyled = true; - + // space around the innermost iframe element var iframePadLeft = MIN_LINEDIV_WIDTH + LINE_NUMBER_PADDING_RIGHT + EDIT_BODY_PADDING_LEFT; var iframePadTop = EDIT_BODY_PADDING_TOP; @@ -122,7 +122,7 @@ function Ace2Inner(){ var console = (DEBUG && window.console); var documentAttributeManager; - + if (!window.console) { var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; @@ -159,7 +159,7 @@ function Ace2Inner(){ var textFace = 'monospace'; var textSize = 12; - + function textLineHeight() { @@ -167,12 +167,14 @@ function Ace2Inner(){ } var dynamicCSS = null; + var outerDynamicCSS = null; var parentDynamicCSS = null; function initDynamicCSS() { dynamicCSS = makeCSSManager("dynamicsyntax"); - parentDynamicCSS = makeCSSManager("dynamicsyntax", true); + outerDynamicCSS = makeCSSManager("dynamicsyntax", "outer"); + parentDynamicCSS = makeCSSManager("dynamicsyntax", "parent"); } var changesetTracker = makeChangesetTracker(scheduler, rep.apool, { @@ -218,6 +220,7 @@ function Ace2Inner(){ var authorStyleSet = hooks.callAll('aceSetAuthorStyle', { dynamicCSS: dynamicCSS, parentDynamicCSS: parentDynamicCSS, + outerDynamicCSS: outerDynamicCSS, info: info, author: author, authorSelector: authorSelector, @@ -562,8 +565,8 @@ function Ace2Inner(){ { return rep.lines.atOffset(charOffset).key; } - - + + function dispose() { disposed = true; @@ -918,14 +921,14 @@ function Ace2Inner(){ editorInfo.ace_doReturnKey = doReturnKey; editorInfo.ace_isBlockElement = isBlockElement; editorInfo.ace_getLineListType = getLineListType; - + editorInfo.ace_callWithAce = function(fn, callStack, normalize) { var wrapper = function() { return fn(editorInfo); }; - + if (normalize !== undefined) { var wrapper1 = wrapper; @@ -951,14 +954,14 @@ function Ace2Inner(){ // @param value the value to set to editorInfo.ace_setProperty = function(key, value) { - - // Convinience function returning a setter for a class on an element + + // Convinience function returning a setter for a class on an element var setClassPresenceNamed = function(element, cls){ return function(value){ setClassPresence(element, cls, !! value) } }; - + // These properties are exposed var setters = { wraps: setWraps, @@ -973,7 +976,7 @@ function Ace2Inner(){ }, grayedout: setClassPresenceNamed(outerWin.document.body, "grayedout"), dmesg: function(){ dmesg = window.dmesg = value; }, - userauthor: function(value){ + userauthor: function(value){ thisAuthor = String(value); documentAttributeManager.author = thisAuthor; }, @@ -986,10 +989,10 @@ function Ace2Inner(){ document.documentElement.dir = value? 'rtl' : 'ltr' } }; - + var setter = setters[key.toLowerCase()]; - - // check if setter is present + + // check if setter is present if(setter !== undefined){ setter(value) } @@ -1098,7 +1101,7 @@ function Ace2Inner(){ return false; } }; - + isTimeUp.elapsed = function() { return now() - startTime; @@ -1479,7 +1482,7 @@ function Ace2Inner(){ var p = PROFILER("getSelection", false); var selection = getSelection(); p.end(); - + function topLevel(n) { if ((!n) || n == root) return null; @@ -1489,7 +1492,7 @@ function Ace2Inner(){ } return n; } - + if (selection) { var node1 = topLevel(selection.startPoint.node); @@ -1747,7 +1750,7 @@ function Ace2Inner(){ root:root, point:selection.startPoint, documentAttributeManager: documentAttributeManager - }); + }); selStart = (selStartFromHook==null||selStartFromHook.length==0)?getLineAndCharForPoint(selection.startPoint):selStartFromHook; } if (selection && !selEnd) @@ -1760,7 +1763,7 @@ function Ace2Inner(){ point:selection.endPoint, documentAttributeManager: documentAttributeManager }); - selEnd = (selEndFromHook==null||selEndFromHook.length==0)?getLineAndCharForPoint(selection.endPoint):selEndFromHook; + selEnd = (selEndFromHook==null||selEndFromHook.length==0)?getLineAndCharForPoint(selection.endPoint):selEndFromHook; } // selection from content collection can, in various ways, extend past final @@ -1781,7 +1784,7 @@ function Ace2Inner(){ // update rep if we have a new selection // NOTE: IE loses the selection when you click stuff in e.g. the // editbar, so removing the selection when it's lost is not a good - // idea. + // idea. if (selection) repSelectionChange(selStart, selEnd, selection && selection.focusAtStart); // update browser selection p.mark("browsel"); @@ -1916,19 +1919,19 @@ function Ace2Inner(){ return rep.selStart[0]; } editorInfo.ace_caretLine = caretLine; - + function caretColumn() { return rep.selStart[1]; } editorInfo.ace_caretColumn = caretColumn; - + function caretDocChar() { return rep.lines.offsetOfIndex(caretLine()) + caretColumn(); } editorInfo.ace_caretDocChar = caretDocChar; - + function handleReturnIndentation() { // on return, indent to level of previous line @@ -2357,8 +2360,8 @@ function Ace2Inner(){ documentAttributeManager.setAttributesOnRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs); } editorInfo.ace_performDocumentApplyAttributesToCharRange = performDocumentApplyAttributesToCharRange; - - + + function setAttributeOnSelection(attributeName, attributeValue) { if (!(rep.selStart && rep.selEnd)) return; @@ -2921,7 +2924,7 @@ function Ace2Inner(){ { if (lineClass !== null) lineElem.className = lineClass; }; - + result.prepareForAdd = writeClass; result.finishUpdate = writeClass; result.getInnerHTML = function() @@ -3283,7 +3286,7 @@ function Ace2Inner(){ { return (n.tagName || '').toLowerCase() == "a" && n.href; } - + // only want to catch left-click if ((!evt.ctrlKey) && (evt.button != 2) && (evt.button != 3)) { @@ -3319,7 +3322,7 @@ function Ace2Inner(){ { return; } - + var lineNum = rep.selStart[0]; var listType = getLineListType(lineNum); @@ -3444,9 +3447,9 @@ function Ace2Inner(){ var thisLineListType = getLineListType(theLine); var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1)); var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker); - + var thisLineHasMarker = documentAttributeManager.lineHasMarker(theLine); - + if (thisLineListType) { // this line is a list @@ -3521,7 +3524,7 @@ function Ace2Inner(){ return !!REGEX_WORDCHAR.exec(c); } editorInfo.ace_isWordChar = isWordChar; - + function isSpaceChar(c) { return !!REGEX_SPACE.exec(c); @@ -4151,7 +4154,7 @@ function Ace2Inner(){ maxIndex: tn.nodeValue.length }; }; - + var selection = {}; if (origSelectionRange.compareEndPoints("StartToEnd", origSelectionRange) === 0) { @@ -4255,7 +4258,7 @@ function Ace2Inner(){ selection.startPoint = pointFromRangeBound(range.startContainer, range.startOffset); selection.endPoint = pointFromRangeBound(range.endContainer, range.endOffset); selection.focusAtStart = (((range.startContainer != range.endContainer) || (range.startOffset != range.endOffset)) && browserSelection.anchorNode && (browserSelection.anchorNode == range.endContainer) && (browserSelection.anchorOffset == range.endOffset)); - + if(selection.startPoint.node.ownerDocument !== window.document){ return null; } @@ -5020,9 +5023,9 @@ function Ace2Inner(){ } } } - + var listAttributeName = 'list'; - + function getLineListType(lineNum) { return documentAttributeManager.getAttributeOnLine(lineNum, listAttributeName) @@ -5035,7 +5038,7 @@ function Ace2Inner(){ }else{ documentAttributeManager.setAttributeOnLine(lineNum, listAttributeName, listType); } - + //if the list has been removed, it is necessary to renumber //starting from the *next* line because the list may have been //separated. If it returns null, it means that the list was not cut, try @@ -5045,7 +5048,7 @@ function Ace2Inner(){ renumberList(lineNum); } } - + function renumberList(lineNum){ //1-check we are in a list var type = getLineListType(lineNum); @@ -5058,7 +5061,7 @@ function Ace2Inner(){ { return null; } - + //2-find the first line of the list while(lineNum-1 >= 0 && (type=getLineListType(lineNum-1))) { @@ -5067,7 +5070,7 @@ function Ace2Inner(){ break; lineNum--; } - + //3-renumber every list item of the same level from the beginning, level 1 //IMPORTANT: never skip a level because there imbrication may be arbitrary var builder = Changeset.builder(rep.lines.totalWidth()); @@ -5094,7 +5097,7 @@ function Ace2Inner(){ ChangesetUtils.buildKeepRange(rep, builder, loc, (loc = [line, 1]), [ ['start', position] ], rep.apool); - + position++; line++; } @@ -5109,19 +5112,19 @@ function Ace2Inner(){ } return line; } - + applyNumberList(lineNum, 1); var cs = builder.toString(); if (!Changeset.isIdentity(cs)) { performDocumentApplyChangeset(cs); } - + //4-apply the modifications - - + + } - + function doInsertList(type) { @@ -5159,7 +5162,7 @@ function Ace2Inner(){ var t = getLineListType(n); mods.push([n, allLinesAreList ? 'indent' + level : (t ? type + level : type + '1')]); } - + _.each(mods, function(mod){ setLineListType(mod[0], mod[1]); }); @@ -5173,7 +5176,7 @@ function Ace2Inner(){ } editorInfo.ace_doInsertUnorderedList = doInsertUnorderedList; editorInfo.ace_doInsertOrderedList = doInsertOrderedList; - + var lineNumbersShown; var sideDivInner; @@ -5189,11 +5192,11 @@ function Ace2Inner(){ var newNumLines = rep.lines.length(); if (newNumLines < 1) newNumLines = 1; //update height of all current line numbers - + var a = sideDivInner.firstChild; var b = doc.body.firstChild; var n = 0; - + if (currentCallStack && currentCallStack.domClean) { @@ -5222,8 +5225,8 @@ function Ace2Inner(){ b = b.nextSibling; n++; } - } - + } + if (newNumLines != lineNumbersShown) { var container = sideDivInner; @@ -5233,27 +5236,27 @@ function Ace2Inner(){ { lineNumbersShown++; var n = lineNumbersShown; - var div = odoc.createElement("DIV"); + var div = odoc.createElement("DIV"); //calculate height for new line number if(b){ var h = (b.clientHeight || b.offsetHeight); - + if (b.nextSibling){ h = b.nextSibling.offsetTop - b.offsetTop; } } - + if(h){ // apply style to div div.style.height = h +"px"; } - + div.appendChild(odoc.createTextNode(String(n))); fragment.appendChild(div); if(b){ b = b.nextSibling; } } - + container.appendChild(fragment); while (lineNumbersShown > newNumLines) { @@ -5262,8 +5265,8 @@ function Ace2Inner(){ } } } - - + + // Init documentAttributeManager documentAttributeManager = new AttributeManager(rep, performDocumentApplyChangeset); editorInfo.ace_performDocumentApplyAttributesToRange = function () { @@ -5309,13 +5312,13 @@ function Ace2Inner(){ bindTheEventHandlers(); }); - + hooks.callAll('aceInitialized', { editorInfo: editorInfo, rep: rep, documentAttributeManager: documentAttributeManager }); - + scheduler.setTimeout(function() { parent.readyFunc(); // defined in code that sets up the inner iframe diff --git a/src/static/js/cssmanager.js b/src/static/js/cssmanager.js index 62f17496..710cdbe5 100644 --- a/src/static/js/cssmanager.js +++ b/src/static/js/cssmanager.js @@ -1,5 +1,5 @@ /** - * This code is mostly from the old Etherpad. Please help us to comment this code. + * This code is mostly from the old Etherpad. Please help us to comment this code. * This helps other people to understand this code better and helps them to improve it. * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED */ @@ -20,14 +20,32 @@ * limitations under the License. */ -function makeCSSManager(emptyStylesheetTitle, parentCss) +function makeCSSManager(emptyStylesheetTitle, doc) { + if (doc === true) + { + doc = 'parent'; + } else if (!doc) { + doc = 'inner'; + } function getSheetByTitle(title) { - if (parentCss) var allSheets = window.parent.parent.document.styleSheets; - else var allSheets = document.styleSheets; - + if (doc === 'parent') + { + win = window.parent.parent; + } + else if (doc === 'inner') { + win = window; + } + else if (doc === 'outer') { + win = window.parent; + } + else { + throw "Unknown dynamic style container"; + } + var allSheets = win.document.styleSheets; + for (var i = 0; i < allSheets.length; i++) { var s = allSheets[i]; @@ -38,8 +56,8 @@ function makeCSSManager(emptyStylesheetTitle, parentCss) } return null; } - - var browserSheet = getSheetByTitle(emptyStylesheetTitle, parentCss); + + var browserSheet = getSheetByTitle(emptyStylesheetTitle); function browserRules() { |