[sharing/testing]: JS object print (a bit like console.log() or PHP print_r())
I just wrote a small JS module mainly for debugging purposes: It iterates over any JS object and prints the content/properties formatted into the the Max console. I also included Max specific JS objects such as LiveAPI, Task or Folder so one can take a fast look at all properties.
The syntax is straight forward:
var objectPrinter = require("jm.objectPrinter");
objectPrinter.printObj(, );
is optional, default is "----";
Here is a demo patch
and attached the js files.
If you find any bug, or have suggestions let me know :)
Edit: There is a limitation with patcher, and the jsthis: They only are iterated down the line when they are on the top level. Ie:
objectPrinter.printObj(this.patcher);
Iteration is stopped when they appear further "down the road" like:
objectPrinter.printObj({"someProperty" : this.patcher});
This is simply to avoid endless iteration loops, as there can be references of those objects inside themselves.
Cheers,
Jan
this is really cool! thank you for sharing
Hello Self Help, i am happy that it is useful for you. Such an old tool… probably some of the newer Max JS are not implemented.
Hi, I just discovered this post and I can't believe how much efficiency this thing brings!
I don't know if anybody needs it, but I'll just paste the typescript version of the objectPrinter.
// Define types for better type checking and autocompletion
type MaxJsObjectClass =
| "Dict"
| "Max"
| "Patcher"
| "Maxobj"
| "Wind"
| "Global"
| "Task"
| "Folder"
| "File"
| "Image"
| "Sketch"
| "LiveAPI";
type NonIterableClass = "String" | "Patcher" | "Max" | "js";
const _maxJsObjectClasses: MaxJsObjectClass[] = [
"Dict",
"Max",
"Patcher",
"Maxobj",
"Wind",
"Global",
"Task",
"Folder",
"File",
"Image",
"Sketch",
"LiveAPI",
];
const _nonIterableClasses: NonIterableClass[] = [
"String",
"Patcher",
"Max",
"js",
];
let _indentString: string = "----";
// Function to print any JS Object content formatted to Max Console
export function printObj(toPrint: any, indentString?: string): void {
if (indentString !== undefined) {
_indentString = indentString;
}
post("********** [printObj Start] ********** \n");
_iterateObject(toPrint);
post("********** [printObj End] ********** \n");
}
// Function to detect if a mixed var is an Integer
function _isInt(mixedVar: any): boolean {
return mixedVar === +mixedVar && isFinite(mixedVar) && !(mixedVar % 1);
}
// Function to detect if a mixed var is a Float
function _isFloat(mixedVar: any): boolean {
return +mixedVar === mixedVar && (!isFinite(mixedVar) || !!(mixedVar % 1));
}
// Function to get number type of mixed var
export function getNumberType(mixedVar: any): string | false {
if (_isInt(mixedVar) || _isFloat(mixedVar)) {
return _isInt(mixedVar) ? "Integer" : "Float";
}
return false;
}
// Function to iterate over JS objects and print content formatted to Max console
function _iterateObject(
obj: any,
tabindex: number = 0,
propertyName?: string,
firstIteration: boolean = true
): void {
_postObjType(obj, tabindex, propertyName);
if (_canIterate(obj) || firstIteration) {
for (const i in obj) {
_iterateObject(obj[i], tabindex + 1, i, false);
}
}
}
// Function to post object content to Max console
function _postObjType(
obj: any,
tabindex: number = 0,
propertyName?: string
): void {
let tabString: string = "";
for (let i = 0; i < tabindex; i++) {
tabString += _indentString;
}
post(tabString);
if (propertyName !== undefined) {
post(`"${propertyName}" : `);
}
// Handle different types of values
switch (typeof obj) {
case "undefined":
post("<undefined> \n");
break;
case "object":
if (obj === null) {
post("<null> \n");
} else if (Array.isArray(obj)) {
post(`Array [length: ${obj.length}]\n`);
} else if (_isMaxJsObject(obj)) {
post(`Max Js Object [${_getMaxJsType(obj)}] \n`);
} else {
post(`Object [${obj.constructor.name}] \n`);
}
break;
case "boolean":
case "number":
case "string":
case "function":
post(`${typeof obj} [${obj}] \n`);
break;
}
}
// Function to get Max class name for Max specific objects such as Maxobj
function _getMaxJsType(obj: any): string | false {
return _isMaxJsObject(obj) ? obj.constructor.name : false;
}
function _isMaxJsObject(obj: any): boolean {
return (
obj !== undefined &&
obj !== null &&
_maxJsObjectClasses.indexOf(obj.constructor.name) !== -1
);
}
// Function to detect if some objects can cause infinite iteration loops
function _canIterate(obj: any): boolean {
if (obj != null && typeof obj !== "string" && _isMaxJsObject(obj)) {
return _nonIterableClasses.indexOf(obj.constructor.name) === -1;
}
return false;
}
I took some hints from the following repository on how to use TypeScript with Max's js.
Wow YUICHI YOGO,
after so many years! Great that it helps you. I should probably clean ip up a bit transform it into a Max Package and put it up on GitHub eventually, for better accessibility. Feel free to put it up yourself if you like.
It most likely also could receive some maintenance to detect JS objects that were implemented into the Max-Js API since.