How can I Detect when a Firefox WebPanel is closed? - javascript

I am interested in opening a webPanel on the right side of the Firefox window. Based on an MDN article, I determined that this could be done by setting the browser element's direction style. However, I wish to clear out this setting after the webPanel is closed. Is there a way I can detect this? Thus far, the only way I can think of is to poll sidebarWindow.location.href (to detect if the sidebar is changed) and sidebarHidden (to detect if the sidebar is closed).
var browser = document.getElementById('browser');
browser.style.direction = "rtl";
var sidebarWindow = document.getElementById("sidebar").contentWindow;
var sidebarBox = document.getElementById('sidebar-box');
var sidebarHidden = sidebarBox.collapsed || sidebarBox.hidden;
sidebarWindow.addEventListener("unload", function (event) {
alert("1"); //This code fires when the web panel is opened
//but not when it is closed.
});
sidebarBox.addEventListener("unload", function (event) {
alert("2"); //This code does not fire.
});
sidebarWindow.addEventListener("close", function (event) {
alert("3"); //This code does not fire.
});
sidebarBox.addEventListener("close", function (event) {
alert("4"); //This code does not fire.
});
openWebPanel('Test', 'http://www.google.com');

IIRC there are essentially three ways a sidebar can be "closed":
The user closes it using the GUI (X-box) or keyboard shortcut. In this case, the web panel will not necessarily get unloaded, so there is no unload event.
Another document is loaded into the web panel. In this case you might get an unload.
The user opens another panel. There is not necessarily an unload.
Should you go forward with your implementation, you need to make sure your code handles all three correctly.
and 3. should be observable by the <broadcaster id="viewWebPanelsSidebar"> changing the checked attribute (see the implementation of toggleSidebar()), so you could have another element observing and acting on onbroadcast.
should listen for unload and act accordingly.
To get proper unload events, I think the following should do the trick:
sidebar.contentDocument.getElementById("web-panels-browser")).
addEventListener("unload", ...);
But my memory there is a bit wonky, so you might need to fiddle with that a bit. (The sizebar has a <xul:browser id="web-panels-browser"> which displays the actual content...)
After having said all that: I think it is a bad idea to mess with the sidebar like this.
The MDN wiki(!) has bad advice in this case.
The sidebar was not designed to be messed with like this.
There are other add-ons "competing" with yours when it comes to messing with the sidebar.
The sidebar code is, for the most part, pretty archaic and under-maintained. Getting things like your requirement to work correctly is pretty hard. There still might be other code (in add-ons) that could dismiss the sidebar that you and I didn't think of.
The sidebar might not be the best place to display your content in the first place (what that content would be you didn't say). If it's something like context-help, dictionary/definition lookup results, login forms, then it won't be a good fit.
Some users might not like that their always-on bookmarks/history sidebar gets replaced by yours. You could handle this by re-opening the previous one, but that will only complicate matters further.
You might be better off using some other way to display information - e.g. a new tab, a panel, a new sidebar like the social sidebar... E.g the social sidebar is not only on the right, it actually is a standalone sidebar not part of the "main" sidebar.

Related

Is it arriving the javascript later than the html?

I'm trying to change the size of a pop-up and give it the same width than the screen, sent from an iframe.
var screen_width = parent.screen.width;
Then I got the html:
<a href="#" onClick="window.open('https://www.google.com','popup', 'width='"+screen_width+"',height=400px')">
I've tryed all possible convinations with the ' " or whatever I know, but I think it should work lie this.
Sorry if it's obvious, my coding skills are not so developed, but I think, it's possible, html it's loading before javascript?
P.D.: One more thing, I want to use a variable, because I want to change a bit the real size of the screen.
One problem you might be having is that in your window.open() options, you shouldn't specify px... just put the number for your height.
In any case, here's a better implementation of what you're trying to do. In your HTML:
<a href="http://example.com" target="_blank" data-fullpopup>Click me!</a>
This way, your link will work, and will even open in a new tab/window if your JavaScript doesn't run for some reason. This is a good fallback. The key here is the data-fullpopup attribute, which we'll look for in your JavaScript:
document.addEventListener('DOMContentLoaded', (e) => {
document.querySelector('body').addEventListener('click', (e) => {
if (!e.target.matches('a[data-fullpopup]')) {
return;
}
window.open(e.target.href, 'popup', 'width=' + window.screen.width + ',height=400');
e.preventDefault();
});
});
Basically, we wait for the document to fully load so that we can attach a click handler to the body element. (Note: If you're only doing this for a couple links, it's better to attach the click handler directly to them. I'm attaching it to body here, assuming that you'll have a lot of these sorts of links... it's more efficient to have one click handler in those cases. Remember though that then this click handler has to run for every click for any element on the page. Choose your tradeoff for your use case.)
Once the link is clicked, we confirm that it's a link with our data-fullpopup attribute. If it is, we treat it like a full-width popup. We get the target (the element) href on the fly, as well as the current screen width. Finally, we prevent the default action so that it also doesn't navigate to the page on its own.
https://jsfiddle.net/L5p0xk98/3/
As mentioned in the comments, you can do this without setting a variable first:
Click Me

Setting viewScope onLoad and onResize

I have used the '#media only screen' in my CSS to determine how and what information should be shown depending on the users screen size. I have a class called panelContainer which is set to display when the screen is greater than 767px, and a class called mobileContainer which displays when the screen is less than that.
I have a couple of custom controls, one that contains the standard form layout and another that contains the mobile device form layout. Originally I placed a div around each with the appropriate styleClass. The problem with it this way was that although only one form is visible, they were both loaded so this caused save issues.
<xp:div id="panelContainer" styleClass="panelContainer">
<xc:content_sCompany></xc:content_sCompany>
</xp:div>
<xp:div id="mobileContainer" styleClass="mobileContainer">
<xc:content_iCompany></xc:content_iCompany>
</xp:div>
I have since added a div to my Xpage with the styleClass of panelContainer, I then added onLoad and onResize events which return the style.display of the div, these should then write the result to a viewScope. But I found it would only write onLoad and although the function was being called onResize it wouldn't change the viewScope variable.
<xp:scriptBlock id="scriptBlock1" type="text/javascript">
<xp:this.value>
<![CDATA[var init = function() {
obj=document.getElementById('formType');
if(getStyleDisplay(obj)=="none"){
formType='#{javascript:viewScope.put("formFormat","mobile");}';
}else{
formType='#{javascript:viewScope.put("formFormat","standard")}';
}
}
dojo.addOnLoad(init);
dojo.connect(window,"onresize",init);
function getStyleDisplay(obj) {
if(obj.currentStyle) { // IE – Opera
return obj.currentStyle.display;
} else { // firefox
return getComputedStyle(obj,'').getPropertyValue('display');
}
}]]>
</xp:this.value>
</xp:scriptBlock>
<div id="formType" class="panelContainer"></div>
.....this viewScope variable is then used in the following way:
<xc:content_Company xp:key="ContentControl">
<xp:this.facets>
<xc:content_sCompany id="content_sCompany"
xp:key="standard">
</xc:content_sCompany>
<xc:content_iCompany id="content_iCompany"
xp:key="mobile">
</xc:content_iCompany>
</xp:this.facets>
</xc:content_Company>
.....extract from content_Company......
<xp:callback facetName="#{viewScope.formFormat}" id="cbkCompanyFormContent">
</xp:callback>
I feel this is the better way to achieve the result I need, as when I have tried it manually it does only load one of the forms and they work as expected.
I cannot see why the viewScope is not being set properly, it is always being set to 'standard', even if I shrink my page before loading the page. I did try writing the value to a Hidden Input, which worked but whenever I tried to access the value using getComponent("hiddenInput1").getValue() it would return null, even though I could see that value had been set when viewing in firebug.
Ok can you check (or tell me if you already have) through some console.log("") 's that the onResize is being called and the correct display is being pulled down etc.
next it may be firing the onResize but are you then partail refreshing the area which is using the viewScope?
Code example of this: (replace controlID with yours)
XSP.partialRefreshGet("controlID", {
onError: function() { console.log('Error'); }
});
I'm a little confused about what the purpose of using onResize is for ? if is to decide what to show whether on mobile or normal screen there are much more efficient ways of doing this.
Using the new redirect control in the latest release of the ExtLib on openNTF. It does exactly what the name suggests and redirects based on certain expressions. leaving you to drop it on a page and say if mobile (or whatever) redirect to this page.
Having a dummy default load page that checks the useragent string to see which page to load (having a separate mobile / fullscreen pages). This is what the teamroom template application that comes with the ExtLib does with its main.xsp and then this is set as the default launch option.
Or if you are trying to do something with whether the phone / tablet is on landscape or portrait you should be using the onOrientationChange event not onResize. check out this example (not the code in the question is what I'm pointing you too, he has a problem getting that to work in a webview):
how to handle javascript onorientationchange event inside uiwebview

How do I discover which function is called when I press a button?

I'm stuck modifying someone else's source code, and unfortunately it's very strongly NOT documented.
I'm trying to figure out which function is called when I press a button as part of an effort to trace the current bug to it's source, and I"m having no luck. From what I can tell, the function is dynamically added to the button after it's generated. As a result, there's no onlick="" for me to examine, and I can't find anything else in my debug panel that helps.
While I prefer Chrome, I'm more than willing to boot up in a different browser if I have to.
In Chrome, type the following in your URL bar after the page has been fully loaded (don't forget to change the button class):
var b = document.getElementsByClassName("ButtonClass"); alert(b[0].onclick);
or you can try (make the appropriate changes for the correct button id):
var b = document.getElementById("ButtonID"); alert(b.onclick);
This should alert the function name/code snippet in a message box.
After having the function name or the code snippet you just gotta perform a seach through the .js files for the snippet/function name.
Hope it helps!
Open page with your browser's JavaScript debugger open
Click "Break all" or equivalent
Click button you wish to investigate (may require some finesse if mouseovering page elements causes events to be fired. If timeouts or intervals occur in the page, they may get in the way, too.)
Inspect the buttons markup and look at its class / id. Use that class or id and search the JavaScript, it's quite likely that the previous developer has done something like
document.getElementById('someId').onclick = someFunction...;
or
document.getElementById('someId').addEventListener("click", doSomething, false);
You can add a trace variable to each function. Use console.log() to view the trace results.
Like so:
function blah(trace) {
console.log('blah called from: '+trace);
}
(to view the results, you have to open the developer console)

Implement a Back-Button 'Warning' in Javascript for use in Flex

I have a Flex application where I want to give the user a warning if they hit the back-button so they don't mistakenly leave the app. I know this can't be done entirely in Actionscript due to cross-browser incompatibility. What I'm looking for is just the Javascript implementation to catch the back-button.
Does anyone have a simple non-library cross-browser script to catch the back-button? I can't seem to find a post that shows an example.
You can use the window.onbeforeunload event.
window.onbeforeunload = function () {
return "Are you sure you want to leave my glorious Flex app?"
}
The user can press okay to leave, cancel to stay.
As you stated, this throws the alert any time the page changes. In order to make sure it only happens on a back button click, we have to eliminate the alert message whenever they're leaving the page from natural, expected sources.
var okayToLeave = false;
window.onbeforeunload = function () {
if (!okayToLeave) {
return "Are you sure you want to leave my glorious Flex app?"
}
}
function OkayToLeave() {
okayToLeave = true;
}
You'll have the responsibility of setting the variable to true whenever they click a button or link that will take them from that page naturally. I'd use a function for unobtrusive javascript.
Set your event handlers in the DOM ready:
referenceToElement.addEventListener('onClick', OkayToLeave(), false);
This is untested, but should point you in the right direction. Although it may seem like a nuisance to do this, I imagine it's more complete functionality. It covers the cases where a user may click on a favorite, or be redirected from an external application.

How to prevent page's scroll position reset after DOM manipulation?

I've got two JS functions, one that is adding options to a select box
function addOption(selectId, text, value) {
var selectbox = document.getElementById(selectId);
var optNew = document.createElement('option');
optNew.text = text;
optNew.value = value;
try {
selectbox.add(optNew, null); //page position resets after this
}
catch(ex) {
selectbox.add(optNew);
}
}
and another that is doing a document.getElementById(formId).appendChild(newHiddenInput) in a similarly simple function.
They both work, elements are added as expected. However, upon calling either of them, the page resets its scroll position to the top of the page in both IE6 and FF. There is no postback, this is purely clientside manipulation. I've set breakpoints in Firebug, and it occurs immediately after the element.appendChild or select.add gets executed. I know I can use JS to manually set a scroll position, but I didn't think it was necessary when the page isn't being re-rendered.
I'm no expert with JS or the DOM, so I may very well be missing something, but I've looked here and ran through their examples with the Try it Here options and I can't replicate the problem, indicating the codebase I'm working with is the culprit.
Any ideas why the scroll position is being reset? jQuery is available to me as well, if it provides a better alternative.
If the functions are being called from a link you might have an internal anchor in your link:
http://www.website.com/page.html#
This is causing said behavior. The default behavior is that if an anchor does not exist, the page scroll position jumps to the top (scrollTop = 0).
If this happens on every function call regardless of the source, then this can be crossed off the list.
What is activating the event?
If it's an anchor then on the click event you need to "return false;" after the call to your jQuery/Ajax/jScript code.
If it's a button you may need to do the same.
I had this issue yesterday and this was the resolution.
So My link

Categories