Как получить выбор пользователя в документах Microsoft Word Online

Я создаю расширение Chrome, которое должно взаимодействовать с выбором пользователя в документах Microsoft Word Online - добавить новое выделение вместо выделения естественного выделения и затем удалить его. Проблема в том, что я не могу получить выбор пользователя: ответ на window.getSelection() возвращает результат, как будто выбор пуст

Вот файлы с моим расширением:

manifest.json

{
    "manifest_version": 2,
    "name": "The extension name",
    "version": "1.0",
    "description": "This extension description",

    "browser_action": {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },

    "icons": {
        "128": "icon.png"
    },

    "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["content_script.js"],
        "run_at": "document_end",
        "all_frames": true
    }],

    "permissions": ["activeTab"]
}

popup.html

<!doctype html>
<html>
<head>
    <script src="popup.js"></script>
</head>
<body>
    <div id="wrapper">
        <form id="settings" name="settings">
            <div id="apply" class="form-row">
                <input type="submit" name="apply" value="Apply"/>
            </div>
        </form>
    </div>
</body>
</html>

popup.js

document.addEventListener('DOMContentLoaded', function() {
    document.getElementById("settings").addEventListener("submit", function (e) {
        e.preventDefault();

        chrome.tabs.executeScript(null, {file: 'toolbar.js'}, function() {
            chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
                chrome.tabs.sendMessage(tabs[0].id, {});
            });
        );
    }, false);
});

toolbar.js

function showToolbar() {
    var dom_body = document.getElementsByTagName('body')[0];
    var tb_wrapper = document.createElement('div');
    tb_wrapper.id = "toolbar_wrapper";

    var tb_toolbar_play = document.createElement('button');
    tb_toolbar_play.id = "toolbar_play";
    tb_toolbar_play.title = "Play";
    tb_toolbar_play.value = "Play";

    tb_wrapper.appendChild(tb_toolbar_play);
    dom_body.appendChild(tb_wrapper);
}

showToolbar();

content_script.js

function playButtonOnClickEventListener(request, sender, sendResponse) {
    var toolbar = document.getElementById("toolbar_wrapper");

    if (toolbar !== null) {
        var toolbar_play_button = document.getElementById("toolbar_play");
        toolbar_play_button.addEventListener("click", function (e) {
            var selection = window.getSelection();
            console.log(selection);
        });
    }

    sendResponse({data: "response", success: true});
}

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    playButtonOnClickEventListener(request, sender, sendResponse);
});

Итак, что я хочу увидеть в инструментах Chrome Developer после console.log(selection) выполняет:
ожидаемый результат в инструментах разработчика Chrome

Что я на самом деле получаю:
фактический результат в инструментах разработчика Chrome

PS Расширение отлично работает с Google Docs.

2 ответа

Решение

Вот решение проблемы. Надеюсь, что это может быть полезно для кого-то однажды.

В настоящее время я вижу всю картину по-другому, поэтому я изменил количество файлов и их содержимое.

manifest.json

{
    "manifest_version": 2,

    "version": "1.1.1",

    "name": "Test name",

    "description": "Test description",

    "browser_action": {
        "default_icon": "icon.png"
    },

    "icons": {
        "128": "icon.png"
    },

    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": ["content_script.js"],
            "run_at": "document_end",
            "all_frames": true
        }
    ],

    "permissions": ["activeTab"]
}

content_script.js

//Word Online pages contain several different iframes, so, in order 
//to find the one where the text that we are going to work with 
//is placed, we have to use the Chrome Runtime API and its 
//"sendMessage" method that works in every frame.
//https://developer.chrome.com/apps/runtime#method-sendMessage

chrome.runtime.sendMessage("", function() {
    if (checkFrameLocation()) {
        showToolbar();
    }
});

function checkFrameLocation() {
    //So as I work with documents in OneDrive (onedrive.live.com) 
    //and in Sharepoint (<USER_NAME>-my.shrepoint.com), I found out 
    //that I need iframes with these URLs only.

    var trusted_urls = [
        "https://euc-word-edit.officeapps.live.com",
        "https://word-edit.officeapps.live.com",
        "nl1-word-edit.officeapps.live.com"
    ];

    var result = false;

    for (var i = 0; i < trusted_urls.length; i++) {
        if (window.location.href.indexOf(trusted_urls[i]) > -1) {
            result = true;
        }
    }

    return result;
}

function showToolbar() {
    var dom_body = document.body;

    var tb_wrapper = document.createElement('div');
    tb_wrapper.id = "toolbar_wrapper";
    tb_wrapper.style.position = "absolute";
    tb_wrapper.style.top = "200px";
    tb_wrapper.style.left = "200px";
    tb_wrapper.style.backgroundColor = "#ffffff";
    tb_wrapper.style.height = "30px";
    tb_wrapper.style.width = "50px";

    var tb_play = document.createElement('button');
    tb_play.id = "toolbar_play_button";
    tb_play.title = "Play";
    tb_play.innerHTML = "&#9658;";
    tb_play.style.height = "100%";
    tb_play.style.width = "100%";
    tb_play.style.lineHeight = "12px";

    tb_play.addEventListener("click", function() {
        playButtonOnClickEventListener();
    });

    tb_wrapper.appendChild(tb_play);
    dom_body.appendChild(tb_wrapper);
}

function playButtonOnClickEventListener() {
    //Now we can use the window selection object

    var window_selection = window.getSelection();
    console.log(window_selection);

    //Also, Word Online adds special class name to every selected element
    //in the document. So, this is another way to get the selected text.

    var elements_selection = document.getElementsByClassName("Selected");
    console.log(elements_selection);
}

И вот скриншот доказательства:

Есть результаты доступа к выделенному тексту в документе Word Online

Я не уверен, как построен редактор Word Online или почему вы не можете использовать window.getSelection(), но одна вещь, которую я сразу заметил, заключается в том, что при выделении текста в нем, редактор дает этот текст Selected учебный класс. Так, может быть, вы могли бы как-то воспользоваться этим? Переопределить стиль соответствующих элементов?

Возможно, вы могли бы использовать MutationObserver и ищите это имя класса, добавляемое к элементам. Вам нужно будет поэкспериментировать, чтобы убедиться, что это работает для ваших нужд, и, очевидно, если Microsoft изменит имя класса или поведение, ваше расширение сломается.

Попробуйте выбрать текст и поставить

document.getElementsByClassName("Selected")[0].innerHTML

в консоли.

Другие вопросы по тегам