I have created a simple addon which bookmarks the active tab in a specific folder when clicked.
The addon is consisted of two .js files, the background.js and the popup.js. The background.js does the heavy work and sends some date values to the popup.js after the bookmarking is done, which then displays them in a popup window. it also displays an 'OK' text on the addon button. After 2 seconds both the popup window and the button text clear out automatically.
Everything works fine, the bookmarking and when showing and closing the popup and the badge.
Here is the problem though. If I happen to close the popup window during those 2 seconds by clicking anywhere in the page or the browser, the badge text doesnt clear out. Until I click the button again next time and repeat the process by letting the popup close by itself this time, then the text clears out.
So what causes this and how can I fix it? I need to clear out the badge text, even if I manually close the popup window during those 2 seconds.
here is the code for the popup.js
// Listener calls background
document.addEventListener("DOMContentLoaded", function () {
backGround = chrome.extension.getBackgroundPage();
backGround.browserOnClickAxn(insertText);
});
// Set text
function insertText (msg) {
var message = "To find your saved tabs, look in the folder ";
message = message + "<br>";
message = message + "<strong>";
message = message + "\""+msg+"\"";
message = message + "</strong>";
message = message + "<br><br>";
message = message + " under ";
message = message + "<br>";
message = message + "<strong>";
message = message + "\"Other Bookmarks/BOOKMARKS/VARIOUS\"";
message = message + "</strong>";
message = message + "<br><br>";
document.getElementById('msg').innerHTML = message;
setBadgeText('OK!');
setTimeout(function () {
setBadgeText('');
window.close();
}, 2000);
}
function setBadgeText(text) {
chrome.browserAction.setBadgeBackgroundColor({
color: '#32cd32'
});
chrome.browserAction.setBadgeText({
text: text
});
}
Related
I observe that the onUpdated listener for the tabs API in Chrome does trigger multiple times.
When I refresh the existing tab, the alert pops up 3 times
When I load a different URL, the alert pops up 4 times
In the alert popup, I also see that there seem to be "intermediate" title tags.
How can I avoid this and reduce action to the final update?
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
/*
Multiple Tasks:
1. Check whether title tag matches the CPD Teamcenter title and custom success tab does not exist
2. If yes, trigger three actions:
a. move tab to new Chrome window
b. call external application to hide the window with the isolated tab
c. add custom success tag to identify that this was already processed
*/
const COMPARESTRING = "My Tab Title"
var title = tab.title;
alert(title) // this alert pops up 3 or 5 times!
/* if (title == COMPARESTRING) {
return "Match. :-)";
} else {
return "No match. :-(";
} */
});
you can do something like this
chrome.tabs.onUpdated.addListener(function (tabId, tabInfo, tab): void {
if (tab.url !== undefined && tabInfo.status === "complete") {
// do something - your logic
};
});
window.addEventListener('popstate', function(event) {
alert("you are not able to push back button");
});
I have create the web application using polymer 2.0 but I have to click on the back button to the browser is logout I have to show the alert if the user is click on the back button of the browser I have tried window.addEventListener but still got error.
I've not been able to stop the browser's back button, but I've managed to get around it. In my app, I want to warn the user that they will log out by backing up to the first page, and give them a chance to leave or stay put. Using the polymer-2-starter-kit as my starting point, and tracking a connected property, I got this working:
_routePageChanged(page) {
// If no page was found in the route data, page will be an empty string.
// Default to 'home' in that case.
this.page = (page && this.connected) ? page : 'home';
// Close the drawer.
this.drawerOpened = false;
}
_pageChanged(page, oldPage) {
// Warn user if backing up logs out.
if ((page == '' || page == 'home') && this.connected) {
if (window.confirm("Do you really mean to logout?")) {
this.$.xhrLogout.generateRequest();
} else {
window.history.forward();
}
}
const resolvedPageUrl = this.resolveUrl('my-' + page + '.html');
Polymer.importHref(
resolvedPageUrl,
null,
this._showPage404.bind(this),
true);
}
So if the user is connected, and navigates to the initial page, I can force them to stay on the page where they were with window.history.forward().
I have an extension that inserts text into textarea and similar.
The user can choose text from the popup or the contextmenu.
I have "all_frames" : true so that my content script can see all the iframes - in case a textarea is in an iframe.
After a save to the database (more on this in a bit), if the user uses the contextmenu to add text (handled via messaging from background.js to content.js) to a text area the text is added twice.
If the user uses the popup.html mechanism, which passes text to the same content.js, the text is only entered once (the desired outcomes!).
The message is only passed once by background.js.
For instance, if there are five iframes on a page, and therefore 5 instances of content.js, the contextmenu listener script runs 10 times (not 5, as it should).
If I remove "all_frames" : true from the manifest then the text only adds once.
But I need to keep this setting so I can reach textareas in iFrames. And the popup insert works beautifully everywhere.
The save to the database is what triggers the behavior - and that process is a simple json write to a php file. I wipe the contextmenu as part of that process - but again, it isn't a question of the background.js sending 2 messages. One message is sent, and for some reason the code runs through the messaging routine 2x.
I've tried creating flags to mark once a single successful insertion has happened, but everything is asynch and I don't think this would be helpful even if I could get it to work in some cases.
I feel like I need to kill some old content.js processes or something...
The kicker: if I Reload the Extension (in developer mode) the contextmenu works properly and inserts selected text only once. It's only after I save to the db that the problem occurs.
I'm very close to throwing out contextmenus as a feature and just using the elegant popup.html. But this seems like some weird edge case that would be worth understanding.
Many thanks for taking a look. I've included some code and also a screenshot of the console showing the 10x repeats of the content.js code when inserting into a Google Doc.
background.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {method: "insertComment", comment: tempText}, function(response) {
// console.log(response.status);
});
});
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.method == 'insertComment'){
var sValue = request.comment;
var currentEltag = document.activeElement.tagName.toLowerCase(); //Checking for currently selected area
console.log("currentEltag before logic: " + currentEltag + " / id: " + document.activeElement.id);
console.log("activeTag: " + activeTag);
// console.log("activeEl: " + activeEl.id + ' / name: ' + activeEl.name + ' /value: ' + activeEl.value);
if (activeTag === undefined || activeTag === null){
console.log('currentEltag in logic: ' + currentEltag);
if (currentEltag === 'iframe'){
activeTag = 'iframe';
console.log('Making activeTag equal iframe');
}
}
var sField = activeEl;
if (activeTag === 'input' || activeTag === 'textarea'){
console.log('Dealing with plain input/textarea - yes! sField is: ' + sField);
var nStart = sField.selectionStart;
var nEnd = sField.selectionEnd;
if (nStart || nEnd == '0'){
console.log("Inside insert sub with starting point: " + nStart + ' and end ' + nEnd + ' with value ' + sValue);
console.log('Print and increment...');
sField.value = sField.value.substring(0, nStart) + sValue + sField.value.substring(nEnd, sField.value.length);
sField.selectionStart = nStart + sValue.length;
sField.selectionEnd = nStart + sValue.length;
console.log('Printed value1...and flag is now: ');
chrome.storage.sync.get("flag", function(data) {
console.log("Flag", data.flag);
});
}
else {
sField.value = sValue;
console.log('Printed value2...');
}
} //End if input or textarea
Today I accidentally found out that when you have a input with type file, and when you have chosen a file and then click the file button again but this time click cancel, the origin file is replaced and the file input remain no file chosen, which is pretty annoying especially I have something like a image preview with original image, and when the users do something like I mentioned before, they end up with nothing being uploaded.
<input type="file" />
I'm thinking using a hidden input to save the original file, like
<input type="file" id="origin"> <!--this would be hidden and save the file-->
<input type="file" ><!--show it to the user-->
and when I upload the image, I select the origin one and upload it..It's any better way to handle this situation?
I was able to find a work around for Chrome's annoying removing file when cancel pressed that has existed for years...
JSFiddle: https://jsfiddle.net/dqL97q0b/1/
<!doctype html><html><head></head><body>
<h2>Fix for Chrome Removing File when 'cancel' clicked</h2>
Upload Image: <input id="imageUpload" type="file" onclick="fileClicked(event)" onchange="fileChanged(event)">
<br/><br/>
<label for="videoUpload">Upload Video:</label> <input id="videoUpload" type="file" onclick="fileClicked(event)" onchange="fileChanged(event)">
<br/><br/>
<div id="log"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
//This is All Just For Logging:
var debug = true;//true: add debug logs when cloning
var evenMoreListeners = true;//demonstrat re-attaching javascript Event Listeners (Inline Event Listeners don't need to be re-attached)
if (evenMoreListeners) {
var allFleChoosers = $("input[type='file']");
addEventListenersTo(allFleChoosers);
function addEventListenersTo(fileChooser) {
fileChooser.change(function (event) { console.log("file( #" + event.target.id + " ) : " + event.target.value.split("\\").pop()) });
fileChooser.click(function (event) { console.log("open( #" + event.target.id + " )") });
}
}
var clone = {};
// FileClicked()
function fileClicked(event) {
var fileElement = event.target;
if (fileElement.value != "") {
if (debug) { console.log("Clone( #" + fileElement.id + " ) : " + fileElement.value.split("\\").pop()) }
clone[fileElement.id] = $(fileElement).clone(); //'Saving Clone'
}
//What ever else you want to do when File Chooser Clicked
}
// FileChanged()
function fileChanged(event) {
var fileElement = event.target;
if (fileElement.value == "") {
if (debug) { console.log("Restore( #" + fileElement.id + " ) : " + clone[fileElement.id].val().split("\\").pop()) }
clone[fileElement.id].insertBefore(fileElement); //'Restoring Clone'
$(fileElement).remove(); //'Removing Original'
if (evenMoreListeners) { addEventListenersTo(clone[fileElement.id]) }//If Needed Re-attach additional Event Listeners
}
//What ever else you want to do when File Chooser Changed
}
</script>
</body></html>
Most of the JSFiddle is just for logging.
The Way it works is if the file Chooser has a value when onClick happense then a Clone of the file chooser is made and stored in the var clone{}; based on the file chooser's id.
Then when a Change Event happense and the file Chooser value is "" (Which would only happen on Chrome) then we replace the Original file Chooser with the clone.
For security reasons, you can't set the value of an input with type file. The best you might be able to do is intercept the change event and store the value in a separate variable, but this still will give you a "No file chosen" next to your input.
For example:
var selected;
$("input").change(function() {
var now = $(this).val();
if (now){
selected = now;
$("#selected")[0].innerHTML = now;
}
});
http://jsfiddle.net/v0j6e385/
It is pretty annoying that canceling doesn't restore the original value (at least in Chrome).
Update: a little experimentation with IE and Firefox and it appears this problem is restricted to Chrome. Firefox and IE won't clear the selected value if you hit cancel. Not sure what the standards actually say about that.
I am dealing with desktop notifications on HTML5. My problem is on Firefox (on Chrome is fine), there I cann't throw more than 1 notification.
//Requestion permissions blablabla
if (permission === "granted") {
var notification = new Notification(id, opt, null);
var notification2 = new Notification(id, opt, null);
var notification3 = new Notification(id, opt, null);
}
This doesn't work on Firefox, if I comment the last ones, works.
Somebody know if I can do this
Many aspects of displaying notifications are up to browsers, but in particular in this case you need to show more then one notification at the same time you can set a different "tag" attribute to each notification (http://www.w3.org/TR/notifications/#tags-example). If you don't specify a tag, the default one is used and the last notification "wins" over the previous ones.
Check this example:
<button id="authorize">Authorize notification</button>
<button id="show">Show notification</button>
<button id="show_another">Show another notification</button>
<script>
function authorizeNotification() {
Notification.requestPermission(function(perm) {
alert(perm);
});
}
function showNotification(myTag) {
var notification = new Notification("This is a title with tag " + myTag, {
dir: "auto",
lang: "",
body: "This is a notification body with tag " + myTag,
tag: myTag,
});
}
document.querySelector("#authorize").onclick = authorizeNotification;
document.querySelector("#show").onclick = function(){ showNotification("firstTag"); };
document.querySelector("#show_another").onclick = function(){ showNotification("secondTag"); };
</script>
If you click "show notification" many times, the notification is closed and a new one is opened. Using the second button a new notification is shown without closing the old one.
You can find a working sample at JSFiddle (http://jsfiddle.net/TuJHx/350/)