最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Send DOM node object via chrome.tabs.sendMessage - Stack Overflow

programmeradmin1浏览0评论

I am writing a Chrome extension. I need to pass an element object from the content script to the background script.

The goal:
The extension is about record and replay user actions.
The data is saved on extension`s localstorage on different object for each tab (by tab ID).
The data structure is a list of {x: x, y:y, element: element}
When the user wants to replay, I am using a loop for each object on the list and using .click() on the element

Code in content script:

The function that sends a message to the background script:

function addToEventHistory(cords) {
    console.log(cords)
    chrome.runtime.sendMessage({action: "addToEventHistory", cords: cords}, function(response) {
        return response;
    });
}

The function that get the element and sens it:

mouseClick: function(e) {
                var target = e.target || e.srcElement
                var clickEvent = {x: e.pageX, y: e.pageY, element: target}
                addToEventHistory(clickEvent)
            }

The code in the background script:

var tabId = sender.tab.id;
var existingRecords = JSON.parse(localStorage.getItem('record_'+tabId)) || [];
existingRecords.push(request.cords)
console.log(request.cords)
localStorage.setItem('record_'+tabId, JSON.stringify(existingRecords));
sendResponse();

The problem is that the element that I am sending is recieved as an empty object. notice to the console.log on send and recieve. the outputs are:

sending:

Object {x: 1205, y: 1067, element: div#content.snippet-hidden}

receiving:

Object {x: 1205, y: 1067, element: Object}

* the element Object is empty and has only _proto_

What is the reason?
How can I solve this issue?

Looks like the issue is not serialize the DOM object, because the object looks ok right before the sending and not ok at receiving..

I am writing a Chrome extension. I need to pass an element object from the content script to the background script.

The goal:
The extension is about record and replay user actions.
The data is saved on extension`s localstorage on different object for each tab (by tab ID).
The data structure is a list of {x: x, y:y, element: element}
When the user wants to replay, I am using a loop for each object on the list and using .click() on the element

Code in content script:

The function that sends a message to the background script:

function addToEventHistory(cords) {
    console.log(cords)
    chrome.runtime.sendMessage({action: "addToEventHistory", cords: cords}, function(response) {
        return response;
    });
}

The function that get the element and sens it:

mouseClick: function(e) {
                var target = e.target || e.srcElement
                var clickEvent = {x: e.pageX, y: e.pageY, element: target}
                addToEventHistory(clickEvent)
            }

The code in the background script:

var tabId = sender.tab.id;
var existingRecords = JSON.parse(localStorage.getItem('record_'+tabId)) || [];
existingRecords.push(request.cords)
console.log(request.cords)
localStorage.setItem('record_'+tabId, JSON.stringify(existingRecords));
sendResponse();

The problem is that the element that I am sending is recieved as an empty object. notice to the console.log on send and recieve. the outputs are:

sending:

Object {x: 1205, y: 1067, element: div#content.snippet-hidden}

receiving:

Object {x: 1205, y: 1067, element: Object}

* the element Object is empty and has only _proto_

What is the reason?
How can I solve this issue?

Looks like the issue is not serialize the DOM object, because the object looks ok right before the sending and not ok at receiving..

Share Improve this question edited Oct 15, 2016 at 19:33 Makyen 33.4k12 gold badges92 silver badges125 bronze badges asked Oct 15, 2016 at 17:50 Oz Bar-ShalomOz Bar-Shalom 1,8951 gold badge20 silver badges35 bronze badges 7
  • Possible duplicate of JSON serialize a DOM element – Makyen Commented Oct 15, 2016 at 18:15
  • Looks like the issue is not serialize the DOM object, because the object looks ok right before the sending and not ok at recieving.. – Oz Bar-Shalom Commented Oct 15, 2016 at 18:23
  • The message in tabs.sendMessage must be "a JSON-ifiable object". DOM elements are not JSON-ifiable. Thus, you can not send them. If you want to identify the element, you will need to determine (or define; e.g. assign an ID) a unique selector. What you will need to do instead of trying to serialize the DOM element is, ultimately, determined by why you need this information in your background script. – Makyen Commented Oct 15, 2016 at 18:28
  • I need to save on the extention`s localstorage the DOM object. The DOM object may not have ID sometimes so saveing the whole element is needed. – Oz Bar-Shalom Commented Oct 15, 2016 at 18:31
  • You can not do what you want to do. Thus, you will need to find some other way of acplishing your actual goal. You have not stated your actual goal, so it is not possible for us to make suggestions as to how you might acplish that. We have hit a point where this is an XY problem. – Makyen Commented Oct 15, 2016 at 18:36
 |  Show 2 more ments

2 Answers 2

Reset to default 9

You can't send a DOM element as a runtime.sendMessage() message

The message in runtime.sendMessage() must be "a JSON-ifiable object". DOM elements/nodes are not JSON-ifiable. Thus, you can not send them. In your case, you are trying to send the target of the click event.

What you will need to do instead of trying to serialize the DOM element is, ultimately, determined by why you need this information in your background script.

If you want to identify the element, you will need to determine a unique selector. One way to do this would be to assign a unique ID to the element and pass that ID in your message. However, that will only be effective if you are wanting to refer to the DOM node during the time that page is loaded within that tab. Obviously, any ID you assign will not be available once the browser has left the page, or loaded it in a different tab. Thus, that alternative is only viable for identifying an element for the life of the current page. However, for an application where you were wanting to just store the actual DOM element, assigning a unique ID would be a valid solution. In other words, storing the DOM element would only be valid for the life of the page, so assigning a unique ID would be valid for the same time period (life of the current page).

If you want methods which will uniquely identify the element when the page is re-loaded, you will need to use a different method than assigning an ID. What to use will depend largely on how you are going about selecting the element when you are wanting to use it and how resilient you want the selection to be with respect to changes in the page structure (e.g. on pages where the structure is dynamic, you may need to use other methods than would work on a static page).

For your application, where you want to record and playback user actions, you will need to determine if you want to record these actions based on where the mouse is within the page, or based on the elements upon which the user initiates events. This is a mon problem for applications/languages which are used to record/playback/simulate user actions. Commonly, the user is given the option as to how they want such user interaction to be recorded (e.g. by location or element). If you choose to store the user actions only by the location of the mouse at the time an event occurred, then you can use Document.elementFromPoint() to determine which element is now at that point and send the event to that element. However, when doing so, you will also need to track the scrolling state of the document and determine if you are going to store the location of the mouse based on the location of the mouse within the current display, or relative to the document.

I used a workaround to click the element,

besides save the element and then using element.click() I used the cords to click the element without saving the element itself:

document.elementFromPoint(cords.x - window.pageXOffset, cords.y - window.pageYOffset).click();
发布评论

评论列表(0)

  1. 暂无评论