Mozilla Extension: Multiple States between multiple tabs - javascript

I am creating a mozilla extension that converts the content of a webpage on click of the "convert button"(Label: Convert) in other language
and its label gets converted to English so that on click of that button(Label: English) the content gets converted into original form
I tried to set attribute "changedcontent" with each tab so that on event focus ,focussed tab reads its "changedcontent" attribute and set the label on button ("Convert" or "English")
problem arises where i need to switch between multiple tabs, plugin in the different tab should maintain different state depending on whether it is displaying changed content(should display button label: English)
or it is in its original form(should display button label: "Convert")
so when i click refresh button or click other link in the webpage. The label of the button which is "English" with converted content on the page should gets changed to "Convert"
so for this i have handled page unload event to track page refresh or link click, but since webpage may contain multiple frames/iframes this event is getting called multiple times.
If in the meantime i switch the tab, label of other tab gets converted from "English" to "Convert"
code of the unload event is:
window.addEventListener('unload', unloadingDocument, true);
function unloadingDocument()
{
var currentTab = gBrowser.selectedTab;
currentTab.setAttribute("changedcontent" , "false");//set the transliterated attribute back to false
var convertButton = document.getElementById("convert_button");
convertButton.setAttribute("label","Convert");
}
Please suggest how can i solve this problem and maintain different states of mozilla plugin between multiple tabs.
Thanks

You could use the Session Store API to have independent state between tabs.
-- EDIT:
So if you already have a way to know if a specific tab is "Translated or not", if you want the button to change to have the correct state when another tab is selected, you might want to check for the tabSelect event: Detecting tab selection
In this event you check your tab attribute to check if you have to change or not the label/behaviour of your button.
-- Edit 2 :
If when you click the "Convert" button you do your processing, and you set the attribute changedcontent of that tab to true. Then you have a load/unload listener to check for the refresh, to change the state back to false. Then if you change tabs, you would have the tabSelect event to change the button whenever you change tabs.
If you add this listener when you change changedcontent to true. Then when the event beforeunload is first called, you check if changedcontent is true, you change it to false and remove the listener.

Related

jQuery animations on back button

I have a page where multiple tabs (subpages) are accessed via jQuery show/hide functions. When one clicks on the logo all other tabs are hidden and the first one is shown.
I would like to attach the same show/hide flow as with $("#logo").click() to the back button. When someone would tap browser's back button the default action should be prevented and show/hide combination should be activated to display the first tab.
Does anyone has a solution?
window.onbeforeunload function does not work...
https://jsfiddle.net/hqkyxz3w/3/
This is usually done using URL's hash (that's everything after #) and window.history.pushState() method.
When the user clicks on a tab/logo:
Change location.hash to whatever you want.
Call window.history.pushState() to add state to browsers history. See https://developer.mozilla.org/en-US/docs/Web/API/History_API for more detailed explanation what parameters it requires.
Call your function that hides/shows appropriate tabs.
Then, when you press the browser's back button you want the tabs to change so you need to know when the URL's hash has changed.
See this answer how to listen to hash change events: On - window.location.hash - Change?
Check current hash and call the same function from bullet point 3 in the previous paragraph that hide/shows tabs.
Here is the half working version... I have used location.hash and history.pushState to change it on clicking the tab and then window.onpopstate to hide the page..
https://jsfiddle.net/hqkyxz3w/4/
The problem still exists because the onpopstate also fires when clicking the tab and not only when tapping back button.. Here is the example:
https://jsfiddle.net/hqkyxz3w/5/
$("#tab1").click(function(){
location.hash = 'something';
history.pushState({extraData: "something"}, '', 'new-hash');
$("#page1").show();
});
$("#logo").click(function(){
$("#page1").hide();
});
window.onpopstate = function() {
alert('How to exclude it on clicking page one?');
$("#page1").hide();
};

Firefox firing onchange events after tab restore

Firefox is firing onchange events in my webapp after tab restore.
When reloading the same URL in Firefox there is no problem, no onchange events get fired on page load, all changed values since last visit are displayed correctly.
But when reopening the same page with the same URL, after closing Firefox and reopening the page with "restored tabs" (from the Firefox option "show my windows and tabs from last time") then it is firing onchange events for all values that have been changed since last visit.
Actual workflow ot reproduce the problem:
My update events are in background (JavaScript/AJAX) and are fired
with onchange events;
Firefox setting "show my windows and tabs from last time" enabled;
Change some values in my page (select fields);
Close Firefox;
Open the same URL on another browser or computer, and change some values;
Reopen Firefox, select the tab with the page on it, it reloads and fires onchange events again for all changed values since last visit.
Tried to reproduce this behaviour with completely different pages (not created by me and using other script libraries and stuff) and the result is the same, it is always firing the onchange events.
Chrome is not doing this with the "restore tabs" option.
Why is it firing onchange events? How can I prevent it?
A few suggestions on how to deal with this depending on the wanted result. Note that this is tested on my machine, behaviors may vary.
They way it seems to work is that Firefox tries to restore data that was entered by user. So it modifies the page, triggering the change event. This event is slighlty different than the one triggered by the user. It is a UIEvent while the user triggered one is a straight Event. And this Event is cancelable and triggered before the window load event. So this gives a couple of ways to deal with this. I'll take a select element for example.
If you want the select to keep value entered before window closing, but not trigger the onchange event, you can set the onchange call on the window.onload. Like this:
window.onload = function(){
element.onchange = function(){
Since the setting of the select occurs before onload, this specific change won't trigger your onchange function.
Other way would be to target behaviors you don't to trigger by putting a condition validating if the element is cancelable or not. If it's cancelable, it means it's called from a restore session and won't trigger what's inside. Like this:
element.onchange = function(e){
if(e.cancelable == true){
Other way, to clear out all data would be to set a document.onchange event and reload the page if the event is cancelable. Like this:
document.onchange = function(e){
if(e.cancelable == true){
window.location = window.location
}
}
Of course you need to make sure you don't have any other cancelable change event called in your page.
EDIT:
To clarify order of events fired, see this jsfiddle, not in iframes, iframes seems to behave differently, so if you have iframes, it may be a bit more complicated. But without iframe, you'll see how the different events are triggered depending on your interactions:
document.onchange = function (e) {
//this will be triggered on restore before the window load event
alert('restore onchange called, e.cancelable = ' + e.cancelable)
}
window.onload = function (e) {
//You'll see that on restore, this will be triggered but after page has been updated
alert('window load called')
document.onchange = function () {
//This onchange will be called normally, not on restore
alert('after onload change, e.cancelable = ' + e.cancelable)
}
}
http://fiddle.jshell.net/nozp9uhk/6/show/
Firefox is caching your files when you load the page, so when you restore the tab, the differences between your cached values and the new ones may be firing onchange events.
Try to clear the cache when restoring the tab. I see two ways to do this :
Call window.location.reload(true) to reload the current page
or
Change the name of the JavaScript file that initializes the onchange events for this :
<script language="JavaScript" type="text/javascript" src="yourscript.js?n=1"></script>
This (?n=1) will force Firefox to load a new copy of the file "yourscript.js"

Trigger an event on back button in browser/android with javascript

My angular app's content creation flow is being broken by androids and browsers physical buttons which take the user to where they came from instead of previous step in the process. I tried fixing it with locationChangeStart as well as few other similar events, but they all get triggered both by my "Continue" buttons as well as physical "back" buttons.
Is there a way to trigger an event only when user presses browsers/android's back button, or alternatively to know if locationChangeStart was triggered by the back button vs app's button? If possible, I would like avoid adding jQuery as we are not currently using it.
I gave up on trying to detect the user pressing back button and act on it. Instead, make it the default action and change the way our buttons behave. I detect when user is pressing one of our buttons and set a variable based on it.
var navigating = false;
$scope.$on('$locationChangeStart', function(event) {
if($scope.global.application="new-ad" && !navigating){
event.preventDefault();
$scope.areYouSure = true;
}
});
$scope.nextStep = function() {
navigating = true;
$location.url('/step-two');
}
Basically, we first set our variable to false, and if the user presses physical back, it will display the prompt alerting user they will lose their work. However, if the user instead uses our "continue" button, also triggering the locationChange, it will set variable to true, letting the app know what the locationChange is triggered from within the app and allowing it to continue.

Calendar appearing again after changing tabs or minimizing browser

I'm using pickadate jquery plugin and applying it to a field in a form page.
When the user clicks on the input field, there are 2 possible options I'm dealing with:
the calendar appears and the user selects a date (after that the calender automatically closes)
the user just close the calendar (selecting no dates)
What's happening is that after one of the 2 options above, if the user opens another tab in the browser (and then go back to the form tab) or minimize the browser (and then open it again in form tab), the calender shows up again.
This only happens if the last field selected is the one with the pickadate plugin applied to. If the user selects another field that does not contain the pickadate plugin and does that same process (of changing tabs or minimizing browser), the calender doesn't appear again.
What should I do to does not make the calender appear if the last field select is the one with the pickadate plugin applied to?
The code that calls the plugin is:
$(document).ready(function() {
$('.datepicker').pickadate();
});
Method 1 (This method worked for me)
Add onOpen to the initialization object.
var $input = $('.datepicker');
$input.pickadate({
onOpen: function () {
if ($input.hasClass('picker__input--target')) {
$input.pickadate().pickadate('picker').close(true);
}
}
});
Method 2 (This method didn't work for me. Maybe I didn't code it right).
Add onClose to the initialization object.
var $input = $('.datepicker');
$input.pickadate({
onClose: function() {
$input.blur();
}
}
});
Source from github
It seems to me that when the tab with the picker is brought back to focus the focus event for that input is being called again, thus causing the picker to pop back up.
I would tie into the window focus event
window.addEventListener('focus', function() {
// make sure input in question is not in focus
});
then make sure input in question is not in focus

ExtJS react to user clicks on tab in tabpanel

(Yes, I know this is similar to How can I attach an react to user clicking on tabs in Ext.TabPanel, but it is a different question)
I have a tabpanel, the panels of which can be accessed either by clicking on a tab, or by clicking links in other tabs. One tab in the tabpanel has a menu for the user to select the desired subpanel. What I am trying to achieve is that clicking on the tab does not activate it - thus forcing the user to select an option from the menu. However, I still want the panel to activate when a link on another panel is clicked, or when a menu option is selected.
This is how I disable the panel:
'beforeactivate': function (component, eOpts) {
//to prevent loading tab content on tab/menu click
console.debug('tab disabler', arguments);
return false;
}
It works - just works too well, blocking everything. I have not been able to find a way to detect the difference between clicking the tab and, well, doing anything else at all.
Basically you already described the problem: you want to prevent activation of the tab only when the tab header is clicked, not altogether, so the beforeactivate event is not the way to go.
You can access the tab header (which is basically just a button in the tab bar) via the tab property on the panel and prevent the execution of its handler by stopping the propagation of the click event:
panel.tab.on({
'click': function(tab, e) {
e.stopEvent();
}
});
Note: the docs say you can also return false to achieve the same, however that does not seem to work.
This won't affect activation of the panel at all, but the interaction on the tab header.
Check out this fiddle for a working example.

Categories