diff --git a/doc/api/editorInfo.md b/doc/api/editorInfo.md index 05656bce7..31361a750 100644 --- a/doc/api/editorInfo.md +++ b/doc/api/editorInfo.md @@ -39,6 +39,13 @@ Returns the `rep` object. ## editorInfo.ace_performDocumentApplyAttributesToCharRange(?) ## editorInfo.ace_setAttributeOnSelection(?) ## editorInfo.ace_toggleAttributeOnSelection(?) +## editorInfo.ace_getAttributeOnSelection(attribute) +Returns a boolean if an attribute exists on a selected range. +The attribute should be the string name of the attribute applied to the selection IE subscript +Example usage: Apply the activeButton Class to a button if an attribute is on a highlighted/selected caret position or range. +Example: `call.editorInfo.ace_getAttributeOnSelection("subscript");` // call here is the callstack from aceEditEvent. +See the ep_subscript plugin for an example of this function in action. +Notes: Does not work on first or last character of a line. Suffers from a race condition if called with aceEditEvent. ## editorInfo.ace_performSelectionChange(?) ## editorInfo.ace_doIndentOutdent(?) ## editorInfo.ace_doUndoRedo(?) diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 467d50632..0c1153fde 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -1067,3 +1067,14 @@ input[type=checkbox] { } /* End of gritter stuff */ +.activeButton{ + background: #eee; + background: -webkit-linear-gradient(#ddd, #fff); + background: -moz-linear-gradient(#ddd, #fff); + background: -o-linear-gradient(#ddd, #fff); + background: -ms-linear-gradient(#ddd, #fff); + background: linear-gradient(#ddd, #fff); + -webkit-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; + -moz-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; + box-shadow: 0 0 8px rgba(0,0,0,.1) inset; +} diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index 63e6e1f4f..012d72f38 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -2372,6 +2372,73 @@ function Ace2Inner(){ } editorInfo.ace_setAttributeOnSelection = setAttributeOnSelection; + function getAttributeOnSelection(attributeName){ + if (!(rep.selStart && rep.selEnd)) return; + var selectionAllHasIt = true; + var withIt = Changeset.makeAttribsString('+', [ + [attributeName, 'true'] + ], rep.apool); + var withItRegex = new RegExp(withIt.replace(/\*/g, '\\*') + "(\\*|$)"); + + function hasIt(attribs) + { + return withItRegex.test(attribs); + } + + var selStartLine = rep.selStart[0]; + var selEndLine = rep.selEnd[0]; + for (var n = selStartLine; n <= selEndLine; n++) + { + var opIter = Changeset.opIterator(rep.alines[n]); + var indexIntoLine = 0; + var selectionStartInLine = 0; + var selectionEndInLine = rep.lines.atIndex(n).text.length; // exclude newline + if(rep.lines.atIndex(n).text.length == 0){ + return false; // If the line length is 0 we basically treat it as having no formatting + } + if(rep.selStart[1] == rep.selEnd[1] && rep.selStart[1] == rep.lines.atIndex(n).text.length){ + return false; // If we're at the end of a line we treat it as having no formatting + } + if(rep.selStart[1] == 0 && rep.selEnd[1] == 0){ + return false; // If we're at the start of a line attributes get confused.. + } + if (n == selStartLine) + { + selectionStartInLine = rep.selStart[1]; + } + if (n == selEndLine) + { + selectionEndInLine = rep.selEnd[1]; + } + while (opIter.hasNext()) + { + var op = opIter.next(); + var opStartInLine = indexIntoLine; + var opEndInLine = opStartInLine + op.chars; + if (!hasIt(op.attribs)) + { + // does op overlap selection? + if (!(opEndInLine <= selectionStartInLine || opStartInLine >= selectionEndInLine)) + { + selectionAllHasIt = false; + break; + } + } + indexIntoLine = opEndInLine; + } + if (!selectionAllHasIt) + { + break; + } + } + if(selectionAllHasIt){ + return true; + }else{ + return false; + } + } + editorInfo.ace_getAttributeOnSelection = getAttributeOnSelection; + function toggleAttributeOnSelection(attributeName) { if (!(rep.selStart && rep.selEnd)) return;