Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Chrome extension to replace characters spanning more than one line in a Facebook status update

I have created a Google Chrome extension to allow users to select text in a component. This works great for most sites. However, Facebook handles its status updates differently. It seems that even though you are filling in what seems to be a single text box, it is actually using a div > div > span > span construct for every single line in this text box. I have no idea why they chose to do this but it makes replacing multiple lines of text much more complex.

Is there a way to select multiple lines (or even contiguous portions of multiple lines) of text in a Facebook status update and replace the data?

The relevant portion of my code looks like this:

function replace_text(language){
    let selection = window.getSelection();
    string = selection.toString();

    /* This section contains code that uses string.replace to replace characters in the string. */

    document.execCommand("insertText", false, string);

}

Based on the way my code works now, if I replace text on a single line I have no problems. But, if I replace text that spans multiple lines I end up with a blank unusable input box. Undoubtedly it is because it is removing portions of the html code. How can I fix my code so that the replacement process works properly not only for other sites but also for Facebook?

like image 342
kojow7 Avatar asked Nov 15 '17 17:11

kojow7


1 Answers

As of this moment, the one common theme among all status updates (and comments) are that their texts reside within a single or set of span elements with the attribute data-text set to true. So let's target those:

document.querySelectorAll("span[data-text='true']");

For me, I've typed into the status field 3 lines and comment field 1 line of dummy text. So when I execute the above code into the console it returns an array of those four cumulative lines:

>>> (4) [span, span, span, span]

With that array, I can use the Array.prototype.forEach() method to iterate through the spans and replace the innerText:

document.querySelectorAll("span[data-text='true']").forEach(function(element) {
    element.innerText = element.innerText.replace('Lorem ipsum','Hello world');
});

However, it is important to note that these changes are being made in the HTML itself and Facebook doesn't store all of its data directly in the HTML. Therefore it can cause undesirable events to occur when you type text into a field, unfocus, change the text in the field, and refocus that field. When you refocus I believe it grabs data of what the text was, before you unfocused that field, from an ulterior source like React's Virtual DOM. To deter it from doing that, the changes either need to be made after clicking the field (real or simulate) or as the user is typing using some sort of MutationObserver (src).

like image 161
Cole Avatar answered Nov 15 '22 20:11

Cole