I want to use window.open to open a window to one of my JSP file. But the browser keeps showing connecting... And even firebug stops working every time I click the text. Neither the p nor the input tags work, but when I use a href to link the JSP it can link to the file:
<!DOCTYPE html>
<html>
<head><title>Sample JSP Page</title>
<script>
function open(){
//window.open("hello.jsp","hello","height=700, width=800");
var x=window.open("hello.jsp","window","status=1,height=700, width=800");
x.focus();
}
</script>
</head>
<body>
<h1>Sample JSP Page</h1>
<p onclick="open()">do not work</p>
<form>
<input type="button" value="new window" onclick="window.open('test-with-utils')"></form>
</body>
</html>
That's because you have redefined window.open when you defined the function open. Use a different function name instead.
Change the name of the function.
The window object is the top level object in JavaScript, and contains in itself several other objects, such as "document", "history" etc.
When you define a variable or a function of your own you really add a new property to the window object. And this will work ( and a little live example ):
var foo = "bar";
alert ( window.foo ); // says "bar"
In addition if you add this little snippet to your code:
window.onerror = function ( msg, url, num ) {
alert ( "Error: " + msg + "\nURL: " + url + "\nLine: " + num );
return true;
};
you will get this error, when press the button:
Error: Uncaught RangeError: Maximum call stack size exceeded
This means an endless recursion. It is a side effect - you define a new open function, and when you call window.open(), you recursively call your function.
Just to expand on the reason that you are having problems here, you may want to read a little about javascript Scope (Very Helpful Blog). Essentially, consider the following code:
<script>
var thisOne=true;
function thatOne() {
alert("whizbang");
}
var theOther={foo:"bar"};
//More code here...
</script>
Once you reach the comment, you know you can access those variables and the function directly, like if (thisOne) {...}, element.onclick=thatOne; or console.log(theOther.foo). However, you can also access them as children of the root object which, in a web browser, is called window. So you can do:
console.log(window["thisOne"]);
window.thatOne.call(obj, params);
console.log(window.foo.bar);
so by defining open() as a function which is not inside another element (which is to say, is inside the root element), you overwrite the window.open() function. When you attempt to call the function later on, you get problems because the open function calls window.open, which calls window.open, which calls window.open...
There's a few ways to get around this -
Define the onclick handler inline
To do this, get rid of the whole <script>..</script> element then, using whichever element you choose (that supports it) add the onclick attribute:
onclick="window.open('hello.jsp','window','status=1,height=700, width=800');"
This is a nice and quick method, and it keeps all the logic right there with it's triggering element, but it is not easily extensible and you may find yourself sneered at by some. ("Oh, you use inline javascript? how quaint")
change the method name
This will take the least effort from you in terms of getting your page working now from what you have (it's also essentially what everyone else has suggested). Just change the name of the open method to something like openANewWindow() or gotoJSP() or anything that doesn't already exist in the root object, making sure to get both where you define it (in the script element) and where you use it (in the onclick attributes).
Use a closure
This is almost definitely not what you want in this case, its more complexity than you need for a single function. Just including this as an example of how to get out of the root object, seeing as being in it seems to be the heart of your problem.
You have probably already seen in javascript how to define an object, but you may not know that by defining an object, all you are really doing is adding an object property to the root object. You can use this behavior to your advantage, to give a hierarchical structure to your functions.
For example:
<script>
var MyFunctions = (function() {
function open(){
var x=window.open("hello.jsp","window","status=1,height=700, width=800");
x.focus();
}
return {open:open};
})();
</script>
This creates an anonymous function that is immediately run. Inside the scope of this function, another function, open() is defined, however it is defined within the scope of that anonymous function, not the root object (window). After open() is defined, a reference to it is returned as the value of the object property: open.
The result of all this is that the open property of the MyFunctions object is the function you need. You can then call it with MyFunctions.open() or even window.MyFunctions.open().
Related
Coming from a C++ background, trying to work with an OO language that doesn't have explicit typing is a little more than a headache.
So I have dynamic elements for a webpage that are "controlled" by objects since there are tons of stuff I need to manage on each for it to work. The element is just the visual output of the data inside of the object itself, that's all I really need it for.
Except that I need the object to perform an internal function when it's clicked. That seems to be the biggest source of my headache thus far.
Javascript:
function onClick(file) //The external onClick function I use to try to get it to call from.
{
file.state = INUSE;
file.checkState();
}
function fileObject () { //The file object itself
this.element;
this.newElement();
//initialize stuff for the object
}
fileObject.prototype.newElement = function() { //creates a new element and sets its event listener
this.element.click(function() {onClick(this)});
}
fileObject.prototype.checkState = function() {/*does stuff*/} //apparently this is "not a function"
The error I get exactly is "file.checkState is not a function" from Firefox's console panel.
I'm still new to javascript, but after doing some debugging, I've come to find out that it's explicitly the onClick(this) function that is causing all of the errors. When used with something else, the onClick function works perfectly, but for some reason, the this keyword doesn't appear to actually be sending the reference to the fileObject since all checks show file being undefined when inside of the onClick scope.
Is there something fundamentally wrong about the way I'm trying to do this or am I just missing a step (or adding something that I don't need) that will help get this snippet working.
So you know, your initial problem isn't actually handling the action, but listening to it. click will trigger a synthetic click event, rather than liste for one.
You want ... .element.addEventListener("click", callback); that said, you face a second problem, immediately thereafter.
I will leave my example code as you've written it to not confuse the matter...
But when you see click( ) know that I mean subscribing with addEventListener, if element really does mean a browser DOM element. If it's not a standard browser element, and your own API, then ignore the previous portion, and carry on.
this is dynamically bound at the invocation time of the function (not at definition time).
The nearest function, scoped above, is your callback function that you are passing into .click( ... ).
Which is entirely different than the this which you mean outside of the callback.
Whatever is on the left-hand side of the dot is the this context for the duration of that particular invocation.
Needless to say, click() doesn't know enough to bind the this you mean, to the left-hand side of your callback.
The solution (or one of many) is to use lexical scoping and/or closure to retain the value of the object you mean.
// easy but messier
var fileObject = this;
... .click(function () { onClick(fileObject); });
// Cleaner with thunks:
function clickHandler (onClick, obj) {
return function () { onClick(obj); };
}
... .click(clickHandler(this));
Coming from c++ the way Javascript handles this will seem a little crazy, it looks like here you need to tell the function you've defined what this is - like so:
this.element.click(function() {onClick(this)}.bind(this));
I am trying to get some old code to work properly with minimal modification. The code was written on the assumption that it would run from a particular context. I have the context object.
Original code:
function oldExample(){
console.log(window); //New Error: window is undefined
console.log(gBrowser); //New Error: gBrowser is undefined
}
New, working code:
function fixedExample(){
console.log(this.window);
console.log(this.gBrowser);
}
//Elsewhere
function loadData(context) {
fixedExample.call(context);
}
Notes:
1. loadData and oldExample are defined in separate files.
2. context has other children besides window and gBrowser; This is an example
Is there a way to transition my oldExample code to work properly without needing to stuff this. everywhere? I.e., how can I run oldExample in a different context?
The only way I know how to do this is to define the properties as variables of the current context:
var object = {gBrowser: 'test'};
function oldExample(){
console.log(gBrowser);
}
var gBrowser = object.gBrowser;
oldExample();
This example outputs 'test'
But all this does is move the property access outside of the function definition, doesn't save you anything.
You can use bind method in javascript.
fixedExample.bind (context);
Now you need not use 'this' inside fixedExample and can use window directly.
I am new to JSONP and had implemented cross domain functionality for my application and everything is working fine. Now i want to change my javascript code to apply object orientation.
My api is
http://localhost:8080/myApplication/getComments?callback=displayComments
CrossDomain.prototype.displayComments = function(data) {
// code to display the comments
}
Now I am getting an error in firebug given below
ReferenceError: displayComments is not defined
I changed the api to
http://localhost:8080/myApplication/getComments?callback=this.displayComments
and found that the function is appended inline to the callback like this
http://localhost:8080/myApplication/getComments?callback=callback=function (jsonData)
{
//code to display the comments
}
this time another error in firebug
SyntaxError: function statement requires a name
I have a doubt whether to use JSONP in object oriented javascript or not.
Please help.
Thanks in advance.
There's no point in defining the function on the prototype of a function unless you are going to create instances of that function, so start by doing that.
var myCrossDomain = new CrossDomain();
Then you have to call the method on the object, not as a global (it isn't a global, so you can't do that anyway)
var uri = "http://localhost:8080/myApplication/getComments?callback=" +
encodeURIComponent("myCrossDomain.displayComments");
In response to edits and comments:
Yes i am creating an instance of this in another js file
Then reference it as shown above.
I changed the api to
http://localhost:8080/myApplication/getComments?callback=this.displayComments
It's JSON-P. It runs by adding a new script element. Everything gets called in the global context. That is going to call this.displayComments which will be the same as window.displayComments.
If you want to call your method directly, then you need to specify the global variable holding the instance explicitly.
If you don't want to call it directly then you can use the more traditional approach of generating a new, anonymous function which has access to said object through a closure, assigning that function to a global variable (with a unique name) and using that name as your callback argument.
and found that the function is appended inline to the callback like this
http://localhost:8080/myApplication/getComments?callback=callback=function (jsonData)
You haven't shown us the code that creates the URI so we can't tell why that might be the case.
I'm not even sure if this is possible, but is there anyway to set an execution context beyond setting the value for "this"?
The case I am primarily referring to is executing code from one frame in the context of another frame, so that when I access global objects (ex: window, document...) from a function that was defined in frame1, It will be executed in the frame2 environment.
If this is not possible, what are some workarounds? Please don't say "just define the function in the child frame", I'm dealing with a larger application framework, and it would be both pointless and memory inefficient if I had to load up two instances of the entire framework.
EDIT: Here is some code which should demonstrate what I am trying to do. When run, it should show an alert that, if a solution is found, displays "iframe.html" at the end of the location string.
<script>
function run() {
go.call(window.iframe);
}
function go() {
alert(window.location);
}
</script>
<iframe src="iframe.html" name="iframe" onload="run()">
Thanks.
This makes use of the deprecated with statement as well as eval, but it may be the only way to accomplish what you want.
function run() {
with (window.iframe) {
eval("(" + go.toString() + ")()");
}
}
function go() {
alert(window.location);
}
If you can "frame" your "integration" code in a closure that aliases window to window.iframe, you could achieve what you want:
(function(window) {
// your integration code...
// the whole code you want to frame...
alert(window.location);
})(window.iframe);
But, you have to "frame" all the code you want to interact with.
Also, you can expose "integration" functions for you to call from "outside" by passing other "context" objects in:
var context = {};
(function(window, context) {
// your integration code...
context.f = function() { ... };
// the whole code you want to frame...
alert(window.location);
})(window.iframe, context);
context.f();
Use Function.apply and Function.call.
function foo(x, y, z) {
console.log(this === someFrame); // true
}
foo.call(someFrame, 1, 2, 3);
EDIT
Based on your code sample and comments below, the answer is no. Scripts cannot change the global scope.
Include the code in both frames. Then, call the function in the other frame. Let's say there's a top level global function called doWork().
You field a button press in frame2 and you want to execute a function in frame1 (where frame1 is the window object representing frame1). Assuming they are in the same domain and pass the same-origin tests, you can simply reach into frame1 and call doWork() in that frame with:
frame1.doWork();
This works because all top level javascript global variables and functions are properties of the window object for that browser window/frame. Each window/frame has it's own set of top level properties. If you are within the same domain and can get the appropriate window object, you can just call javascript in that window. The javascript must be present in that window. You can't execute javascript from your window in the content of another window, but if you put the code in both windows, you can execute it in either window by starting with the right window object.
How you get the right window object for a particular frame depends upon how your frames are structured.
Again assuming these frames are in the same domain and pass the usual same-origin tests, it would also be possible write a javascript function in frame2 that operates on frame1 contents. For example, you could have this code in frame2:
frame1.document.getElementById("foo").value = "";
So, you couldwrite a function in frame2 that would operate on frame1. You cannot, however, just execute a function from frame2 in the content of frame1 without writing it to know about operating on a different frame.
For example, you could write a function like this that takes the desired window to operate on:
function clearValue(id, win) {
win.document.getElementById(id).value = "";
}
I'm trying to create hidden iframes in my page dynamically to load 3 other pages so that i can grab all the HTML and combine them into 1 in a new window.
However i'm stuck at this.
tHe frames are created fine.
But whenever the javascript runs to the part of
var printWindow="";
function openNewWindow()
{
printWindow = window.open("","");
printWindow.document.open();
printWindow.document.write(HTMLfromFrames);
printWindow.document.close();
}
i get this error:
TypeError: Result of expression 'printWindow' [undefined] is not an object.
but if i generate a button to call this function seperately, it works fine.
however i need it to run all in one click event
Anybody has any idea what's wrong?
Thanks!
It looks to me like a scoping problem. The scope of your printWindow object ends when openNewWindow returns; in other words, the variable only exists inside that function and disappears as soon as the function ends. Remove the var to make the variable available globally (considered bad form) or declare the variable elsewhere in your code and make sure it's available to openNewWindow when it executes.
oh i solved it. SOmehow i declared as a global var
then declare the obj earlier in the method.
printWindow = window.open("","");
still not sure why i can't declare it after i dynamically create my iframes.
Thanks for the help!:D