Attribute Parsing

I’ve been working with javascript in MaxMSP quite a lot recently. I find it easier to work with when dealing with lists, logic and patch scripting. Personally, I think it makes a lot more sense to use a few lines of code than loads of standard objects. I will share some of these javascript tools in the future, hopefully someone will find them useful. In the meantime I’ve been tidying them up, documenting them and making helpfiles. While doing this I realised that it would be nice to be able to use @style attributes in the [js] object like you can in standard objects rather than just creating an array from the “jsarguments” property. So I decided to write a script to parse both attributes and arguments automatically so you don’t have to search for them yourself. Here it is:

/*
* argument and attribute parser for javascripts in max
* 
* initial jsarguments become the args property array
* "@somename" formatted jsarguments define a new attribute
* any following jsarguments become the somename property array
* attributes with no following jsarguments are ignored
* attribute names must only contain characters: a-z0-9_
* "args" is reserved, an attribute named "args" will be ignored
* 
* example:
* 
* var aa = new aa_parser(this);			// define variable and initialise
* property: aa.args;					// returns array of arguments
* property: aa.type;					// returns array of "@type" attribute
* object: aa["attrname"];				// dynamically return one of the above
*/

function aa_parser(scope) {
	var flag;
	var temp = [];
	var attrnames;
	var attrvals;
	var args;
	var re = /^@\w+$/;
	this.init = function() {
		flag = 0;
		args = [];
		attrnames = [];
		attrvals = [];
		for (var i=1; i<scope.jsarguments.length; i++) {
			if (!re.test(scope.jsarguments[i])) {
				if (!flag) {
					args.push(scope.jsarguments[i]);
				} else {
					temp.push(scope.jsarguments[i]);
				}
			} else if (!re.test(scope.jsarguments[i+1])) {
				if (temp.length) {
					attrvals.push(temp);
				}
				if (i != scope.jsarguments.length-1) {
					attrnames.push(scope.jsarguments[i].slice(1));
				}
				flag = 1;
			temp = [];
			}
		}
		if (temp.length) {
			attrvals.push(temp);
		}
		for (var i=0; i<attrvals.length; i++) {
            this[attrnames[i]] = attrvals[i];
        }
		this["args"] = args;
	}
	this.init();
}

/*
* end of argument and attribute parser code
* author: lhall
* date: November 2009
*/

You need to save this as lh.jsextensions.js in Cycling ’74 > jsextensions in your MaxMSP folder and then restart the program for it to be found. The comments at the top explain how to use it. You can then either query the arguments and specific attributes using properties or do it dynamically using the object style notation. There are a few things to notice:

  • @attributes with no following jsarguments are ignored
  • attribute names can only include “word” characters: A-Za-z0-9_
  • and finally @args is reserved as an attribute array and will be ignored if present

If you do any development for max with javascript and end up using this then please let me know. Your comments and suggestions are welcome. Here’s an example of how you might use it in a patch, click the boxes to expand. I’ve included the patch as JSON rather than compressed text for the benefit of MaxMSP4 users. Enjoy!

// lh.aa_example.js

var aa = new aa_parser(this);

function findattr(a,b) {
    if (typeof(aa[a]) != "undefined") {
        outlet(0,aa[a][b]);
    }
}

function findarg(a) {
    outlet(0,aa.args);
}

function bang() {
    outlet(0,aa.args);
    outlet(0,aa.mode);
    outlet(0,aa.verbose);
}

autowatch = 1;

// EOF
{
	"boxes" : [ 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "print result2",
				"fontsize" : 12.0,
				"numinlets" : 1,
				"patching_rect" : [ 49.0, 85.0, 73.0, 20.0 ],
				"numoutlets" : 0,
				"id" : "obj-24",
				"fontname" : "Arial"
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "button",
				"outlettype" : [ "bang" ],
				"numinlets" : 1,
				"patching_rect" : [ 49.0, 41.0, 20.0, 20.0 ],
				"numoutlets" : 1,
				"id" : "obj-25"
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "js lh.aa_example 0 3 @mode linear @verbose 1",
				"outlettype" : [ "" ],
				"fontsize" : 12.0,
				"numinlets" : 1,
				"patching_rect" : [ 49.0, 63.0, 267.0, 20.0 ],
				"numoutlets" : 1,
				"id" : "obj-26",
				"fontname" : "Arial"
			}

		}
 ],
	"lines" : [ 		{
			"patchline" : 			{
				"source" : [ "obj-26", 0 ],
				"destination" : [ "obj-24", 0 ],
				"hidden" : 0,
				"midpoints" : [  ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-25", 0 ],
				"destination" : [ "obj-26", 0 ],
				"hidden" : 0,
				"midpoints" : [  ]
			}

		}
 ]
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s