registerClass not working in javascript - javascript

I am trying to extend a class using registerClass.
derived.registerClass("derived",base);
but when i try to access the function defined in the base class using a derived object it throws the following error : 'Object doesn't support property or function FunctionName'.
When i try debugging using visual studio debugger (by placing the breakpoint on the function call and looking the current values of the object), the function is visible.
The code for base class looks something like following:
Type.registerNamespace("MyProject");
base.jam = function(refObj,primaryStringField,nestedType){
....
}
base.jam.prototype = {
testfunc: function() {
...
}
}
base.jam.registerClass("base.jam");
And the code for derived class is
Type.registerNamespace("base.pages.item");
..
base.pages.item.behavior = function() {
...
...
testFunc(); // <- this function is visible while debugging (as explained above), but throws an error while ruunning
}
base.pages.item.behavior.registerClass("base.pages.item.behavior",base.jam)

Related

automating / overriding / extending prefix in console.log for debugging

Anyone have a good solution to extending console.log so that it auto prints class name and method as a prefix? I'm using web components and use strict is turned on.
someFunction() {
let varA = "hello"
console.log(this.constructor.name, "someFunction", {varA})
}
Would like to automate this part: this.constructor.name, "someFunction", ...
arguments.callee.name will print the function name, but no longer works with strict mode turned on.
Extending console.log in a centralized location via:
export var log = function(){
var args = Array.prototype.slice.call(arguments);
args.unshift(this.constructor.name + ": ");
console.log.apply(console, args);
}
does not work as this.constructor.name does not print the correct context and if it's not in a web component, it doesn't work at all.
Extending console.log in each web component defeats the purpose (or half of it).
Could fold a function that extends console.log in the build for each web component but would still have the problem of not being able to call arguments.calleee.
Using lit-element, but this is a native javascript issue.
console.trace() may be of use here, instead of a custom console method.
Or, use the new Error()'s .stack property.
class A {
b() {
return function c() {
return function d() {
return (function e() {
return new Error().stack;
})();
}
}
}
}
console.log("here's the stack:\n", new A().b()()());
so based on sean-7777's answer, I suppose we could slice the stack output like this:
let funcname = new Error().stack.split('\n')[1];
funcname=funcname.slice(funcname.indexOf("at ")+3, funcname.indexOf(" ("));
console.log(debugline, 'debug text');
If you put it into a helper function, you could just grab line index 2 (since index 1 would give you the name of the helper function).
I was hoping for something a little more straightforward but hacking the output does work.
UPDATE:
export function prtfun() {
let debugline = new Error().stack.split('\n')[2];
return debugline.slice(debugline.indexOf("at ")+3, debugline.indexOf(" ("));
}
call it from anywhere like this:
console.log(prtfun(), 'log text...');
and it will print ClassName.FunctionName log text...
Works great. I'd disable this in production though.

Odoo Override Javascript Class Method

First off, my apologies - I'm a complete novice when it comes to javascript so this is a bit above my head. I'm also fairly new to Odoo and have mostly stuck with python and XML customization thus far.
I'm trying to override a javascript method within a class to replace it completely with my own version. From the Odoo documentation (https://www.odoo.com/documentation/14.0/reference/javascript_reference.html#patching-an-existing-class) this should be a simple matter of using the .include() method to patch the original class with my new method. But when I do this I get an error Error while loading mymodule.CustomControlPanelModelExtension: TypeError: ControlPanelModelExtension.include is not a function
The original Odoo code that I'm trying to override:
odoo.define("web/static/src/js/control_panel/control_panel_model_extension.js", function (require) {
"use strict";
// a bunch of code here ...
class ControlPanelModelExtension extends ActionModel.Extension {
// more code here ...
// this is the method I'm trying to override
_getAutoCompletionFilterDomain(filter, filterQueryElements) {
// original method body here
}
// more code
}
// more code
});
Below is what I came up with based on the documentation but this gives me the error Error while loading mymodule.CustomControlPanelModelExtension: TypeError: ControlPanelModelExtension.include is not a function (this error is reported in browser dev tools console).
odoo.define('mymodule.CustomControlPanelModelExtension', function(require) {
"use strict";
var ControlPanelModelExtension = require('web/static/src/js/control_panel/control_panel_model_extension.js');
ControlPanelModelExtension.include({
// override _getAutoCompletionFilterDomain
_getAutoCompletionFilterDomain: function(filter, filterQueryElements) {
// my custom implementation here
},
});
});
Any ideas what I'm doing wrong here? I've tried various other things with extends and such but I don't think I want to extend - that won't replace the function in existing instances.
The problem here is that the include function is available only for the classes that inherit from OdooClass and in this case the class you are trying to inherit is a native JavaScript class.
Then, to add a property or method to a class, the prototype property of the object class must be modified.
odoo.define('mymodule.CustomControlPanelModelExtension', function(require) {
"use strict";
const ControlPanelModelExtension = require('web/static/src/js/control_panel/control_panel_model_extension.js');
function _getAutoCompletionFilterDomain(filter, filterQueryElements) {
// your custom implementation here
}
ControlPanelModelExtension.prototype._getAutoCompletionFilterDomain = _getAutoCompletionFilterDomain;
return ControlPanelModelExtension;
});

Is it possible to get the class or class name from inside a function?

I'm trying to write debugging tools and I would like to be able to get the class name of the caller. Basically, caller ID.
So if I have a method like so, I want to get the class name:
public function myExternalToTheClassFunction():void {
var objectFunction:String = argument.caller; // is functionInsideOfMyClass
var objectFunctionClass:Object = argument.caller.this;
trace(object); // [Class MyClass]
}
public class MyClass {
public function functionInsideOfMyClass {
myExternalToTheClassFunction();
}
}
Is there anything like this in JavaScript or ActionScript3? FYI AS3 is based on and in most cases interchangeable with JS.
For debugging purposes you can create an error then inspect the stack trace:
var e:Error = new Error();
trace(e.getStackTrace());
Gives you:
Error
at com.xyz::OrderEntry/retrieveData()[/src/com/xyz/OrderEntry.as:995]
at com.xyz::OrderEntry/init()[/src/com/xyz/OrderEntry.as:200]
at com.xyz::OrderEntry()[/src/com/xyz/OrderEntry.as:148]
You can parse out the "caller" method from there.
Note that in some non-debug cases getStackTrace() may return null.
Taken from the documentation:
Unlike previous versions of ActionScript, ActionScript 3.0 has no
arguments.caller property. To get a reference to the function that
called the current function, you must pass a reference to that
function as an argument. An example of this technique can be found in
the example for arguments.callee.
ActionScript 3.0 includes a new ...(rest) keyword that is recommended
instead of the arguments class.
Try to pass the Class name as argument:
Class Code:
package{
import flash.utils.getQualifiedClassName;
public class MyClass {
public function functionInsideOfMyClass {
myExternalToTheClassFunction( getQualifiedClassName(this) );
}
}
}
External Code:
public function myExternalToTheClassFunction(classname:String):void {
trace(classname); // MyClass
}

How can I use a javascript function globally in Drupal 7

How can I use a javascript function globally in Drupal 7.
I have my javascript file set up like this and add it using drupal_add_js():
(function($) {
function add_if_country_is_not_usa() {
// Check what country it is
// Update text, image, etc.. of a block.
}
});
In my block WYSIWIG I added the following code (The reason I add it in the WYSIWIG is because I want it to update before the page is fully rendered):
<script type="text/javascript">
add_if_country_is_not_usa();
</script>
But I get the following error:
Uncaught ReferenceError: add_if_country_is_not_usa is not defined
(anonymous function)
I read about adding functions to Drupal behaviors but that happens on document ready. I want to run the function as soon as the block is shown.
Any ideas?
Either define in the global scope, or do like below:
(function($) {
function add_if_country_is_not_usa() {
// Check what country it is
// Update text, image, etc.. of a block.
}
// set as a property of the global object `window`
window.add_if_country_is_not_usa = add_if_country_is_not_usa;
});
Not sure if this is the best way but I ended up being able to get it work using a namespaces. I call myGlobalObject.add_if_country_is_not_usa() from my block and it works now.
var myGlobalObject = mySingleGlobalObject || { 'country': {} };
(function ($) {
myGlobalObject.country = '';
myGlobalObject.add_if_country_is_not_usa = function() {
// Check what country it is
// myGlobalObject.country = 'US';
}
})(jQuery);

How to return name of the property an unnamed function is assigned to

I got following code:
function test () {
this.testFunction = function () {
//code to alert or return the string "testFunction"
}
}
var testVar = new test();
testVar.testFunction();
Is there a way to find out the name of the property, which the unnamed function is assigned to? Whatever I tried yet in conjunction with "caller" and "callee" methods didn't yield any success.
Edit:
The reason why I'd like to retrieve the property name is to use it for debugging messages, where I don't have to manually pass the property name to the logger. Performance would be not an issue since this is just for the developing process.
Actually the suggestion to name the function is a good idea ... I think. Does this have any obvious/well-known side effects, beside having to type in the function name twice? :-P
Additionally this brought me to the idea to add a comment at the start of a function which looks something like
/* $$NAME$$="testFunction" */
and which could also be parsed - but JavaScript comments seem to be trimmed in FireFox (unlike IE), and I rather prefer FF for developing. Would there be a way to also display/use JS comments in FF when using the "caller"/"callee" property?
You can cycle through everything that's available in the instance of the object, e.g.
function test() {
this.testFunction = function () {
for (var i in this) {
if (this[i] === arguments.callee) {
alert(i); // alerts 'testFunction'
}
}
}
}
var x = new test();
x.testFunction();
If your intent is to call the function recursively, you can simply name it
this.testFunction = function inner() {
inner();
}

Categories