I'm writing my first Firefox XUL toolbar, and am getting a strange behavior - in order to debug my code, I call the same js function from both the firefox toolbar and from a button on a very simple HTML file I created.
The javascript function displays an alert window, gets an element using 'document.getElementById', changes its color, and displays another alert window.
The javascript function works well when called using the HTML button, but when using the toolbar button the 'document.getElementById' returns null and the function terminates (only the first alert window shows).
Any guess what can be wrong? I provide the (very simple) code below for refenrece.
Many thanks in advance!
The javascript file - facebrew.js
function FaceBrew_rtlSelection() {
alert('Before!');
sel_node = document.getElementById("header");
sel_node.style.color = 'blue';
alert('After!');
}
The HTML file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<script type="text/javascript" src="http://localhost/Sandbox/FaceBrew/chrome/content/facebrew.js"> </script>
</head>
<body>
<input type="button" value="Click me" id="select" onclick="FaceBrew_rtlSelection()" />
<div id="header">
<h1>Hello world!< /h1>
</div>
</body>
</html>
The XUL file - facebrew.xul
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://facebrew/skin/facebrew.css" type="text/css"?>
<overlay id="FaceBrew-Overlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript"
src="chrome://facebrew/content/facebrew.js" />
<toolbox id="navigator-toolbox">
<toolbar id="FaceBrew-Toolbar" toolbarname="FaceBrew Toolbar" accesskey="F"
class="chromeclass-toolbar" context="toolbar-context-menu"
hidden="false" persist="hidden">
<toolbaritem flex="0">
<toolbarbutton id="FaceBrew-Web-Button" tooltiptext=""
label="Run" oncommand="FaceBrew_rtlSelection()" />
</toolbaritem>
</toolbar>
</toolbox>
</overlay>
The CSS file - facbrew.css
#FaceBrew-Web-Button {
list-style-image: url("chrome://facebrew/skin/web.png");
}
as Paul said, when function is called from toolbar, document context is different. get your currently selected HTML document object with:
var doc = gBrowser.selectedBrowser.contentDocument;
doc.getElementById(...);
also, you can always take a look at error console to see why your code is failing (Tools -> Error Console).
Your toolbar is an overlay, so the context (document and window) is browser.xul, no your html file.
Related
I know that there are several similar questions, but I have to ask the question again with attached code because of being unable to work out.
I have two .xhtml file in JSF project. One is mainPage.xhtml has a button that generates dynamic html code to create an iframe (iFramePage.xhtml) and show it on the browser;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<h:outputStylesheet library="css" name="style.css" />
<script type="text/javascript">
/** Create dynamic iframe HTML code for iFramePage.xhtml **/
function createIFrameHTML(){
document.getElementById("iFrameContainer").innerHTML = '<div id="iframe0"><iframe src="iFramePage.xhtml" width="450px" height="300px"></iframe></div>';
}
/** Close iFrame **/
function removeElement() {
/*Both lines work properly when I call inside this page, */
/*..however it does not work by calling from iFramePage.xhtml */
//document.getElementById("iFrameContainer").removeChild("iframe0");
$('iframe0').remove();
}
</script>
</h:head>
<body>
<f:view>
<h:form id="mainForm">
<!-- Control Menu -->
<div id="cntrMenu">
<h:commandButton id="cntrBtn1"
onclick="createIFrameHTML();return false;"></h:commandButton>
<h:commandButton id="cntrBtn2"
onclick="removeElement();return false;"></h:commandButton>
</div>
<div id="iFrameContainer">
<!-- an iframe will be generated by createIFrameHTML() -->
</div>
</h:form>
</f:view>
</body>
</html>
The other page is iFramePage.xhtml that has some html and javascript code;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<h:outputScript name="......js" />
<h:outputStylesheet name="....css" />
<script>
/** Close iFrame.**/
function closeSelf() {
/* Two lines works properly, however third line does not work!*/
//window.top.location.href = "HIDDEN";
//parent.document.location.href = "HIDDEN";
parent.removeElement();
}
</script>
</h:head>
<body>
<input jsfc="h:commandButton" id="exitBtn" value="Kapat" onclick="closeSelf();" />
</body>
</html>
I can generate the iframe by clicking "cntrBtn1" button and removing by clicking "cntrBtn2" inside mainPage.xhtml. However, I need to remove the iframe within itself (iFramePage.xhtml). When I click "exitBtn" in iFramePage.xhtml, the iframe does not disappear. There is nothing about cross-domain, because mainPage.xhtml and iFramePage.xhtml are in the same JSF project, even in the same directory. I can redirect the parent page (looks at two lines in closeSelf() in iFramePage.xhtml), but I cannot remove the iframe by using parent element, why! Please, help me :)
Communicate between the parent and iframe using window.postMessage.
Replace the closeSelf() function in iframe page to the following :
function closeSelf() {
parent.window.postMessage("removetheiframe", "*");
}
and on the parent page, add the following code to listen when the iframe sends a message :
function receiveMessage(event){
if (event.data=="removetheiframe"){
var element = document.getElementById('iframe-element');
element.parentNode.removeChild(element);
}
}
window.addEventListener("message", receiveMessage, false);
You can also check the origin of postMessage by event.origin to make sure that the right iframe requested to remove the iframe.
I have below code in one (main) Facelets page,
<h:panelGroup rendered="true">
<ui:insert>
<ui:include src="/includeSecondPage.xhtml" />
</ui:insert>
</h:panelGroup>
Below is the content in includeSecondPage.xhtml page,
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<script type="text/javascript">
/* <![CDATA[ */
function myScript ()
{
alert("Inside myScript");
}
myScript();
/* ]]> */
</script>
</head>
<f:view>
<body>
<h:form id="secondForm">
<ui:composition>
<h:outputText value="This panel is called using Component Control Component"></h:outputText>
</ui:composition>
</h:form>
</body>
</f:view>
</html>
My Java Script is not getting called in my includeSecondPage.xhtml. Alert box is not popping up in my first (main) page which includes this second page. And there are no Java Script errors in Java Script console.
Anything outside <ui:composition> is discarded during include. Any content outside <ui:composition> is only used by visual editors such as Dreamweaver and should actually only represent "fill up" content in such way so that the include content is "properly" visually represented. If you have looked closer at the JSF-generated HTML output by rightclick, View Source in browser, you'd have noticed that those parts are completely absent in the HTML output.
Put the include content inside <ui:composition>. If you aren't using a visual editor, then also just get rid of anything outside <ui:composition>. Here's how your entire include file can look like:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<script type="text/javascript">
// <![CDATA[
function myScript () {
alert("Inside myScript");
}
myScript();
// ]]>
</script>
<h:outputText value="This panel is called using Component Control Component" />
</ui:composition>
See also:
How to include another XHTML in XHTML using JSF 2.0 Facelets?
I am attempting to code a simple example of a Dojo dialog box. I have copied the example shown in the Dojo reference here => http://dojotoolkit.org/reference-guide/1.7/dijit/Dialog.html
My code is shown below:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Dialog Test</title>
<script language="JavaScript" type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dojox.widget.Dialog");
dojo.require("dijit.form.Button");
dojo.require("dijit.layout.TabContainer")
dojo.require("dijit.layout.ContentPane")
</script>
</head>
<body>
<div id="dialogOne" dojoType="dojox.widget.Dialog" title="My Dialog Title">
<div dojoType="dijit.layout.TabContainer" style="width: 200px; height: 300px;">
<div dojoType="dijit.layout.ContentPane" title="foo">Content of Tab "foo"</div>
<div dojoType="dijit.layout.ContentPane" title="boo">Hi, I'm Tab "boo"</div>
</div>
</div>
<p>When pressing this button the dialog will popup:</p>
<button id="buttonOne" dojoType="dijit.form.Button">Show me!
<script type="dojo/method" event="onClick" args="evt">
// Show the Dialog:
dijit.byId("dialogOne").show();
</script>
</button>
</body>
</html>
When the page loads in a browser, the Dialog doesn't work. I just see the text from the tabbed panes appear in the browser.
I've copied the code from the reference guide exactly so I'm very confused. Any suggestions?
Thanks.
James.
The Dojo samples unfortunately tend not to work fully 'as is', but are bits of skeleton code that need wrapping up in various standard bits of ceremony.
You've at least three things causing this not to work and render correctly. There may be other problems on top, but these will definitely cause it not to render:
You need to link to a version of the core Dojo scripts. Linking to a CDN version is a simple way to go. e.g. <script src="//ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojo/dojo.js"></script>. Details are here: http://dojotoolkit.org/download/. Be sure to put this before your require scripting.
Add a link to a Dijit theme style sheet (CSS file) in your page, otherwise none of the widgets will display correctly. e.g. <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dijit/themes/claro/claro.css"/>
Add a class attribute on the body element describing which theme you want to use. e.g. <body class="claro">.
Only when you've done all those three things will it have a chance of working. There may be other problems too, but they're the fundamental three.
I'm having some problems with getting one of my site pages with IE8. It works fine in IE9, Safari (both PC & Mac) & Firefox (Mac). I'm using a find(tag1).html(tag1) call sequence to do a title substitution, but I get the following error in IE8 when I debug it in the IE script debugger, and this in the html(tag2) function:
Unexpected call to method or property access
The find(tag1) function seems to return the enclosing object (i.e. #sidebar), rather than the nested object #sidebarheader, and this causes problems when later making the html(tag2) call.
I've created a representative test case as follows:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JQuery .find() test case</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.js"></script>
<script type="text/javascript">
function UpdateHeader() {
$('#sidebar').find('header').html("New Title"); // IE8, nesting div's in the find fct. will not discover the child div
}
document.ready = UpdateHeader;
</script>
</head>
<body>
<div style="height: 400px; width: 390px">
<div id="jqm-home">
<div id="page">
<div id="sidebar">
<div id="sidebarheader">
<header>Old Title</header>
</div>
</div>
</div>
<p onclick="UpdateHeader();">Click to update title</p>
</div>
</div>
</body>
</html>
And here is the jsFiddle test case:
http://jsfiddle.net/bnmcK/21/
Has anybody a suggestion on how to get this to work in IE8?
In order to support the new HTML 5 elements in older versions of IE (8 and below), there's a handy trick, which involves creating a dummy element before running your script.
So, simply calling document.createElement('header'); in your page will solve the problem, see here.
For the full explanation, this post does a nice job of providing an explanation.
Also, html5shiv is a project that solves this problem for other elements too.
<header> is a HTML5 tag, which IE8 doesn't know about (IE9 however, supports this tag). Since you're declaring XHTML 1.0 transitional, I'd suggest using a <h1> tag instead, which will work just fine in IE8.
I've got simple html on Login.aspx with an ActiveX object:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head><title></title>
<script language="javaScript" type="text/javascript">
function getUserInfo()
{
var userInfo = MyActiveX.GetInfo();
form1.info.value = userInfo;
form1.submit();
}
</script>
</head>
<body onload="javascript:getUserInfo()">
<object id="MyActiveX" name="MyActiveX" codebase="MyActiveX.cab" classid="CLSID:C63E6630-047E-4C31-H457-425C8412JAI25"></object>
<form name="form1" method="post" action="Login.aspx">
<input type="hidden" id="info" name="info" value="" />
</form>
</body>
</html>
The code works perfectly fine on my machine (edit: hosted and run), it does't work on the other: there is an error "Object doesn't support this property or method" in the first line of javascript function. The cab file is in the same folder as the page file. I don't know javascript at all and have no idea why is the problem occuring. Googling didn't help. Do you ave any idea?
Edit: on both machines IE was used and activex was enabled.
Edit2: I also added if (document.MyActiveX) at the beggining of the function and I still get error in the same line of code - I mean it looks like document.MyActiveX is true but calling the method still fails
I think the onload event is making the function to run even before the ActiveX object is loaded. You may try the following instead:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title></title>
<script language="javaScript" type="text/javascript">
function getUserInfo(){
if(document.MyActiveX){
var userInfo = MyActiveX.GetInfo();
form1.info.value = userInfo;
form1.submit();
}
}
</script>
</head>
<body>
<object id="MyActiveX" name="MyActiveX" codebase="MyActiveX.cab" classid="CLSID:C63E6630-047E-4C31-H457-425C8412JAI25"></object>
<script for="window" event="onload" language="JavaScript">
window.setTimeout("getUserInfo()", 500);
</script>
<form name="form1" method="post" action="Login.aspx">
<input type="hidden" id="info" name="info" value="" />
</form>
</body>
</html>
Now the getUserInfo() function will start to run 500 milliseconds after the page is loaded. This must give some time for the ActiveX object to be loaded.
IE8 manages access to the ActiveX on domain level.
To fix it:
IE8, Tools -> Manage Add-ons
In "Toolbars and Extensions" find your ActiveX
Right click - More information
Click - Allow on all sites
Enjoy
maybe the browser on the other machine does not support activeX? just a wild guess
Maybe the ActiveX needs some prerequisite (For example CRuntime) that isn't present on the other machines? Have you tried running depends for the Activex on the hosting machine?
Maybe the other machine has a virus scanner or similar which silently prevents ActiveX use?