Making a Chrome Extension with React to Look at DOM Changes - javascript

I was thinking of using React to develop a chrome extension. This app would need to check for any DOM changes on the current web page the user is on.
I have always used react to check DOM updates within the react app itself, is it possible to check the DOM of web pages with a react chrome extension?
EDIT: I tried to use Mutation Observer but its not producing any results here.
var twitter = document.querySelector('#tweet-box-home-timeline > div'); //twitter time-line specific HTML
var observer = new MutationObserver(function(mutations){
mutations.forEach(function(mutation){
console.log(mutation.type); //should log mutation type
console.log('hello'); // should also log
});
});
var config = {characterData: true, subtree: true};
observer.observe(twitter, config);
//observer.disconnect();
}
EDIT2: I got it, thanks!
New/working code:
$(document).keypress(function() {
var twitter = document.querySelector('#tweet-box-home-timeline > div');
new MutationObserver(function() {
console.log(twitter.innerHTML);
}).observe(twitter, {characterData: true,childList: true, subtree: true});
});
}

Related

Javascript innerHTML live console.log the changes

I am trying to console log every changes i make in google developer tools
<div class="test">2</div>
var result = document.getElementsByClassName("test")[0].innerHTML;
console.log(result);
So i have a number 2 inside a div, and it prints out 2 in console, but when i edit this div using google developer tools for example to 3, the console log never prints out new changes i make.
Jquery or javascript?
Nothing is going to re-run your console.log line for you unless you tell it to.
In this case, the thing you'd use to tell it to is a MutationObserver. You'd say you want to see all mutations (modifications) to that element's character data, child list, and subtree (most likely).
For example, if you use devtools to change the foo in this example, you'll get a notification of that change:
const target = document.querySelector(".test");
const observer = new MutationObserver(function() {
console.log(target.innerHTML);
});
observer.observe(target, {
characterData: true,
childList: true,
subtree: true
});
<div class="test">foo</div>

How to attach a javascript SDK in a react app by avoiding window object

I have got a web app written in React js in which I need to integrate a javascript SDK as documented in this link
The sample code is:
<script type="text/javascript">
var _user_id = 'al_capone'; // Set to the user's ID, username, or email address, or '' if not yet known.
var _session_id = 'unique_session_id'; // Set to a unique session ID for the visitor's current browsing session.
var _sift = window._sift = window._sift || [];
_sift.push(['_setAccount', 'INSERT_BEACON_KEY_HERE']);
_sift.push(['_setUserId', _user_id]);
_sift.push(['_setSessionId', _session_id]);
_sift.push(['_trackPageview']);
(function() {
function ls() {
var e = document.createElement('script');
e.src = 'https://cdn.sift.com/s.js';
document.body.appendChild(e);
}
if (window.attachEvent) {
window.attachEvent('onload', ls);
} else {
window.addEventListener('load', ls, false);
}
})();
</script>
Now, I'm aware that I should not use window object in React app however this sample code requires me to attach an object to the window object.
I have created a function to add the script:
function createSiftScript(sift_script_ele) {
//attach the object array to the window
var _sift = window._sift = window._sift || [];
_sift.push(['_setAccount', SIFT_SCIENCE_BEACON_KEY]);
_sift.push(['_setUserId', email]);
_sift.push(['_setSessionId', setUniqueSessionId()]);
//attach the external script
sift_script_ele = document.createElement("script");
sift_script_ele.setAttribute('id', SIFT_SCRIPT_ID);
sift_script_ele.setAttribute('type', "text/javascript");
sift_script_ele.setAttribute('src', "https://cdn.sift.com/s.js");
document.head.appendChild(sift_script_ele);
}
And a function to set the object on the window as suggested for SPAs like mine build in React/Angular:
export function pushEventsToSift() {
_sift.push(['_trackPageview']);
}
I'll call these functions in all the pages wherever needed however, accessing the window object looks dirty to me.
My question is:
If you would be doing this SDK integration in a React SPA then how would you have approached it by following the cleanest approach?
If this doesn't touch the DOM elements in React's care then you're safe in terms of it integrating with React. Regarding setting it on the page, you could throw it directly in index.html, there's nothing stopping you.
If you want it on specific pages - though wasn't this an SPA? - then you can throw the config in a React element as per their docs which should return an empty div or something that React never touches afterwards; But you'll still need to clean up the window object manually .

MutationObserver in "new" Google Calendar

I have an browser extension for Google Calendar, where I observe the DOM to gather events that are being viewed with:
// content.js
const calendarContainer = document.getElementById('gridcontainer');
const observer = new MutationObserver(mutations => {
// just for test
console.log('content', mutations);
}
observer.observe(calendarContainer, {
childList: true,
characterData: true,
subtree: true
});
It works correctly in "classic" Calendar, but since the last update to Material design, DOM structure is different. So, I tried to change observed element accordingly:
// content.js
const calendarContainer = document.querySelector('div[role="main"]');
Even though I switch between week/day view, schedule or between dates, I cannot receive any new mutations besides first load of the page (after refresh). If you look on the source code trough Developer Tools you can see that DOM is changing, but Observer is somehow not able to see it.
Any thoughts?
According to wOxxOm comment, I have changed it to observe the parentElement, which is not replaced between different calls, and it's working.

Unable to click anything inside of webpack-dev-server screen

We have a React js site that uses the webpack-dev-server component. When I load the regular version of the site, everything seems to work fine. The problem is that when I load the webpack-dev-server version, I am unable to click on any elements on the screen.
After a little debugging, it looks like it is caused by the -index of the overlaying iframe being set to -1.
This thread seems to be the same issue, but their solution of changing the "inline" property to true doesn't fix anything for me.
Has anyone else had issues like this?
I'm experiencing the same issue for the exact same reason.
I followed your link and it seems like their webpack-dev-server configuration is handled differently than vanilla webpack.
In order to get the webpack-dev-server running in inline mode, the webpack configuration should have something similarly to:
webpackConfig.devServer = {
inline: true
}
As far as I can tell, the webpack dev server will change it's entry from localhost:8080/webpack-dev-server to localhost:8080/ and provide the live reloading script in the bundled JavaScript files.
In my case, I wanted my example page (~/index.html) to be interactive. Regardless of the inline mode setting, I can just go to localhost:8080/index.html. However, with inline mode enabled, the page auto-reloads on source code changes (all notifications are provided via the dev console).
This strange bug is affecting a project using nextjs version 7.0.2.
Setting the webpack config did not work.
We've fixed it with this hack:
if (process.env.NODE_ENV !== 'production' && typeof window !== undefined) {
// Select the node that will be observed for mutations
var targetNode = window.document.getElementsByTagName('body')[0];
// Options for the observer (which mutations to observe)
var config = { childList: true, subtree: true };
// Callback function to execute when mutations are observed
var callback = function(mutationsList) {
for (var mutation of mutationsList) {
if (mutation.type == 'childList') {
var iframe = document.getElementsByTagName('iframe')[0];
if (iframe && iframe.style.zIndex > -1) {
iframe.style.zIndex = Math.min(-iframe.style.zIndex, -2);
}
}
}
};
// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
// Later, you can stop observing
// observer.disconnect();
}

Using MutationObservers in addons

I am trying to use a MutationObserver inside my addon. Therefore I inject a content-script which then sets the observer. This somehow seems to work, also the detected mutations seem not be be serializable to JSON.
But actually I want to use this library for monitoring mutations. Explicitly this one is officially mentioned by Mozilla regarding mutation monitoring in addons. But this doesn't work at all.
So anybody got a working example for a working mutation-observer (better mutation-summary - see link) inside a content-script?
My code looks like this:
var observer = new MutationObserver(function (mutations) {
self.port.emit("domModified", mutations); //I gets received as 'Array [{}]'
mutations.forEach(function (mutation) {
console.log(mutation.type); //printing mutation results in {}, printing mutation.type results in an actual string
console.log(mutation.target);
console.log(mutation.addedNodes.length);
});
});
observer.observe(unsafeWindow.document.body, {
attributes: true,
subtree: true,
characterData: true,
childList: true
});
This somehow seems to work, also the detected mutations seem not be be serializable to JSON.
Mutations are not serializable, especially because they contains nodes. If you need to pass something from the content script, to the main add-on code, you need to be sure they're JSONable values.
So anybody got a working example for a working mutation-observer (better mutation-summary - see link) inside a content-script?
I never used the library you mentioned, but I used mutation observers quite a lot; and they're working quite fine. You can see an example here: https://github.com/ZER0/tweet-to-read It basically adds a button to every tweet in the stream that contains an external URL; and I needed the mutation observer to add the buttons also in future tweets. You can have a look to the implementation here: https://github.com/ZER0/tweet-to-read/blob/master/data/observable.js
Hope it helps.

Categories

Resources