How do I solve the JavaScript error: method XX is undefined? - javascript

I am working on asp.net and jquery website , and when run browse the site an java script error has occurred .
Visual studio debuger references that GetMainFrameUrl is undefined :
function EBNavigateComplete()
{
if (!GetMainFrameUrl())
{
navCounter++;
if (navCounter%100==0)
{
o.loadEmptyTerm();
counter = 0;
}
}
else
{
if (o.pbNavigateComplete(GetMainFrameUrl()))
{
counter = 0;
}
}
}
is there help please???

Are you using the Conduit API? If so, do you have that script library referenced?
http://www.conduit.com/Developers/HtmlAndGadget/Methods/GetMainFrameUrl.aspx
http://www.conduit.com/Developers/HtmlAndGadget/Events/EBNavigateComplete.aspx

Visual Studio debugger isn't always capable of loading all dynamically loaded scripts (but normally it does though). Is the same error occurring if you run it in, say, Firefox or Opera?
The error means that the function GetMainFrameUrl is not defined. That can happen if you misspelled the name of an existing function, or when the function is loaded only later in the chain. In the latter case, change the order of your <script> blocks to have the one with GetMainFrameUrl in it load first.
One easy way to find out whether that function is available somewhere is hitting Ctrl-Shift-F in Visual Studio, select "Entire Solution" and nothing for the file filter and search for the name of the missing function.

If you whant to check if the GetMainFrameUrl-function exists you cant use "if (!GetMainFrameUrl())". In this case javascript execute the function and comprare the return value.
You can use "if (!GetMainFrameUrl)" but this only checks if any function, object or variable exists with this name.
You should use "typeof". See exampel:
function EBNavigateComplete()
{
if ( typeof GetMainFrameUrl !== 'function' )
{
navCounter++;
if (navCounter%100==0)
{
o.loadEmptyTerm();
counter = 0;
}
}
else
{
if (o.pbNavigateComplete(GetMainFrameUrl()))
{
counter = 0;
}
}
}

Related

Importing script and calling a method on a variable

I'm new to typescript and I'm trying to use a bit of code I found online to change links to look nice for my site,
<script src="https://wow.zamimg.com/widgets/power.js"></script>
<script>var wowhead_tooltips = {
"colorlinks": true,
"iconizelinks": true,
"renamelinks": true
};
</script>
I included that into my index.html, and it works great, until I load a component, I spent a lot of time looking around and found that I need to call $WowheadPower.refreshLinks();
To get the links to change when a new element is added, I wasn't sure how to declare that variable in typescript so I could tie it to various angular commands I wanted to do, unless I add it in a try catch:
loadScript(){
try{
// update tooltips
if(typeof $WowheadPower == 'undefined'){
$.getScript('//wow.zamimg.com/widgets/power.js');
} else {
$WowheadPower.refreshLinks();
console.log($WowheadPower)
}
} finally {}
}
I get an error that says
Cannot find name '$WowheadPower'
but I saved it anyway, and somehow on my page it works as I want it too.
It works perfect, but I still got the error so I declared it
try{
// update tooltips
var $WowheadPower
if(typeof $WowheadPower == 'undefined'){
$.getScript('//wow.zamimg.com/widgets/power.js');
} else {
$ WowheadPower.refreshLinks();
console.log($WowheadPower)
}
} finally {}
and it broke, I assume because I overwrote the correctly variable that has the right method.
Now I have to leave the error in to get functionality, but the error stops me from compiling when I ng serve. Until I hit save on VScode then it works fine again.
Any thoughts on how to resolve this?
since $WowheadPower is an external variable imported from another file, you can tell typescript that it exists without explicitly declaring it:
declare var $WowheadPower: any
write this at the beginning of your code so you tell TS that this variable exists. Ideally, you would write an interface that correctly defines $WowheadPower's type instead of any there.

Google Scripts/Basic JavaScript - Issue fixed by debugger

I'm working on a Google Scripts add on for Google Sheets, but I'm trying to get the script working before I actually set it up on the sheet. The code below works fine if I set a breakpoint somewhere in the extractNumbers function. If I just execute the code without breakpoints, I get an error:
TypeError: Cannot call method "replace" of undefined. (line 36, file "")
Here's the code:
var myVar = phoneCheck("a1","a2","o1","o2");
Logger.log(myVar);
function phoneCheck(newCell,newHome,oldCell,oldHome) {
Logger.clear();
var newCell = extractNumbers(newCell);
var oldCell = extractNumbers(oldCell);
var newHome = extractNumbers(newHome);
var oldHome = extractNumbers(oldHome);
if (newCell === oldCell) {
return newCell;
exit;
} else if (newCell === oldHome && newHome === oldCell) {
return oldCell;
exit;
}
if (newCell === '' && oldCell !== '' ) {
return oldCell;
exit;
}
if (newCell !== oldCell && newCell !== oldHome) {
return newCell;
exit;
}
return "No value found";
exit;
}
function extractNumbers(input) {
Logger.log(input);
var str = input;
return str.replace( /\D+/g, '');
}
Now I realize my if/then logic is more than a bit inelegant, but for my purposes, quick and dirty is fine. I just need it to run.
ALSO, I have read of other novice JavaScript programmers having similar issues related to the sequence of code execution. If someone would like to link to a concise source aimed at a non-advanced audience, that would be great too. Thanks!
EDIT: I put my code into a new fiddle and it works fine, but it continues to fail in Google Scripts editor unless running in debug mode with a breakpoint. The problem seems to be that the function parameters aren't available to the function unless there is a breakpoint. Anyone have access to Google Scripts that can try my updated code from https://jsfiddle.net/hrzqg64L/ ?
None of the suggestions got to the root of your problem - and neither did your answer, although you've avoided the problem by putting an enclosure around everything.
There's no AJAX, no asynchronous behavior - it's simpler than that. "Shadowing of parameters" is likewise a red herring. Bad coding practice, yes - but not a factor here.
If someone would like to link to a concise source aimed at a non-advanced audience, that would be great too.
Sorry - no such thing. I can explain what's going on, but can't guarantee it will be accessible to novices.
The exception
Let's just clarify what causes the exception, or thrown error, that you've observed.
As written, extractNumbers() will throw an exception if it has a null parameter (or any non-string parameter) passed to it. If you choose to extractNumbers() then hit "run", you'll get:
TypeError: Cannot call method "replace" of undefined. (line 36, file "")
That is telling you that on line 36, which is return str.replace( /\D+/g, '');, the variable str contains an object that is undefined (...and has no replace() method).
For bullet-proof code, you would check your parameter(s) to ensure they are valid, and handle them appropriately. Sometimes that would be with a valid default, and other times you might return an error or throw an exception that is more explicit about the parameter problems.
Running code in Google's debugger
The only way to run code in Google's Debugger is to select a function, then choose "run" or "debug". Assuming you posted all your code, you had just two functions to choose from:
phoneCheck()
extractNumbers()
Whenever Google Apps Script runs any part of a script, the entire script is loaded and scanned to find all symbols & check syntax. The scope of all symbols is noted as well, and so are any dependencies between functions and global symbols (symbols outside of any closure, or block of code).
That takes some time. To speed things up when asked to execute a specific function, the global symbols are only evaluated if they are a dependency for the requested function or the functions it may call. There is another condition that will trigger evaluation of global symbols, and that is if there is a possibility that the debugger may need to stop and display values.
When this happens, any code that is outside a closure (outside a function, for example) will be executed. This is what you observed when you set breakpoints.
Why did it work when breakpoints were set?
As explained, just having a breakpoint set triggers evaluation of global symbols.
You start this script with a few lines of code that are not in any closure:
var myVar = phoneCheck("a1","a2","o1","o2");
Logger.log(myVar);
It is that code which makes the only proper invocation of phoneCheck() with parameters. Because myVar is evaluated, phoneCheck() gets called with parameters, and in turn calls extractNumbers() with a defined parameter.
Unfortunately, because of the way the debugger works, you cannot choose to run that code yourself. You need to rely on these side-effect behaviors.
How to fix this?
Simple. Don't rely on global code to invoke functions under test. Instead, write an explicit test function, and call that.
function test_phoneCheck() {
var myVar = phoneCheck("a1","a2","o1","o2");
Logger.log(myVar);
}
Finally found the issue, but I don't fully understand it.
This question got me thinking about scope and how it might be different in the Google Script environment. I figured a simple workaround would be to enclose the entire script in its own void function, and it worked! Also, I simplified the script quite a bit with an array:
function init () {
var numberArray = ["a3", "a2", "o3", "o10"];
var myVar = phoneCheck(numberArray);
Logger.log(myVar);
function phoneCheck(myArray) {
var phoneString = '';
Logger.clear();
var arrayLength = myArray.length;
for (i = 0; i < arrayLength; i++) {
phoneString += myArray[i].replace(/\D+/g, '');
}
return phoneString;
}
}
Also, I realize the functionality of this script is different than the original, but I was really just trying to solve this problem. Now that I have, I can finish the script properly.
Thanks for all the suggestions, everyone! I learned a lot of good things, even though they turned out not to be the answer.

Why is this Javascript library available in browser but not in PhoneGap?

I have defined a library in Javascript that works great when I am in a browser but whose name isn't found when running under PhoneGap on my device.
The library is defined as so:
(function(bsdi, $) {
bsdi.SomeName = "XYZ";
bsdi.addDays = function (date, days) { ...stuff here...}
....
}(bsdi = window.bsdi || {}, jQuery));
Later, in a .js file that is loaded last, I have:
function knockoutFn() {
var self = this;
if (bsdi.SomeName == "XYZ") { <<--- CRASHES HERE, "bsdi not defined" but only on Device
...stuff here...
}
}
// Happens to use Knockout...
var koFn = new knockoutFn();
ko.applyBindings(koFn);
function init() {
if (isPhoneGap) {
document.addEventListener("deviceready", onDeviceReady, false);
}
else {
koFn.InitPage();
}
}
function onDeviceReady() {
// Now safe to use the Cordova API
koFn.InitPage();
}
What happens is that a normal web browser handles this just fine. However, when I download to my iPhone using the PhoneGap Build app, it gets to "bsdi.SomeName" and crashes because bsdi is not defined. I thought that my method for defining the bsdi library was correct but, obviously, there is something in PhoneGap that doesn't like this. Note that "isPhoneGap" is true and we do use the addEventListener on the device.
Any ideas are greatly appreciated!
UPDATE: On a hunch, I tried moving the bsdi object into the same .js file as the code that uses it. In this case, it finds the object and uses it correctly. When it is an external file, however, it fails. And yes, I have triple-checked that the file exists and is at the correct location. Again, it works fine in a browser!
If window.bsdi isn't defined, then (as posted in your question) your initialization code never ensures that window.bsdi is defined by the time the code is finished. All it does is add those properties to the new empty object passed in, but that won't have any effect on anything once the initialization function is finished.

Issue with retrieving object data on IE 8 on Windows XP or 2003

This is an interesting problem that I am facing with JavaScript and IE8 on Windows XP and Windows 2003. I create an object on the page and then retrive information about that object (for example, its version). When trying to get the version, I am running this code:
var myObject = document.getElementById(objectId);
console.log(myObject.version);
What is interesting is that this code works on every single browser except IE8 on Windows XP and 2003. I've done some debugging and this is where things get interesting.
myObject is not null but myObject.version is undefined. So what I did is I added an alert in between so the code is now as follows:
var myObject = document.getElementById(objectId);
alert(myObject.version);
console.log(myObject.version);
The alert results in "undefined", however, the console.log is now resulting in the actual version. If I add an alert before this alert of anything (let's say alert("something")) then the second alert has the actual version now. I am assuming this is a timing issue (for some reason the object needs sometime to be able to provide the data stored in it?) but I am not sure what kind of timing issue this is or how to approach it.
Sorry for the long description but any help is appreciated.
document.getElementById doesn't return an object. It returns a DOM element. So, you expect to see a .version property in a DOM element, which by the official W3C specification is missing (or at least I don't know about this).
I'm not sure what you are expecting to see in .version, but if it is something custom then you should create a custom object like that:
var o = { version: "..." }
console.log(o);
You said that this may be a time issue. If that's true then I'll suggest to try to access the .version property after the DOM is fully loaded. You can use jQuery for the purpose:
$(document).ready(function() {
var myObject = document.getElementById(objectId);
alert(myObject.version);
console.log(myObject.version);
});
You can add a setTimeout in your function till the .version property is there.
var f = function(callback) {
var check = function() {
var myObject = document.getElementById(objectId);
alert(myObject.version);
console.log(myObject.version);
if(typeof myObject.version !== "undefined") {
callback(myObject.version);
} else {
setTimeout(check, 1000);
}
}
setTimeout(check, 1000);
}
What happens if you put the <script>...</script> tag with the js code at the end of the html file? In my opinion, the code is executed when the DOM is not ready. If you put it in the end, then it will be executed after it's loaded.

Functions registered with ExternalInterface.addCallback not available in Javascript

I'm working on a Flash game that needs to call some Javascript on the page and get data back from it. Calling Javascript from Flash works. Calling the Flash functions from Javascript (often) doesn't.
I'm using the Gaia framework.
What happens:
The swf is loaded in with SWFObject
There's a button in the Flash file. On click, it uses ExternalInterface.call() to call a Javascript function. This works.
The Javascript function calls a Flash function that was exposed with ExternalInterface.addCallback().
Sometimes, the Javascript produces the following error: TypeError: myFlash.testCallback is not a function.
When the error happens, it affects all functions registered with addCallback(). Gaia and some of its included libraries use addCallback(), and calling those functions from Javascript also produces the TypeError.
Waiting a long time before pressing the button in Flash doesn't solve the error.
Having Flash re-try addCallback() periodically doesn't solve the error
When the error occurs, ExternalInterface.available = true and ExternalInterface.objectID contains the correct name for the Flash embed object.
When the error occurs, document.getElementById('myflashcontent') correctly returns the Flash embed object.
Edited to add:
This issue shows up in Firefox 3.6, but not Chrome or IE8. I haven't tried older browsers.
I'm running the Debug version of the Flash player.
My calls to ExternalInterface.addCallback() are wrapped in a try...catch block. When the JS error occurs, the catch block is not triggered. It's a silent failure.
The error occurs when testing on a webhost, with the swf loaded from the same server as the page it's on.
I set allowScriptAccess = always.
Setting flash.system.Security.allowDomain("mydomain") doesn't fix the error.
From my Page class:
public class MyPage extends AbstractPage
{
// declarations of stage instances and class variables
// other functions
override public function transitionIn():void
{
send_button.addEventListener(MouseEvent.MOUSE_UP, callJS);
exposeCallbacks();
super.transitionIn();
}
private function exposeCallbacks():void
{
trace("exposeCallbacks()");
if (ExternalInterface.available) {
trace("ExternalInterface.objectID: " + ExternalInterface.objectID);
try {
ExternalInterface.addCallback("testCallback", simpleTestCallback);
trace("called ExternalInterface.addCallback");
}
catch (error:SecurityError) {
trace("A SecurityError occurred: " + error.message + "\n");
}
catch (error:Error) {
trace("An Error occurred: " + error.message + "\n");
}
}
else {
trace("exposeCallbacks() - ExternalInterface not available");
}
}
private function simpleTestCallback(str:String):void
{
trace("simpleTestCallback(str=\"" + str + "\")");
}
private function callJS(e:Event):void
{
if (ExternalInterface.available) {
ExternalInterface.call("sendTest", "name", "url");
}
else {
trace("callJS() - ExternalInterface not available");
}
}
}
My Javascript:
function sendTest(text, url) {
var myFlash = document.getElementById("myflashcontent");
var callbackStatus = "";
callbackStatus += '\nmyFlash[testCallback]: ' + myFlash['testCallback'];
//console.log(callbackStatus);
var errors = false;
try {
myFlash.testCallback("test string");
}
catch (err) {
alert("Error: " + err.toString());
error = true;
}
if (!error) {
alert("Success");
}
}
var params = {
quality: "high",
scale: "noscale",
wmode: "transparent",
allowscriptaccess: "always",
bgcolor: "#000000"
};
var flashVars = {
siteXML: "xml/site.xml"
};
var attributes = {
id: "myflashcontent",
name: "myflashcontent"
};
// load the flash movie.
swfobject.embedSWF("http://myurl.com/main.swf?v2", "myflashcontent",
"728", "676", "10.0.0", serverRoot + "expressInstall.swf",
flashVars, params, attributes, function(returnObj) {
console.log('Returned ' + returnObj.success);
if (returnObj.success) { returnObj.ref.focus(); }
});
Calls made to JS via ExternalInterface are wrapped within a try { } block and that causes subsequent JS errors to get suppressed.
A workaround for the same is to cause a function closure in JavaScript and execute the actual code after a timeout.
Example:
function myFnCalledByEI (arg1, arg2) {
setTimeout(myActualFunction () {
// You can use arg1 and arg2 here as well!
// Errors raised within this function will not be
// suppressed.
}, 0);
};
Here was our scenario once we narrowed down all the conditions:
Only on FireFox/Windows
Only when wmode=transparent
Only when using the js alert() function
In this specific scenario, ExternalInterface.call() would not fire right away. It only worked after creating a tiny delay with Timer class.
If we made wmode=window, or removed the alert() - everything worked. Try using console.log() to display debug text in firebug.
The other gotcha? Whether your js function returns an array or object vs a string. Surprisingly returning the native js array was interpreted by an array in Flash. Try outputting info about your return data like this:
var myRetVal = flash.external.ExternalInterface.call("my_js_func");
debug_txt.text = flash.utils.describeType(myRetVal).toString();
This might be similar to the issue you are experiencing.
http://www.google.com/support/forum/p/translator-toolkit-api/thread?tid=58cda1b34ae1e944&hl=en
You can see that type of error message if something wrong happened in Flash while making the call. Something like an uncaught exception.
Are you running the debug version of the player? That might give you more information about what's going on.
Also, is this consistent across browsers? I've seen old versions of IE having trouble accepting several consecutive Flash <-> JS calls.
J
I tryied your code, and It worked ok if I place an alert before everything, so, I thinkg it is something related to some kind of time you have to wait.
Have you tried this in JavaScript?
if (myFlash)
{
if (!myFlash.testCallback)
{
if (__flash__addCallback)
{
__flash__addCallback( myFlash, "testCallback" );
}
else
{
console.log("Error: Flash External Interface injected JavaScript function not found. The external interface function won't work.");
}
}
}
myFlash.testCallback("test string");
I had used this in many cases.
Again at certain places I had to redefine __flash_addCallback and _flash_removeCallback functions to minimize the errors.
Presently I do not remember what I did for __flash_addCallback, but this is what I did for the latter:
if (__flash__removeCallback)
{
__flash__removeCallback = function (instance, name) {if(instance && instance[name]) instance[name] = null;
}
We've run into the same problem, and only in Firefox.
Following the advice given by THM we were able to find a solution.
In our case, the swf being inserted was inside a div being animated into view with jQuery.slideDown(). This apparently causes it to sometimes reboot while being started. In some cases this led to the callback functions not being available.
Fixed by calling swfobject.embedSWF only after the slideDown effect had finished.
I was getting this error because I had the same Flash file on the page multiple times. Even though each one of them had a different id/name, they were all using the same callback.

Categories

Resources