I'm trying to make an extension for twitter and I'm stuck at inserting the div block (Kinda like btn) in this section
Manifest.json
{
"manifest_version": 3,
"name": "Twitter Saver",
"version": "0.0.1",
"description": "Twitter Saver| Save tweets.",
"permissions": ["tabs", "https://*.twitter.com/*"],
"icons": {
"128": "img/icon-app-128.png",
"256": "img/icon-app-128@2x.png"
},
"content_scripts": [
{
"html": ["save-dropdown.html"],
"js": ["js/jquery-3.6.0.min.js", "js/content.js"],
"matches": ["https://*.twitter.com/*"]
}
]
}
Content.js
$(
"<div>",{
class: "css-1dbjc4n r-18u37iz r-1h0z5md",
text: "HELLO WORLD"
}
).appendTo(".css-1dbjc4n.r-1ta3fxp.r-18u37iz.r-1wtj0ep.r-1s2bzr4.r-1mdbhws");
I've looked into few things like MutationObserver but here I got error as parameter is not a node
let react_root = $("#react-root");
let callback = function(changeList, observer) => {
console.log(changeList);
}
const observer = new MutationObserver();
observer.observe(callback, {childList: true});
Twitter removes the previous posts as scrolling down adding new ones and adds the previous ones removing new ones when scrolling back to top
For Twitter, MutationObserver is the way to go, and for how to use it, I prefer this Mozilla guide .
To get is working correctly, note the syntax: here in registering the MutationObserver, it says watch the entire body and descendants, and call function appendCustomNode
when change occurs.
// Step 1. Create an observer instance linked to the callback function
// const observer = new MutationObserver(callback);
// Step 2. Start observing the target node for configured mutations
// observer.observe(targetNode, config);
const observer = new MutationObserver(appendCustomNode);
observer.observe(document.body, {subtree: true, childList: true});
Next step is to define this function appendCustomNode
.
In planning how to append nodes to the cards, it is necessary to take into consideration that you will see the same node possibly multiple times, which requires having a strategy to append the custom element only once. Picking some sufficiently random value, then tagging all previously seen nodes with that value, will help accomplish this. Here is an example:
const customTag = `tag-${Date.now()}` // your choice of a valid & unique value
function appendCustomNode(){
// find all timeline cards, their tag name is article
const cards = document.getElementsByTagName('article');
// check each card
for (let n = 0; n < cards.length; n++) {
const card = cards[n];
// check that cards is new / has not been seen before
if (!card.hasAttribute(customTag)) {
addButton(card);
// mark the card as "processed" by adding the custom tag
card.setAttribute(customTag, true);
}
}
}
Lastly implement the logic to append the button you want to add to the card. Here card attribute represents the DOM node of one timeline item.
function addButton(card){
const myButton = document.createElement('div');
myButton.innerText = 'hello world';
// select the div of action buttons
// or wherever you want to insert your custom node
// SEE NOTE BELOW
const target = card.querySelector('....?....')
// append/prepend/insertAdjacentHTML the button here
target.append(myButton);
}
I will leave this last part open for a few reasons: when deciding how to find the buttons row in the card, if using classes as a selector, the implementation breaks if the classes change, which is out of your control. This is always a challenge when extending 3rd party web apps. I suggest trying to find a more reliable selector (which is why earlier I used tag name article to select cards). Secondly the buttons/card structure changes periodically, so that is another point to consider: where do you want to insert this custom node. Lastly this approach does not require jQuery.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.