'ggbApplet is not defined' error in javascript - javascript

I have a web page which include a geogebra applet. On loading the page I would like to modify certain elements in the applet, depending on user input. I tested the following code
<script type="text/javascript">
var parameters = {
"width":600,"height":450,
"filename":"trois_ensembles.ggb"};
var applet = new GGBApplet('5.0', parameters);
window.onload = function() {
applet.inject('applet_container');
ggbApplet.setVisible('A', false);
}
</script>
But the line
ggbApplet.setVisible('A', false);
produces an error in the console
ReferenceError: ggbApplet is not defined
When ggbApplet is referenced elsewhere, as in
<button onclick="ggbApplet.setVisible('A', true)">Set A </button>
everything works as expected.
I don't understand the scope of ggbApplet. Help appreciated.

Checking Global JavaScript section of Scripting page of Geogebra's wiki may be useful.
Cheers.
See this section:
Note: Using any ggbApplet methods in Global JavaScript outside of ggbOnInit will not work as intended since they will be called before the construction is loaded.

Related

QuerySelector Not Working in Rails Webpacker

I have the following JavaScript loaded into Webpacker:
'use strict';
(function() {
alert("This shows up.");
var someObject = document.querySelectorAll('[data-toggle="thing"]');
})();
I know that the file is loaded into Webpacker correctly and is executed because I see the alert This shows up.. However, when I go into the console, someObject is an empty array despite the page containing an object with the data-toggle attribute.
I don't see any errors in the console to help diagnose the issue.
I am guessing that the problem involves the script executing before the page is loaded? However, I'm not sure how to remedy that situation when using Rails 6 with Webpacker...
Any assistance would be hugely appreciated!
You may need to wrap your code in an event listener callback that will execute when the DOM is loaded. This may be the case if your script tag is in the <head>; it executes before the rest of the page is loaded.
window.addEventListener('DOMContentLoaded', (_event) => {
let someObject = document.querySelectorAll('[data-toggle="thing"]');
});
You also don't necessarily need to wrap your code in an IIFE (i.e., (function() { })() because each file in webpack is (typically) treated as module with its own function scope.

Function Undefined: Must a javascript function be defined within the same file?

I've got a file notifications.js containing one event bound to an element, and a function updateNotification(). This function uses jQuery to update certain elements on the page when a JSON object is passed as a parameter.
The problem:
I'm attempting to call this function within the page (via <script> tags), however rather than calling it, it breaks the page. I did some digging around within the Chrome Developer Console (not sure of the name), and an error is flagged:
/pleaseshare/views/install/:50 Uncaught ReferenceError:updateNotification is not defined
However, when I pan within the console, I can clearly see the file notifications.js listed under scripts, and the function is defined there. If I define the function within the current scope (e.g. the line above the call), it works fine.
What I've tried
The function contains some javascript that requires jQuery, so I've attempted both with and without encasing it in $(document).ready( function() {});, with neither seeming to have any affect.
I'm pretty stumped.
For good measure, here's a link to show the structure of my javascript and html: http://snippi.com/s/znk6xe9
Any help in figuring out why this is happening, or explanations of why javascript functions cannot be called cross-file (although I'd hope this isn't the case), would be greatly appreciated ;)!!
A function cannot be called unless it was defined in the same file or one loaded before the attempt to call it.
A function cannot be called unless it is in the same or greater scope then the one trying to call it.
You code looks like the structure should work, but is clearly a reduced test case that has been reduced to the point where it won't.
Got it working. The issue was definitely multi-faceted, but I figured it out.
First off the use of RequireJS had an impact on updateNotification(), in that it couldn't be called cross-file, and was therefore considered undefined. I assume this because of how RequireJS loads files, and I'll look into the documentation later (and post an edit if I find anything relevant).
Secondly, updateNotification() would again be considered undefined when encased within jQuery's DOM ready loader $(document).ready(function(){}). However updateNotification() contains executions which require jQuery, so I had to encase the contents of the function in $(document).ready(function(){}).
This is an issue very unique to RequireJS/jQuery, hence why in most use cases this wouldn't occur.
Side note: The tags are edited to reflect this.
you need to import your script into your page:
<script type="text/javascript" language="javascript" src="path/to/notifications.js"></script>
This needs to be added above the <script> tag that calls updateNotification()
Functions do not need to be declared in the same file. In fact, avoiding having every declaration dumped into the global namespace is usually a concern in JavaScript.
In the sample code in the link you provided, updateNotification is declared as a global, so there should not be a scoping problem.
However, in the same sample, you don't show notifications.js being included. You need to import it using a <script></script> element and that element must come before the script element that includes the call to updateNotification. You also must include jQuery before notifications.js, since it uses jQuery. So you need something like:
<body>
// One or two elements
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="notifications.js"></script>
<script type="text/javascript">
$(document).ready( function() {
var json = {status : 'ok', message: 'Hello'};
updateNotification(json);
});
</script>
// All other elements
</body>

Executing injected Javascript code in a page when developing a Firefox extension

I'm developing a Firefox extension which places a button in the status bar. When the button is clicked, the extension injects some Javascript into the current page. This Javascript has a function that I would like to invoke with some parameters. I've managed injecting the code, I've inspected the page through Firebug and verified that the JS has been injected. How can I call a Javascript function in the page from my extension?
--More information
Here's the code that I'm using to inject my Javascript:
var doc = window.content.document;
//Add the script
var visibilityJS = doc.createElement("script");
visibilityJS.setAttribute("type", "text/javascript");
visibilityJS.setAttribute("charset", "UTF-8");
visibilityJS.setAttribute("src", "chrome://visibility/content/scripts/visibility.js");
head.appendChild(visibilityJS);
//Call the function
alert("Executing testfunction");
window.content.document.defaultView.testFunction();
..and the code inside my JS file that i'm going to inject. i.e. visibility.js
window.testFunction = function() {
alert("Message");
}
Thanks.
This worked. I don't know the technicalities. I got part of the solution from Felix and part of it from here.
window.content.document.defaultView.wrappedJSObject.testFunction();
If you declare a global variable in your injected code (or explicitly set a property of the window object), then one way do get a reference to this element from your extension, is via the gBrowser object:
gBrowser.contentDocument.defaultView.yourObject
^-- HTML document ^
object |-- window object
Be careful though, when you use window and document inside your code. Depending on the context it might refer to the Firefox window or the website window object.

Injecting JS functions into the page from a Greasemonkey script on Chrome

I have a Greasemonkey script that works just fine in Firefox and Opera. I struggle with getting it to work in Chrome, however. The problem is injecting a function into the page that can be invoked by code from the page. Here's what I'm doing so far:
First, I get a helper reference to the unsafeWindow for Firefox. This allows me to have the same code for FF and Opera (and Chrome, I thought).
var uw = (this.unsafeWindow) ? this.unsafeWindow : window;
Next, I inject a function into the page. It's really just a very thin wrapper that does nothing but invoking the corresponding function in the context of my GM script:
uw.setConfigOption = function(newValue) {
setTimeout(setConfigOption, 0, newValue);
}
Then, there's the corresponding function right in my script:
setConfigOption = function(newValue) {
// do something with it, e.g. store in localStorage
}
Last, I inject some HTML into the page with a link to invoke the function.
var p = document.createElement('p');
p.innerHTML = 'set config option to 1';
document.getElementById('injection-point').appendChild(p);
To summarize:
In Firefox, when the user clicks that injected link, it will execute the function call on the unsafeWindow, which then triggers a timeout that invokes the corresponding function in the context of my GM script, which then does the actual processing. (Correct me if I'm wrong here.)
In Chrome, I just get a "Uncaught ReferenceError: setConfigOption is not defined" error. And indeed, entering "window.setConfigOption" into the console yields an "undefined". In Firebug and the Opera developer console, the function is there.
Maybe there's another way to do this, but a few of my functions are invoked by a Flash object on the page, which I believe makes it necessary that I have functions in the page context.
I took a quick look at the alternatives to unsafeWindow on the Greasemonkey wiki, but they all look pretty ugly. Am I completely on the wrong track here or should I look more closely into these?
RESOLUTION: I followed Max S.' advice and it works in both Firefox and Chrome now. Because the functions I needed to be available to the page had to call back into the regular ones, I moved my whole script to the page, i.e. it is completely wrapped into the function he called 'main()'.
To make the extra uglyness of that hack a little bit more bearable, I could at least drop the usage of unsafeWindow and wrappedJSObject now.
I still haven't managed to get the content scope runner from the Greasemonkey wiki working. It should do the same and it seems to execute just fine, but my functions are never accessible to <a> elements from the page, for example. I haven't yet figured out why that is.
The only way to communicate with the code running on the page in Chrome is through the DOM, so you'll have to use a hack like inserting a <script> tag with your code. Note that this may prove buggy if your script needs to run before everything else on the page.
EDIT: Here's how the Nice Alert extension does this:
function main () {
// ...
window.alert = function() {/* ... */};
// ...
}
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head || document.documentElement).appendChild(script);
I have this :
contentscript.js :
function injectJs(link) {
var scr = document.createElement('script');
scr.type="text/javascript";
scr.src=link;
document.getElementsByTagName('head')[0].appendChild(scr)
//document.body.appendChild(scr);
}
injectJs(chrome.extension.getURL('injected.js'));
injected.js :
function main() {
alert('Hello World!');
}
main();
The other answers either force you to use function expressions, import an external additional file or use a long patched hack.
This answer will add the javascript into the page directly from your source code. It will use ECMAScript 6 (ES6) template literals to get the multi-line javascript string effortlessly onto the page.
var script = document.createElement('script');
script.type = "text/javascript";
script.innerHTML = `
function test() {
alert(1);
}
`;
document.getElementsByTagName('head')[0].appendChild(script);
Please note the backticks `` that define the beginning and the end of a multi-line string.
I took a quick look at the alternatives to unsafeWindow on the Greasemonkey wiki, but they all look pretty ugly. Am I completely on the wrong track here or should I look more closely into these?
You should look, because it's only available option. I'd prefer to use location hack.
myscript.user.js:
function myFunc(){
alert('Hello World!');
}
location.href="javascript:(function(){" + myFunc + "})()"
example.com/mypage.html
<script>
myFunc() // Hello World!
</script>
Sure, it's ugly. But it's working well.
Content Scope Runner method, mentioned by Max S. is better than location hack, because its easier to debug.

Why is my JavaScript function sometimes "not defined"?

I call my JavaScript function. Why do I sometimes get the error 'myFunction is not defined' when it is defined?
For example. I'll occasionally get 'copyArray is not defined' even in this example:
function copyArray( pa ) {
var la = [];
for (var i=0; i < pa.length; i++)
la.push( pa[i] );
return la;
}
Function.prototype.bind = function( po ) {
var __method = this;
var __args = [];
// Sometimes errors -- in practice I inline the function as a workaround.
__args = copyArray( arguments );
return function() {
/* bind logic omitted for brevity */
}
}
As you can see, copyArray is defined right there, so this can't be about the order in which script files load.
I've been getting this in situations that are harder to work around, where the calling function is located in another file that should be loaded after the called function. But this was the simplest case I could present, and appears to be the same problem.
It doesn't happen 100% of the time, so I do suspect some kind of load-timing-related problem. But I have no idea what.
#Hojou: That's part of the problem. The function in which I'm now getting this error is itself my addLoadEvent, which is basically a standard version of the common library function.
#James: I understand that, and there is no syntax error in the function. When that is the case, the syntax error is reported as well. In this case, I am getting only the 'not defined' error.
#David: The script in this case resides in an external file that is referenced using the normal <script src="file.js"></script> method in the page's head section.
#Douglas: Interesting idea, but if this were the case, how could we ever call a user-defined function with confidence? In any event, I tried this and it didn't work.
#sk: This technique has been tested across browsers and is basically copied from the Prototype library.
I had this function not being recognized as defined in latest Firefox for Linux, though Chromium was dealing fine with it.
What happened in my case was that I had a former SCRIPT block, before the block that defined the function with problem, stated in the following way:
<SCRIPT src="mycode.js"/>
(That is, without the closing tag.)
I had to redeclare this block in the following way.
<SCRIPT src="mycode.js"></SCRIPT>
And then what followed worked fine... weird huh?
It shouldn't be possible for this to happen if you're just including the scripts on the page.
The "copyArray" function should always be available when the JavaScript code starts executing no matter if it is declared before or after it -- unless you're loading the JavaScript files in dynamically with a dependency library. There are all sorts of problems with timing if that's the case.
My guess is, somehow the document is not fully loaded by the time the method is called. Have your code executing after the document is ready event.
Verify your code with JSLint. It will usually find a ton of small errors, so the warning "JSLint may hurt your feelings" is pretty spot on. =)
A syntax error in the function -- or in the code above it -- may cause it to be undefined.
This doesn't solve your original problem, but you could always replace the call to copyArray() with:
__args = Array.prototype.slice.call(arguments);
More information available from Google.
I've tested the above in the following browsers: IE6, 7 & 8B2, Firefox 2.0.0.17 & 3.0.3, Opera 9.52, Safari for Windows 3.1.2 and Google Chrome (whatever the latest version was at the time of this post) and it works across all browsers.
If you're changing the prototype of the built-in 'function' object it's possible you're running into a browser bug or race condition by modifying a fundamental built-in object.
Test it in multiple browsers to find out.
This has probably been corrected, but... apparently firefox has a caching problem which is the cause of javascript functions not being recognized.. I really don't know the specifics, but if you clear your cache that will fix the problem (until your cache is full again... not a good solution).. I've been looking around to see if firefox has a real solution to this, but so far nothing... oh not all versions, I think it may be only in some 3.6.x versions, not sure...
Solved by removing a "async" load:
<script type="text/javascript" src="{% static 'js/my_js_file.js' %}" async></script>
changed for:
<script type="text/javascript" src="{% static 'js/my_js_file.js' %}"></script>
Use an anonymous function to protect your local symbol table. Something like:
(function() {
function copyArray(pa) {
// Details
}
Function.prototype.bind = function ( po ) {
__args = copyArray( arguments );
}
})();
This will create a closure that includes your function in the local symbol table, and you won't have to depend on it being available in the global namespace when you call the function.
This can happen when using framesets. In one frame, my variables and methods were defined. In another, they were not. It was especially confusing when using the debugger and seeing my variable defined, then undefined at a breakpoint inside a frame.
I'm afraid, when you add a new method to a Function class (by prtotyping), you are actually adding it to all declared functions, AS WELL AS to your copyArray(). In result your copyArray() function gets recursivelly self-referenced. I.e. there should exist copyArray().bind() method, which is calling itself.
In this case some browsers might prevent you from creating such reference loops and fire "function not defined" error.
Inline code would be better solution in such case.
I think your javascript code should be placed between tag,there is need of document load

Categories

Resources