Chrome Extension change div content of a local page - javascript

I have a local html page called "PageRedirect.html" for chrome extension that has a p tag with id called "toChange"
I have a function in background.js
function doRedirect(tab,val){
var tabUrl = encodeURIComponent(tab.url);
var tabTitle = encodeURIComponent(tab.title);
// determine the type of redirection
if(val == 1 ){
var redirectURL = chrome.extension.getURL('PageRedirect.html');
}
chrome.tabs.update(tab.id, {url: "redirectURL"});
}
This will successfully redirect the page I want.
However, if I want to dynamically p tag with id="toChange" content from blank to new string that I want.
What can I do in this case?
Is there any demo?
I tried message sending method but it has some problems locating the id.
Something like this
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse)
{
if (request.warning == "true"){
url = request.url;
var elem = document.getElementById("toChange"); // elem will be undefined
}
}
);
I am guessing the reason why it will be undefined is caused by the fact that PageRedirect.js is not the "document".

Related

Window.location.href not working inside an onmessage event?

I have an iframe, inside the iframe there is a form, the form is loaded either empty or with errors message or success message, very basic form, no AJAX or Axios, the page refreshes with the form & success or error messages
I am using this iframe inside another website, when my form is being submitted, I have to scroll to it from the window parent, if there an error message I scroll to it for example
Did not implement that completly, because this is not my problem
This a script I added inside the form ( and iframe of course )
<script>
let errors = document.getElementsByClassName("msg-error");
let data = [];
if(errors.length !== 0) {
for(let i = 0; i<errors.length; i++){
data.push(errors[i].classList[1]);
let anchor = errors[i].getElementsByClassName("error-anchor")[0];
anchor.id = (errors[i].classList[1] + "").trim();
}
}
window.onmessage = function(event) {
event.source.postMessage({message: "TESTForm", data}, event.origin);
};
</script>
I am sending a message to the hosting page! for now, if there is error message, their id are going to be sent the the hosting page
On the hosting page I have this :
<script>
// Main page:
window.onmessage = function (event) {
if (event.data.message === "TESTForm") {
let receivedData = event.data.data;
console.log("JOCELYN", receivedData.length === 0);
window.location.href = receivedData.length === 0 ? "#frmTestFrame-1" : "#" + receivedData[0];
}
};
</script>
I receive the message, how I know I am receiving them ?
console.log shows me when the page loads for the first time "JOCELYN true" as a result, & if there is an error it shows me "JOCELYN false"
But in either cases, I have to see an anchor in my url ? right ? in both cases, either true or false! But I don't see it at all, that my original url
Why ? I don't know, and that's why I am here!
Any help would be much appreciated really!

background.js is no longer accessible after iframe is loaded in background.html

In background.js, I injected an iframe:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.action == "doubanSearch")
test(request.title, request.year);
}
);
function test(title, year){
var frame = document.createElement('iframe');
frame.src = 'https://movie.douban.com/subject_search?cat=1002&search_text=' + title + ' '+ year;
document.body.appendChild(frame);
}
However, once the iframe is loaded, the background.js no longer responds to doubanSearch request. Is there a solution to allow background.js remain responsive to future requests even iframe is loaded?
I have checked the content.js separately and can confirm it does what I want it to be doing.
update 1
The netflixContent.js that makes requests:
var prevDOM = null;
var prevMovieTitle = 'prevMovie';
// Mouse listener for any move event on the current document.
document.addEventListener('mousemove', function (e) {
var srcElement = e.srcElement;
if (srcElement == null)
return;
if (prevDOM != srcElement){
prevDOM = srcElement;
return;
}
// find the bob-overlay class
if (srcElement.parentElement != null && srcElement.parentElement.className.startsWith('bob')) {
while (srcElement.className!="bob-overlay"){
srcElement = srcElement.parentElement;
// if srcElement is no longer a bob- class, we are out of luck here.
if (srcElement == null || !srcElement.className.startsWith('bob'))
return;
}
}
// the srcElement at this stage has to be bob-overlay class!
if (srcElement == null || srcElement.className!="bob-overlay")
return;
// now we are in the right place, get movie title and publication year
var movieTitle = srcElement.getElementsByClassName('bob-title');
var movieYear = srcElement.getElementsByClassName('year');
if (movieTitle.length != 1){
console.log('Movie title not found.', srcElement);
return;
}
if (movieYear.length != 1){
console.log('Movie year not found.', srcElement);
return;
}
// now get the title and year
movieTitle = movieTitle[0].textContent;
movieYear = movieYear[0].textContent.trim();
// if the current movie is the same as the previous movie, we return.
if (movieTitle == prevMovieTitle)
return;
// return if title is empty
if (movieTitle == '')
return;
// if movie year isn't empty, add parenthesis.
if (movieYear != '')
movieYear = '(' + movieYear + ')';
prevMovieTitle = movieTitle;
console.log('Movie found:', movieTitle, movieYear);
// replace special characters with space.
movieTitle = movieTitle.replace(/[^\w\s]/g, ' ').trim();
console.log('Movie found (special characters removed) :', movieTitle, movieYear);
// now let's send the message and start searching!
chrome.runtime.sendMessage({action: 'doubanSearch', title: movieTitle, year: movieYear});
}, false);
It is opensource hosted on github in case you need to check out the entire code. I'm really new to js and chrome extension development, so please execuse me for crappy coding :).
update 2
The background page before a request is sent:
The background page after a request is sent and iframe is loaded
Also, the background page link is no longer available from the chrome://extensions:
The site performs frame-busting (assigning top.location to an URL of the page itself) which navigates the background page to the site URL so the extension no longer has a background page. It looks like an oversight in Chrome which has been intermittently prevented in some recent versions and is about to be fixed for good in v67.
The solution is to sandbox the iframe by adding the following attribute:
frame.sandbox = 'allow-scripts';
Some sites may require more features to be allowed e.g. allow-forms, see MDN for the full list.

Chrome extension logic is not wοrking

I've managed to get most of my Chrome extension working, but there is a problem I can't work out.
You can grab it here if you want and load it as an unpacked extension.
After loading it works like this.
You are prompted that they need to enter a URL on the options page.
You enter a URL (e.g. http://example.com) on the options page as asked and click save, and then when you click the icon in the toolbar you can see the web page appear in the popup.
If you then go and removes the URL from the options page and clicks save, then the popup does not show the original prompt page they saw at the beginning.
I think this code (from popup.js) is at fault, but I can't see why it won't work.
var url = localStorage.url;
var alturl = chrome.extension.getURL("need-to-enter-url.html");
var element = document.getElementById("testerURL");
if (url != undefined || url != null) {
element.src = url;
} else {
element.src = alturl;
};
When you "remove" the url you are actually saving an empty string. localStorage.url = "" so your value checking is failing. I would also recommend tweaking the if logic to be clearer.
Use something like this:
if (url === undefined || url === null || url === "") {
element.src = alturl;
} else {
element.src = url;
}
Optionally you can rely on JavaScript's truthiness.
if (url) {
element.src = url;
} else {
element.src = alturl;
}

How to check a "sync" value in an async function?

I try to make some changes on a Chrome extension. I need the extension checks the value and if it is true, then execute a script. If false, then do nothing. I wrote something like this:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if(localStorage["statusOfSomething"]){
chrome.tabs.executeScript(tabId, {file: "file.js" ,runAt:'document_end'});
}
});
But this takes the initial value of localStorage["statusOfSomething"] always. So there is an async function to register a listener for "onUpdated". But I need to check the localStorage["statusOfSomething"] value of "now", not the value of the time by registering the listener.
How can I do this?
Edit:
Actually I was trying to check two things:
if the website is in the site list of extension
if this website is enabled for the extension
Now here the full story;
There are some websites, I defined them on background.js file. Let's say;
a.com, b.com ... etc.
var sites = [{
name : "a",
wildcard : ["*://a.com/*"],
js : "a.js"
},{
name : "b",
wildcard : ["*://b.com/*"],
js : "b.js"
}]
and there are statuses of the sites (enable/ disable; true/false)
I think it was good to store statuses by localStorage, so I write as initial value true:
for(var i = 0; i<sites.length; i++){
localStorage[sites[i].name] =true;
}
As option; it was needed to addListener for changes:
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
if(request.method == "setSite"){
var name = request.site;
var status = request.active;
localStorage[name] = status;
}
return true;
});
If user checks the checkbox for status option of the website, then options.js sends message:
$('#' + name).change(function(){
var status = $(this).is(':checked');
chrome.extension.sendMessage({method: "setSite", site: this.id, active: status}, function(response) {
console.log(response.data);
});
});
Now, back to background.js , for every update of the tab, I need to check these two things together:
1. am I interested in this website?
2. is it enable for me now?
So I wrote:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.status === 'complete') {
var url = tab.url;
for(var i = 0; i<sites.length; i++){
var site = sites[i];
var name = site.name;
var wildcard = site.wildcard;
if(localStorage[name] && testUrl(url,wildcard)){
chrome.tabs.executeScript(tabId, {file: site['js'] ,runAt:'document_end'});
break;
}
}
}
});
Here, I get the value of localStorage[sitename] true
If you are more interested, you can see the code on github (the version)

Javascript redirect causing IE 'null' is null or not an object error

I'm trying to A/B test our product drop view. below is the javascript code I'm using:
var url = window.location.href,
defaultType = 'Gallery',
otherType = 'List';
if(Cookie.read('SEARCHVIEW') == otherType && Cookie.read('viewTypeChanged') != otherType){
if(url.contains('v='+otherType)){
url = url.replace('v='+otherType, 'v='+defaultType);
}else if(url.contains('?')){
url = url + '&v='+defaultType;
}else{
url = url + '?v='+defaultType;
}
window.location = url;
}
After the page redirects in IE I get the dreaded 'null' is null or not an object and Object does not support this property or method errors.
This is happening in both IE 7 & 8
How can I fix this?
I was able to resolve the problem. and for future reference I'll post some code and explain.
The offending code looks like this:
<script type="text/javascript">
window.addEvent('domready', function(){
$('v_toggle').addEvents({
'mouseenter': function(e){
$('vertical_slide_container').show();
},
'mouseleave': function(e){
$('vertical_slide_container').hide();
}
});
});
</script>
</head>
<body>
<div class="mboxDefault">/div>
<script type="text/javascript">mboxCreate('header',etc...);</script>
My company uses Omniture for our A/B testing and my code was being run in the mboxCreate() function. You'll notice above that there is code adding a domready event which adds hover events to our navigtaion(which is incidentally below my mboxCreate() code). What was happening was my code was redirecting, which stopped the page from loading, which also signaled that the DOM was ready. So when I called the redirect, the DOM ready code was run and was trying to add hover events on DOM elements that did not exists.
Thus the 'null' is null or not an object' and the object does not support this method or property errors.
The solution to the problem was to remove all domready events before I redirected so my error free code looks like this:
var url = window.location.href,
defaultType = 'Gallery',
otherType = 'List';
if(Cookie.read('SEARCHVIEW') == otherType && Cookie.read('viewTypeChanged') != otherType){
if(url.contains('v='+otherType)){
url = url.replace('v='+otherType, 'v='+defaultType);
}else if(url.contains('?')){
url = url + '&v='+defaultType;
}else{
url = url + '?v='+defaultType;
}
window.removeEvents('domready');
window.location = url;
}
href is not a property of window it can be used with anchor() object, try to use only window.location and this should work.

Categories

Resources