Little JS Syntax Bible in Max/MSP

Federico-AmazingMaxStuff's icon

Here I want to collect all the less intuitive Javascript syntax and techniques for Max.
Feel free to comment everything that comes to your mind related to the subject, I'll add it to the list.

Max JS uses ES5 version, so features like "let" and Classes added in ES6 will not work.

Max's documentation for JS:
https://docs.cycling74.com/max8/vignettes/javascriptinmax

Tim's JS Reference:
http://max-javascript-reference.tim-schenk.de/

Get keys pressed in JS:
https://github.com/cskonopka/maxJS

Max Scripting

  • Create a new Max object:
    var myObj = this.patcher.newdefault(<obj_pos_x>, <obj_pos_y>, "<max_obj_name>");

  • Add arguments to Object when creating it:
    var anotherObject = p.newdefault(100, 100, "combine", "text", "::", "moretext")

  • Add Object to Presentation:
    maxObject.presentation(1); // note that it's a function

  • Move Object:maxObject.message("patching_position", [posX, posY]);

  • Create a new "bpatcher" object with attributes:
    var myNewObject = p.newdefault(100, 100, "bpatcher", "@name", "myPatch", "@args", name);

  • Get patcher file path: var filepath = this.patcher.filepath;

  • Rescale Max Object:
    this.patcher.script("sendbox", <max_obj>.varname, "patching_rect", [ <obj_pos_x>, <obj_pos_y>, <obj_size_x>, <obj_size_y> ]);

  • Hide a Max Object:
    <max_obj>.hidden = val;

  • Rescale Max Object in Presentation:
    this.patcher.script("sendbox", <max_obj>.varname, "presentation_rect", [ <obj_pos_x>, <obj_pos_y>, <obj_size_x>, <obj_size_y> ]);

  • Bring to Front/Back Max Object:
    this.patcher.script("bringtofront" / "sendtoback", <max_obj>.varname);

  • Connect two Max objects:
    this.patcher.connect(<max_obj_1>, <outlet_index>, <max_obj_2>, <inlet_index>);

  • Connect two Max objects with hidden cable:
    this.patcher.hiddenconnect(<max_obj_1>, <outlet_index>, <max_obj_2>, <inlet_index>);

  • Connect the JS object itself with a Max object in the same patch:this.patcher.connect(this.box, <outlet_index>, <max_obj>, <inlet_index>)

  • Send a message to a Max "receive" object from within JS:
    messnamed("<receive_obj_name>");

  • Get a named Max object and assign it to a JS object:
    var myMaxObj = this.patcher.getnamed("<obj_varname>");

  • Get the value of an attribute of a Max object:obj.getboxattr("<attr_name>");

  • Resize a BPatcher that contains the JS object:
    this.patcher.box.rect = [<leftTopX>, <leftTopY>, <bottomRightX>, <bottomRightY>]

  • Change size of Max patcher:this.patcher.window( "size", x, y, x + w, y + h );
    this.patcher.window( "exec" );

  • Get the size of the current patcher: var size = this.patcher.wind.size;

  • Get the rect of the current patcher:var rect = this.patcher.wind.location;

JSUI

  • Get the rect of the JSUI object box:
    var objRect = box.rect.slice();
    Get size of box.rect =
    var objSize = [box.rect[2] - box.rect[0], box.rect[3] - box.rect[1]];
    box.rect can also be set.

Folder Object

  • Create a Folder object and read the file names in the folder:
    var myFolder = new Folder(<folder_path>);
    Set Folder typelist (an empty typelist will make the Folder object read every file type):
    myFolder.typelist = ["<file_type>", "<file_type>", etc...];
    Read the Folder file names:
    while (!myFolder.end)
    {
    post(myFolder.filename);
    myFolder.next();
    }

Dict Object

  • Basic querying:

    function dictionary(dictname)
    {
    var d = new Dict(dictname);
    outlet(0, d.get('layer1key::layer2key');
    }

  • Iterating through layers of a Dict:

    function dictionary(dictname)
    {
    var d = new Dict(dictname);
    var layer1 = d.getkeys();
    layer1.forEach(function(key)
    {
    var layer2 = d.get(key).getkeys();
    }
    }

Max Object Listener

  • Listen to a Max Object for attributes or value changes:
    var myListener = new MaxobjListener(<max_obj>, <callback_function>);
    The Callback function can be used like this:
    function MyCallback(data)
    {
    data.value; // the output of the Max object
    data.maxobject; // the object itself
    }

  • To make the "this" inside a callback refer to the current object, you can write the callback directly inside the object in this way:

var MyCallback = (function(data)
{
post(this.myObjProperty);
} ).bind(this);

  • MaxobjListener tutorial:

Jitter in Javascript

  • Create Jitter Matrix:
    var myMatrix = new JitterMatrix("<name_optional>", <int_number_of_planes>, "<type>", [<int_dim_0>, <int_dim_1>, ... ] );

  • Get name of object as registered from Max:
    var objRegName = <jsJitterObj>.getregisteredname();

  • Create Jitter Object:
    var myJitterObj = new JitterObject("<obj_name>", <argument>);
    Example:
    var myJitterObj = new JitterObject("jit.gl.gridshape", "<drawto>");

  • Free Jitter Object Memory (must be done every time a Jitter object is deleted in JS):
    myJitterObj.freepeer();

  • Use a "jit.gl.pix" object within JS (same for "jit.gl.slab"):
    var myGLPix = new JitterObject("jit.gl.pix");
    myGLPix.gen = "<genjit_file_path>";

Set the input you want to send the next texture:

myGLPix.activeinput = <int_input_index>

Set parameters:
myGLPix.param("<param_name>", <param_value> / [<array_of_param_values>]);
Get the processed texture:
myGLPix.jit_gl_texture("<texture_to_process_name>");
myGLPix.draw(); // IMPORTANT, the jit.gl.pix obj needs also to draw
var myProcessedTexture = myGLPix.out_name;

  • Play a movie with "jit.movie" and get a texture output from within JS:
    First create a dummy matrix, the dimensions don't matter:

    var dummyMat = new JitterMatrix(4, "char", 320, 240);
    jit.movie needs output_texture enabled:

    var moviePlayer = new JitterObject("jit.movie");
    moviePlayer.output_texture = 1;

    Get new frame and output texture:

    function LoadNewFrame()
    {
    moviePlayer.matrixcalc(dummyMat, dummyMat);
    outlet(0, moviePlayer.texture_name);
    }

Get the new frame as texture: newFrame = moviePlayer.texture_name;

  • Get texture output from jit.gl.node:var texOut = myNode.out_name;

  • Use a JitterListener to listen to change of state in Jitter Objects:
    https://docs.cycling74.com/max8/tutorials/jitterchapter47?q=jitterlistener

  • OUTPUTMATRIX from GL objects in JS:
    check out the example patch js.gl.matrixoutput.maxpat in the Files Browser.

  • JIT.CONCAT in JS:
    var concat = new JitterObject("jit.concat");
    concat([leftMat, rightMat], outMat);

  • Get the TEXTURE name from JIT.GL.NODE:
    return myNode.out_name;
    Or:
    myNode.out_names;

Max 4 Live

11OLSEN's icon

Hi, I think the real bible is this https://docs.cycling74.com/max8/vignettes/javascriptinmax, isn't it ?

btw: the JitterListener link doesn't work.

Federico-AmazingMaxStuff's icon

Thank you Olsen, that's a great resource, will pin it to the top.
However I find that it's still useful to collect all the Jitter syntax and the more esoteric things (like "activeinput" for jit.gl.pix and jit.gl.slab) which are not immediately recollected from the documentation.

If nothing else, I will use this post to note things I encounter and that I wish to remember.

Oh yes, Tim's website is a bit funky, thanks for noting

Rob Ramirez's icon

try this link for Tim's JS site - http://max-javascript-reference.tim-schenk.de/

(and thanks much for collecting these Federico, hugely helpful)

Federico-AmazingMaxStuff's icon

Thank you Rob, wanted to point to a precise article, but will pin Tim's website as well as a resource.

ntrm's icon

Might be nice to have some more advanced new object examples

Here are some from my own patches
var myNewObject = p.newdefault(100, 100, "bpatcher", "@name", "myPatch", "@args", name);

var anotherObject = p.newdefault(100, 100, "combine", "text", "::", "moretext")

ntrm's icon

Feel like Dict stuff needs a section, too. Some examples:

Basic querying:
function dictionary(dictname) {
var d = new Dict(dictname);
outlet(0, d.get('layer1key::layer2key');
}

Iterating through layers of a Dict:

function dictionary(dictname) {
var d = new Dict(dictname);
var layer1 = d.getkeys();
layer1.forEach(function(key) {
var layer2 = d.get(key).getkeys();
}
}

Federico-AmazingMaxStuff's icon

Awesome NTRM, both added.

fraction's icon

This thread is going to be very helpful, as js in max related informations are pretty much spread and scarce along a lot of years, and probably under documented, even in the forum, so the learning start might seem scary for our community while i find js in max is powerful,

I m looking forward to see this growing. Thx Federico!

11OLSEN's icon

Here are some JSUIs which accept mouse drag operations to move other objects in locked patchers.

11OLSEN's icon

Roald Baudoux collected some examples of buffer~ operations with js in this thread.

OCH's icon

Thanks everyone.

fraction's icon

When you arrive in js, it is sometimes complicated to identify script errors that are related to specificities of js in max. It would be helpfull for js beginners (like me) if we could collect here the things to know about these little particularities that your max logic won't help to figure out :)

Two examples :

For jit.gl.text , 2d or 3d has to be specified in the var attribute, and not in the object argument itself (unlike the max externals)

var mytext = new JitterObject ("jit.gl.text","context");
mytext.mode = 2d ; // or 3d

For jit.gl.light, the drawing context has to be specified in the drawto attribute (not in the object argument)

var mylight = new JitterObject ("jit.gl.light");
mylight.drawto = "mycontext";

Context set in the argument will generate console error "#N: extra arguments for message "jit_gl_light"

fraction's icon

Sharing this pretty interesting thread, which links to comprehensive tutorials on how to use Ableton Api in js/m4l.
It worths to share it again here:
https://cycling74.com/forums/tutorial-using-the-javascript-live-api-in-max-for-live

http://compusition.com/writings/js-live-api

Federico-AmazingMaxStuff's icon

Awesome! Loving the contributions

fraction's icon

some useful links referenced in here :
https://cycling74.com/forums/looking-for-good-inforeference-on-js

timtation's icon

I guess the documentation on my site is pretty outdated, guess I made it almost 10 years ago. Is it still helpful? Did not try the node integration of max ever. So I don't know what changed lately. Are there any updates needed?

loadmess's icon

Recently found this resource for people getting started (like me) and I believe it's great.
http://hems.io/max.js/#/
* you have to use the cursor. :)

Jan M's icon

@loadmess: that is indeed a very compact guide - apart from showing the title is does do nothing here :)

* yes I used the cursor :)

Federico-AmazingMaxStuff's icon

Ah! Was working on my phone but not on pc, it was looking great tho!

loadmess's icon

@JAN Perhaps try giving a click in the area where information is shown before using the cursor. It works for me. I'm using chrome by the way.

OCH's icon

On the phone you can just swipe up to change the slides, and then when you reach the end you swipe left to go to next column. On the computer you can press ESC key to see the overview of all the columns ;)

OCH

lysdexic's icon

One thing I can never remember is how to get the arguments typed into another object box (ie not jsarguments)..

Federico Foderaro's icon

Hey LYSDEXIC!

I think it would work like this:

var myNewObject = p.newdefault(100, 100, "objName", "@argName", argValue);

lysdexic's icon

Hey Federico!

Yep - that looks like what you'd want to do to create a new object.. What I mean is to query an existing object for its args.

ie:

// walk the patchcord and get the arguments from the object connected to the first outlet
ourself = this.box;
destobj = ourself.patchcords.outputs[0].dstobject;
// destobj.getattr("text"); ?

11OLSEN's icon

Hi, here you go:
destobj.getboxattr("boxatoms");

lysdexic's icon

brilliant! it works! cheers - something I look for all the time! :D

Federico-AmazingMaxStuff's icon

Awesome!!
I did try to do this for a while without success.
Straight in the list.

Trevor being Trevor's icon

Posted this a couple threads the other, but it also seems revelant here. This tutorial provides a lot of great examples for declaring classes in Javascript with the old syntax used in the Max js object. https://www.newthinktank.com/2015/09/object-oriented-javascript/

Max Carell's icon

I will make sure it's available from somewhere safe soon after some optimisations since the original Ircam website seem to be dead or sth!

SanGennaro's icon

Thank you, Federico, for this useful guide.

I just found a pitfall, encapsulating File into a function, if using an argument as a path, needs to be converted to string again or it will not work. I.e.:

function fileExists(filePath) {
    this.f = new File(String(filePath));
}