My Javascript knowledge is less experienced, so I might use wrong descriptions in the following.
I have an object in a static .js file:
var Info = {
methodA: function() {
// Call methodB.
this.methodB('test');
},
methodB: function(value) {
// Do stuff
}
}
Now, in an .aspx file, I create a function methodC(value) with varying contents (depending on some data), which I want to insert instead of the above definition of methodB(value):
...
var methodC = function(value) {
// Do different stuff
}
...
My idea has so far been to replace methodB with methodC in the following fashion:
...
Info.methodB = methodC;
...
Using IE's buildin developer tool, I get the following error when calling this.methodB('test'); from Info.methodA():
Object doesn’t support this property
or method
Removing the 'this' from this.methodB('test') results in the error:
Object expected
I don't get any errors using FireBug - probably because I use various frameworks, which might catch the error.
How should I do this or should I use a completely different approach?
Regards, Casper
It should work, you are doing it the right way. The problem lays elsewhere.
update:
This should still work as long as you call methodA on an object, eg Info.methodA().
Maybe you are not understanding the error messages ?
"Object doesn’t support this property or method" means that in the expression "this.methodB()", this doesn't have a property named "methodB". So it means that this is not Info when the code of methodA is executed.
"Object expected" means that the variable methodB is unknown in the current execution context. Of course it is, since methodB is never a variable, only a property of Info.
To debug your problem, you need to know what is this when a code is executed, and why it's not what you think it should be. When you call Info.methodA(), this is set to be Info when methodA begins its execution.
Related
When trying to create a new script record within NetSuite, I get the error "Fail to evaluate script: All SuiteScript API Modules are unavailable while executing your define callback". I can't find any real information on what may cause this, and I can't see anything in my custom module that looks suspicious. I can't post the code here as the module is nearly 2,000 lines in length and has some proprietary code in it. As it was with another custom module I built that had issues at the "Upload Script File" stage, if I remove reference to the module in the script the process continues, and then I can go back to the script and return the module reference, wherein everything seems to work correctly afterward.
The only information I found that seemed useful was that the error could be caused by referencing a module outside of the define callback, but that isn't the case. The module has two large objects constructed within, and they're returned from the callback. The only other thing I can think of is that this module calls the other custom module, but I haven't seen anything that says I can't do that.
So, overall, what should I look for to resolve this error? I really cn't seem to find anything useful or that applies to this situation.
EDIT
Ok, so I believe that I discovered the cause is due to the calling of a search function outside of an object/function being returned for the callback. Here's a simplified version of what's happening, since a lot of fields and values are managed:
/**
* custom.module.js
* #NApiVersion 2.x
* #NModuleScope Public
*/
define(['N/search'],
/**
* #param {search} search
*/
function(search) {
var fields = new Array("a","b","c","d","e");
var lValues = search.lookupFields({
type : "customrecord_ng_cs_settings"
, id : "1"
, columns : fields
});
var _values = {
a : lValues.a
, b : lValues.b
, c : lValues.c
, d : lValues.d
, e : lValues.e
};
var _funcs = {
func_a : function() {
// do stuff
}
, func_b : function() {
// do stuff
}
, func_c : function() {
// do stuff
}
};
return {
value : _values
, func : _funcs
};
});
I need to maintain this kind of structure as not everything that gets returned in _values is actually a search/lookup result. Am I going to be forced to encapsulate the construction of this object within a function? And would that cause the lookup to occur every time a value is needed? This is a conversion from a 1.0 script, and this gets loaded and set only once at the beginning so the data is all there the entire time without having to be repeatedly fetched.
So, I see the following options:
Convert the callback output to a function and doing something like
the following at the start of every script:
var _values = customModule.values();
Find some way to rework the code so that any script using the module
can still access values in the following way:
var _a = customModule.values.a;
I'd very much prefer option #2. Is it possible?
You cannot run any SuiteScript module code outside of an entry point. You will need to encapsulate your data retrieval in a function, then invoke that function at the beginning of your entry point.
If you want to avoid multiple fetches, you can leverage memoization in your function, or perhaps N/cache or N/session to store the data.
I keep getting following error: TypeError: this._url is undefined at the callback of a Dojo FilteringSelect.
I simplified my code to this:
var testFeatures = [
{ "id": 1, "Adresa": "Pyšvejcova 6, Kotěhůlky"},
...
];
var filteringSelect = new FilteringSelect({
id: "testSelect",
autoComplete: false,
searchAttr: "Adresa",
store: new Memory({ data: testFeatures }),
onChange: this.onSelected
}, "testSelect");
filteringSelect.startup();
//end of the function, still in the same define callback
onSelected: function () {
//custom processing
var queryTask = new esri.tasks.QueryTask(this.serviceUrl);
var query = new esri.tasks.Query();
query.outFields = ["OBJECTID"];
query.where = "Adresa=" + dojo.byId("testSelect").value;
query.returnGeometry = true;
queryTask.execute(query, this.zoomToSelected);
}
zoomToSelected: function (featureSet) {
//custom map processing
}
and HTML:
<input id="testSelect" data-dojo-attach-point="testSelect" />
I have no idea where's the problem, Google found no case similar to mine. FireBug says the error occurs in init.js. Console says line 199, but the code in question (...nction(){},onExecuteForCountComplete:function(){},onExecuteForExtentComplete:fun...) is on line 256.
One possible cause of problems might be ArcGIS JavaScript API or Web AppBuilder - this seems not to be one of the "ArcGIS-heavy" parts of the code, but I don't know for sure. It's ArcGIS JS API 3.15 (Dojo 1.10) and Web AppBuilder for developers version 1.4.
EDIT: with help of #KenFranqueiro and this post I made some progress. I can't say that I fully understand the onChange callbacks, but I learnt to omit the parentheses while calling a named function. The onSelected still wasn't called, but modifying the input data to include id solved this. But it didn't solve the main problem...
Now the old good TypeError: this._url is undefined occurs at queryTask.execute, or between it and start of zoomToSelected method. The exact place where the error occurs changed to line 256, column 351, with following referenced code:
...e:function(a,b,c,d,f){var m=f.assembly;a=this._encode(n.mixin({},this._url.query...
There is a pointer at the = after "a", so the error seems to be to the right of it, trying to mixin something non-existent to something else. I have no idea what the this in the init.js should mean. Unfortunately, dojo core code is almost undebuggable without some de-obfuscation. Is this my only option, or does anybody know how to solve it?
So debugging the init.js wasn't so hard, it takes QueryTask as this. As far as I know, this shouldn't have a _url attribute. So I must have some mistake in the queryTask as well.
Obsolete part of the question, archived:
I wonder whether the problem might be caused by the onChange callback's argument, which I don't really understand. I've read several examples of Dojo FilteringSelect with onChange event set, like the official one. Usually it has some argument, but I don't know what does it mean and where it gets from. In the official example it corresponds to the div id and nothing else. However, how is the id translated to a variable and even whether my assumption that it's the id is correct. The detailed documentation is not much helpful in this case.
Older EDIT: testSelect is an object. Seems it was created implicitly with the dom - it's a childnode of this.domNode. So now I understand where it comes from, but not how to prepare another function to be called on change and why the correct syntax is what it is.
Also, I don't know where exactly is the problematic undefined this._url supposed to exist. In my example, this refers to the dijit, but I have no idea what is the scope of the part of init.js where the problem occurs.
I'm not sure how much related are the two subquestions (confusion in the onChange callback and identification of this in init.js), I only suppose they are symptoms of the same issue since the error is thrown at the onChange event in my code.
The problem at the query was caused by this.serviceUrl either missing as a part of wrong coontext, or being an object instead of a URL string. So the final step was to make sure the correct context is used (by lang/hitch) and then setting this.serviceUrl to be what I originally thought, one of the attributes of the object referenced as serviceUrl before.
I'm writing a bootstrap firefox extension. Using firefox developer edition v36.2a
I have two problems that seem related, which I don't understand. The first one, mere annoyance:
my bootstrap Console.utils.imports a js file which loads my application (creates a namespace object and imports all other js files as properties on the namespace. All other files include this same namespace file and thus have access to each other. They even store state and everything works much similar to how node caches modules, eg it seems there is only one object of every class which is shared throughout the whole application. Now, this happens:
my namespace file does:
namespace.console = Components.utils.import( 'you know the one/console.jsm' )
namespace.Services = Components.utils.import( 'you know the one/Services.jsm')
namespace.Cu = Components.utils
Now in another file that imports this file, I get the namespace object, but namespace.Cu will be undefined. console.log( namespace ) is fine however and shows me Cu, that I can expand and see all its properties and so on... All other things (console, Services, my own classes) are fine, but trying Cc, Ci etc from Components -> undefined.
In another place in my app I have a function (in file A) which returns an array of nsiDomWindows. A function in file B calls it and when it arrives, similar story: in console all looks fine, Array with ChromeWidows that I can look at. But it's no longer an array actually and is of type object and array[ 0 ] is undefined. If I put both classes in the same file they're fine.
For further confusion, I think I have already used this method in another file and all was fine:
// A.js
//
function A()
{
b = new B()
c = new C()
let windows = b.windowList () // works fine, yields an actual valid array
// with valid windows inside
c.doSomething() // broken, see below
c.doSomething( windows ) // passing it as a parameter
// doesn't help, still broken
}
// B.js
//
function B()
{
this.windowList = function windowList()
{
let result = []
// get open windows from nsiWindowMediator
// foreach...
//
result.push( nsiDomWindow )
console.log( typeof result ) // Array -> it's completely valid here
return result
}
}
// C.js
//
function C()
{
this.b = new B()
this.doSomething = function doSomething( windows )
{
if( ! windows )
windows = this.b.windowList()
console.log( windows ) // in the console shows:
// Array[ ChromeWindow -> about:home ]
// I can inspect all it's properties, looks ok
console.log( typeof windows ) // object
console.log( windows.constructor.name ) // undefined
console.log( windows[ 0 ] ) // undefined
// looping over the object properties shows that it does
// have 1 property called '0' which points at undefined
// note: there was only one open window in the array.
}
}
// Note: the order in which I use Components.utils.import on these is B, C, A
I also wondered if this had to do with security measures in gecko, but no wrapper objects are to be seen anywhere, and afaik they should only shield content code from chrome code (this is all chrome code).
It's the kind of bugs that frustrates me, because I can't think of one sensible reason why the return value of a function shouldn't be the same thing on two sides of the call.
Lucky enough there is a workaround, I will have my make file concatenate all my js files and be done with Components.utils once and for all. Seems the less of the mozilla API I have to use, the happier and more productive I'll be.
I'm seeing errors from mozilla code as well. I just had an error saying "shouldLog is not a function" in Console.jsm. This function is clearly defined higher up in that file. The line that throws the error is an anonymous function that is being returned. That should inherit the scope without a doubt, but it doesn't. It might be that something is mangling return values and that this is related.
I filed a bug on bugzilla with a sample addon attached which demonstrates the first of the problems mentioned above.
update:
I'm sorry, I confused two things. I just figured out what happened in the first case of Cu not being available. I just loaded the file in which the problem happens before adding Cu to my namespace and since I did const { console, Services, Cu } = namespace on the global scope, this actually got evaluated before the property was made. The confusing part about it is that the console keeps references, not copies of the objects it shows you (an unfortunate design choice if you ask me) logging the namespace before the code in question gives you a view on it's state later on, which I missed to take into consideration.
That still doesn't explain how one function can return a perfectly sound value to a receiving function who receives something else, or how a function declared in Console.jsm doesn't seem to exist anymore in a function who inherits it's scope.
All in all, the first problem hasn't got anything to do with the others. I can't however create a reproducible small addon to illustrate the other 2. If I think of a way I'll upload it.
Btw: The pitfall by console can be easily seen (put the following in a javascript scratchpad):
let a = { some: "value" }
console.log( a )
delete a.some
// output: Object { }
For debugging purposes (usually it's main purpose) console has it's limits, and it usually better to set a breakpoint in a debugger or use JSON.stringify
I think I've narrowed all the fore mentioned problems to unloading uncorrectly. I had eventlisteners that I didn't remove and when they fired, objects or scopes can be invalidated.
Using the Extension Auto-Installer somewhat made these problems more severe because when reloading the addon when it hasn't properly unloaded creates an unreliable state of the addon code.
The shouldLog is not a function was because I thought that I had to unload all modules that I loaded with Components.utils.unload, so I unloaded Console.jsm.
After fixing that plus wrapping all the entry points into my software in try-catch blocks, things now run smoother. I now rarely have to uninstall the addon and restart firefox after updating the code.
There's nothing like a few fun days of debugging...
I didnt read it all but:
I think the first issue is you are importing it wrong.
If you want to bring it to a certain namespace to the exported var from Cu.import you should do it like this:
Cu.import('resource://gre/modules/ctypes.jsm', namespace);
No need for the var blah = Cu.import
Console.jsm and Services.jsm export a var named te same thing.
You can even just do Cu.import('rsource://gre/modules/ctypes.jsm') and start using it like ctypes.blah
Also to get access to Cu do this:
var {Cu: utils, Cr: results} = Components
Next i think if you change the module in one scope, it will not change in other scopes until you do Cu.import again in that scope.
I'm trying to test a page using CasperJS, in particular I want to poke the data model a bunch. Let's say I've got a basic function called taxes, and I want to ensure that it uses the right tax rate. So I'd like something like:
this.test.assert(taxes(100, 'Ontario') === 15, "Check ontario tax rate");
Rather than filling out a form and seeing what it prints. That taxes method exists in the global scope, so I'm able to execute it quite easily from anywhere (including from the console in firebug or Chrome). But it's not in the right scope for that to work inside CasperJS (I think? I'm getting ReferenceError: Can't find variable: taxes.
It seems like I'm missing something simple.
TL;DR: How do I execute an on-page bit of JS directly inside a CasperJS test?
Have you tried using evaluate()?
relevant quote: "execute code as if you were using the browser console."
something along the lines of:
casper.evaluate(function(amount, province) {
return taxes(amount, province);
}, {100, 'Ontario'});
Use assertEvalEquals() method.
If you're calling the method via a jQuery-style reference, make sure to explicitly include the library, lest you'll get the ReferenceError:
var casper = require('casper').create({
clientScripts: ['js/jquery-1.7.2.js']
});
...
casper.start('foo.php',
function() {
console.log(this.evaluate(function() {
return $('taxes').text();
}));
});
casper.run();
See: https://groups.google.com/forum/#!msg/casperjs/2uyUOqdzShw/bHWrJYXni40J
If you're calling it implicitly in the global scope (i.e., straight javascript, rather than, for example, $('taxes')), you might have to explicitly prepend the window or document namespace to the reference:
document.querySelector('#taxes').value = taxes_text;
I need some scripts inside an existing site's scripts.js.
This site has been online for ages, and I can not touch the scripts file.
I am including it standardly in another page. There are numerous jQuery calls in the scripts file. The place I include it does not have jQuery.
I want to void all $() type things. I tried this...
$ = function() { };
before I included scripts.js and it didn't seem to work. I am still getting errors like
$(document) is undefined
Is there a way to void all these jQuery calls?
Thanks
Even if you do get that working, you'll still have problems because the code was written with the assumption that jQuery was present. Yes, you can avoid $ is null or not defined errors on lines like this:
$('div.foo');
But there's no point in just writing that line: there will always be actions on the returned object:
$('div.foo').html('blah');
After the NOP jQuery function, you'll get a "html" is not a function error, and so on. The only way you could do it would be to fill out a skeleton of every possible jQuery method, making sure each one returns itself when appropriate.
...or just rewrite it properly...
try
window.$ = function(selector, context) {alert('eating the calls to $');}
in your file that you're including before the scripts.js file. This is how it's defined in jquery so should take care of the selector syntax.
You may need to define other overrides to cater for the $.method() type calls tho
Well, it's no surprise that $(document) is undefined, since you're not returning a value from your placeholder function. Thus, things like $(document).ready(function(){}); will naturally be errors.
Basically, if I understand right, you need $ to be a function that does nothing and returns another object where calling any member function does nothing. Further, calling member functions of $ itself (e.g. $.ajax()) should have the same behavior.
You can do this with __noSuchMethod__, which is unfortunately non-standard:
window.$ = function()
{
var doNothingObj = new (function()
{
this.__noSuchMethod__ = function()
{
return doNothingObj;
}
})();
return doNothingObj;
};
window.$.__noSuchMethod__ = window.$;
This will allow arbitrary chains:
$(document).ready(function(){});
$("#foo").animate().animate();
$.ajax({ url: "file.html"});
etc.
Of course, a much saner solution is to refactor the code that uses jQuery.