VSCode extension API - text selection - javascript

I am having trouble updating the vs code selection after the extension triggers.
const selection = editor.selection;
const text = editor.document.getText(selection);
const modText = "/* " + text + " */";
let edit = new vscode.WorkspaceEdit();
let startPos = new vscode.Position(selection.start.line, selection.start.character);
let endPos = new vscode.Position(selection.start.line + text.split(/\r\n|\r|\n/).length - 1, selection.start.character + text.length);
let range = new vscode.Range(startPos, endPos);
edit.replace(editor.document.uri, range, modText);
return vscode.workspace.applyEdit(edit);
I am selecting everything below.
body {
background: blue;
}
The result after trigger is:
/* body {
background: blue;
} */
but the selection is missing the initial /*
How do I change the selection to include the initial
/* ???

Try adding this to the end of your code:
await vscode.workspace.applyEdit(edit); // add the next line
editor.selections = [new vscode.Selection(startPos, new vscode.Position(endPos.line, endPos.character+6))];
See that it adds 6 characters to account for the /* and */ to a Selection that should include your entire comment characters and included text.
This code does the same thing and is a little more compact:
editor.selections = [new vscode.Selection(startPos, endPos.translate(0, 6))];

Related

Indesign : in a table cell, how to get and move any paragraph content

I need help for complete my code.
I created a table and inserted 4 paragraphs texts and a image into the same cell.
I want to modify the content of the cell like this :
1: move 'text3' before 'text4'
2: move the image at the first place
I understood the principe of the insertionpoints, however after many tests i didn't succeed the moves...
Please help me to fix, Thank you !
var myDocument = app.documents.add();
var myPage = myDocument.pages;
var tf = myPage[0].textFrames.add({ geometricBounds: [20, 20, 100, 150] });
insertionpoint = tf.insertionPoints[0];
app.select(insertionpoint);
mySelection=app.selection[0];
mySelection.tables.add({
label : "theTable",
bodyRowCount : 7,
columnCount : 8,
});
tableList = myDocument.stories.everyItem().tables.everyItem().getElements();
myTable = tableList[0];
myTable.columns[4].cells[5].contents = "test2\n";
myTable.columns[4].cells[5].insertionPoints[-1].contents = "test4\n";
myTable.columns[4].cells[5].insertionPoints[0].contents = "test1\n";
myTable.columns[4].cells[5].insertionPoints[-1].contents = "test3\n";
var myFrame = myTable.columns[4].cells[5].insertionPoints[-1].rectangles.add({
name : "theFrame"
});
myFrame.horizontalScale *= 2;
myFrame.verticalScale *= 3;
try
{
myFrame.place(File("Put here a valid local image path"));
}
catch(err)
{
myFrame.fillColor = "Black";
};
myFrame.fit(FitOptions.proportionally);
myFrame.fit(FitOptions.frameToContent);
/* 1: Code for moving "test3\n" paragraph before "test4\n" in the cell (4,5) */
/* 2: Code for moving the rectangle in first place in the cell (4,5) */
Here is the rather clumsy solution but it works:
/* 1: Code for moving "test3\n" paragraph before "test4\n" in the cell (4,5) */
app.findGrepPreferences = NothingEnum.nothing;
app.findGrepPreferences.findWhat = '^(.+?)\\n(.+?)\\n(.+?)\\n(.+?)\\n';
app.changeGrepPreferences.changeTo = '\\n$1\\n$2\\n$4\\n$3';
myTable.columns[4].cells[5].changeGrep();
/* 2: Code for moving the rectangle in first place in the cell (4,5) */
myFrame.select();
app.cut();
myTable.columns[4].cells[5].insertionPoints[0].select();
app.paste();

ContentEditable div - set cursor position after updating inner html

I have a spell check solution that uses a content editable div and inserts span tags around words that are misspelled. Every time the inner html of the div is updated, the cursor moves to the beginning of the div.
I know I can move the cursor to the end of the div if the user adds new words to the end of the sentence (code below).
Old Text: This is a spell checker|
New Text: This is a spell checker soluuution|
var range = document.createRange();
range.selectNodeContents(element[0]);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
However, I am unable to retain the cursor position if the user adds words in the middle of a sentence.
Old Text: This is a spell checker
New Text: This is a new spell checker|
In the above case, the cursor goes to the end of the div when it should be after "new".
How do I retain the cursor position? Since I am updating the html and adding nodes, saving the range before the update and adding it to the selection object isn't working.
Thanks in advance.
As far as I know, changing the content of the div will always have problem.
So here is the solution that I came with. Please type error word such as helloo, dudeee
This should ideally work for textarea as well.
Solution details:
Use a ghost div with same text content
Use transparent color for the ghost div
Use border-bottom for the ghost div span text
Change zIndex so that it does't appear infront
// some mock logic to identify spelling error
const errorWords = ["helloo", "dudeee"];
// Find words from string like ' Helloo world .. '
// Perhaps you could find a better library you that does this logic.
const getWords = (data) =>{
console.log("Input: ", data);
const allWords = data.split(/\b/);
console.log("Output: ", allWords)
return allWords;
}
// Simple mock logic to identify errors. Now works only for
// two words [ 'helloo', 'dudeee']
const containsSpellingError = word => {
const found = errorWords.indexOf(word) !== -1;
console.log("spell check:", word, found);
return found;
}
const processSpellCheck = text => {
const allWords = getWords(text);
console.log("Words in the string: ", allWords);
const newContent = allWords.map((word, index) => {
var text = word;
if(containsSpellingError(word.toLowerCase())) {
console.log("Error word found", word);
text = $("<span />")
.addClass("spell-error")
.text(word);
}
return text;
});
return newContent;
}
function initalizeSpellcheck(editorRef) {
var editorSize = editorRef.getBoundingClientRect();
var spellcheckContainer = $("<div />", {})
.addClass("spell-check")
.prop("spellcheck", "false");
var spellcheckSpan = $("<span />")
.addClass("spell-check-text-content")
.css({
width: editorSize.width,
height: editorSize.height,
position: "absolute",
zIndex: -1
});
var text = $(editorRef).text();
var newContent = processSpellCheck(text);
spellcheckSpan.append(newContent);
spellcheckContainer.append(spellcheckSpan);
spellcheckContainer.insertBefore(editorRef);
$(editorRef).on("input.spellcheck", function(event) {
var newText = $(event.target).text();
var newContent = processSpellCheck(newText);
$(".spell-check .spell-check-text-content").text("");
$(".spell-check .spell-check-text-content").append(newContent);
});
}
$(document).ready(function() {
var editor = document.querySelector("#editor");
initalizeSpellcheck(editor);
});
#editor {
border: 1px solid black;
height: 200px;
}
.spell-check {
color: transparent;
}
.spell-error {
border-bottom: 3px solid orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="editor" contenteditable="true" spellcheck="false">
dudeee
</div>
This answer might work from SitePoint:
Store the selection x, y:
cursorPos=document.selection.createRange().duplicate();
clickx = cursorPos.getBoundingClientRect().left;
clicky = cursorPos.getBoundingClientRect().top;
Restore the selection:
cursorPos = document.body.createTextRange();
cursorPos.moveToPoint(clickx, clicky);
cursorPos.select();
SitePoint Article: Saving/restoring caret position in a contentEditable div
Update 25.10.2019:
The solution mentioned above doesn't work anymore since functions are used that are deprecated. Does chrome supports document.selection?

Textarea selection in IE 11 not working appropriately on last line

I'm building an Angular directive that consists of a textarea for writing Markdown, and buttons that insert formatting into the text area. When clicked, if no text is currently selected, a button (bold, for instance) should append the following:
**replace text**
where replace text is selected.
It is working as expected in every scenario save the following: In IE 11, when the selection occurs on the final row, but is not the first row. It works as expected in every other browser, and works fine in IE 11 minus this condition.
Here is the code from the directive for performing the selection:
var editor = element.find('textarea')[0];
function createWrappingMarkdown(symbol) {
// If text is selected, wrap that text in the provided symbol
// After doing so, set the cursor at the end of the highlight,
// but before the ending symbol(s)
/* This section works fine */
if (editor.selectionStart < editor.selectionEnd) {
var start = editor.selectionStart,
end = editor.selectionEnd;
var value = editor.value.substring(0, start) + symbol +
editor.value.substring(start, end) + symbol +
editor.value.substring(end, editor.value.length);
scope.$evalAsync(function () {
editor.value = value;
editor.focus();
editor.selectionStart = end + symbol.length;
editor.selectionEnd = end + symbol.length;
});
// If no text is highlighted, insert {symbol}replace text{symbol}
// at the current cursor position.
// After inserting, select the text "replace text"
/* This is where the selection is broken in IE 11 */
} else if (editor.selectionStart || editor.selectionStart === 0) {
var start = editor.selectionStart,
message = "replace text";
var value = editor.value.substring(0, start) + symbol +
message + symbol + editor.value.substring(start, editor.value.length);
scope.$evalAsync(function () {
editor.value = value;
setCursorSelect(start + symbol.length, start + symbol.length + message.length);
});
}
}
function setCursorSelect(start, end) {
editor.focus();
if (editor.setSelectionRange) {
editor.setSelectionRange(start, end);
} else {
editor.selectionStart = start;
editor.selectionEnd = end;
}
}
Update
See answer for the fix to this issue. The Plunk has been revised to demonstrate this fix.
After debugging further in IE, I found that editor.selectionStart was being set to a value higher than editor.value.length whenever the cursor was at the last available position in the textarea. This was only happening in IE, and not the other browsers. With this in mind, I was able to come up with the following solution whenever a selection is needed following a button press:
scope.$evalAsync(function () {
if (editor.value.length < editor.selectionStart) {
start = editor.value.length;
}
editor.value = value;
setCursorSelect(start + symbol.length, start + symbol.length + message.length);
});
The plunk above has been updated to reflect this fix.

Automatically Highlight Specific Word in Browser

In the content scripts of my chrome extension I am trying to inject code that highlights a specific word in the page.
In this instance, I am viewing espn.com and would like to have all instances of 'bryant' highlighted in the text immediately as the page is loaded.
This is the current code I have customized after viewing several questions similar to mine:
var all = document.getElementsByTagName("*");
highlight_words('Bryant', all);
function highlight_words(keywords, element) {
if(keywords) {
var textNodes;
keywords = keywords.replace(/\W/g, '');
var str = keywords.split(" ");
$(str).each(function() {
var term = this;
var textNodes = $(element).contents().filter(function() { return this.nodeType === 3 });
textNodes.each(function() {
var content = $(this).text();
var regex = new RegExp(term, "gi");
content = content.replace(regex, '<span class="highlight">' + term + '</span>');
$(this).replaceWith(content);
});
});
}
}
In my jquery-ui.css I have the following code. I understand it does not highlight at this moment but I am just trying to get a proof of concept:
.highlight {
font-weight: bold;
}
At this time everything loads properly but no iteration of 'bryant' is read in bold.
Thanks!
The fastest way to do this is to define the what are you want to search for highlight, for example:
You have 3 parts on site, the navbar on left, the title on the top and the content.
Lets attach .foo class to article.
var list = document.getElementsByClassName("foo")
var search_word = ""
var contents = []
for(var i = 0; i < list.length; i++){
var contents = list[i].textContext.split(search_word)
list[i].textContext = contents.join('<span class="heighlight\">'+search_word+'</span>')
}
Hope it will help.
(The highlight is bound to elements that have .foo class)
some example: https://jsfiddle.net/Danielduel/0842qntu/2/

MarkItUp: Tab/Indent, Set Selection

I see that theres is no build in way for doing tabs/indents in MarkItUp? So I did something like
onTab: {
keepDefault: false,
replaceWith: function(markItUp) {
return miu.openEachLineWith(markItUp, ' ');
}
},
openEachLineWith: function(markItUp, openingStr) {
var textarea = markItUp.textarea,
selStart = textarea.selectionStart,
selEnd = textarea.selectionEnd,
selText = textarea.value.substring(selStart, selEnd),
lines = [],
charsAdded = 0;
lines = selText.split(/\r?\n/);
for (var i = 0, len = lines.length; i < len; i++) {
lines[i] = openingStr + lines[i];
charsAdded += openingStr.length;
}
textarea.selectionEnd = selEnd + charsAdded;
return lines.join('\n');
}
which works but, how can I set the selection after replacing the the text, I want it to select the tabbed text, also I prefer the way the editor here on SO works where when I bold some text, it selects the bolded text instead of moving the cursor to the end, can I do that with markItUp too?
I've been working on a script to do this. Here's an example: http://jsfiddle.net/timdown/dp2WL/2/
It indents when Tab is pressed and outdents when Shift + Tab is pressed and doesn't require any library. It hasn't had as much testing as I'd like, but seems to work well in all major browsers, including IE 6. The main code comes from an open source project I'm working on. The bit that enables tab indentation is at the bottom:
window.onload = function() {
rangyInputs.init();
rangyInputs.enableTabIndentation(document.getElementById("test"), " ");
};
You must set the selection in the afterInsert callback (not in replaceWith)

Categories