Introduction to the Weave JavaScript API

Weave is a Flash application, and its API functions are accessible in JavaScript directly from the embedded Flash object. You do not need to include any extra file in the HTML source. However, you can't call the functions immediately when the HTML page loads because at that time the Flash application hasn't finished loading yet and the functions are not available. The best way to handle this problem is to define a function that will be called automatically by Weave when the API is ready. Inside that function you can begin manipulating the session state or signal to other scripts that Weave is ready to communicate. There are two options, both of which can be defined either at the global scope or as properties of the embedded Flash object:
  • weaveApiReady() will be called as soon as the API functions are available, before any external session state has loaded.
  • weaveReady() will be called when the external session state file has been loaded.

Defining a weaveReady() function

This example defines a weaveReady() function that is automatically called by Weave and prints version information to the JavaScript console. Since multiple Weave instances can be embedded into a single HTML page, a pointer to the particular Weave instance is passed in to the weaveReady() function. Outside the weaveReady() function, you can get a pointer to the Weave embedded object using document.getElementById().

/**
 * @param weave A pointer to the Weave object that has just finished initializing.
 */
function weaveReady(weave) {
    var version = weave.path('WeaveProperties', 'version').getState();
    console.log('Weave version: ' + version);
}

The Path API

The Path API makes it easy to perform multiple operations relative to an object in the session state. The same WeavePath object can be re-used for multiple commands using method chaining. To generate a WeavePath object, call the path() function of the embedded Weave object.

Click here to skip to the examples.

Weave methods

/**
 * Creates a WeavePath object.  WeavePath objects are immutable after they are created.
 * This is a shortcut for "new weave.WeavePath(basePath)".
 * @param basePath An optional Array (or multiple parameters) specifying the path to an object in the session state.
 *                 A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @return A WeavePath object.
 */
function path(...basePath)

/**
 * Loads a session state file from a URL.
 * @param url The URL to the session state file (.weave or .xml).
 * @param callback An optional function to call when the file loading completes.
 */
function loadFile(url, callback)

/**
 * This function will remove all callbacks that were previously added using addCallback().
 * You may want to call this before calling loadFile() to prevent unwanted behavior due to scripts previously executed.
 */
function removeAllCallbacks()

WeavePath chainable methods

/**
 * Creates a new WeavePath relative to the current one.
 * @param relativePath An Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @return A new WeavePath object which remembers the current WeavePath as its parent.
 */

function push(...relativePath)

/**
 * Returns to the previous WeavePath that spawned the current one with push().
 * @return The parent WeavePath object.
 */
function pop()

/**
 * Requests that an object be created if it doesn't already exist at the current path (or relative path, if specified).
 * This function can also be used to assert that the object at the current path is of the type you expect it to be.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @param objectType The name of an ActionScript class in Weave.
 * @return The current WeavePath object.
 */
function request(...relativePath, objectType)

/**
 * Removes a dynamically created object.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @return The current WeavePath object.
 */
function remove(...relativePath)

/**
 * Reorders the children of an ILinkableHashMap at the current path.
 * @param orderedNames An Array (or multiple parameters) specifying ordered child names.
 * @return The current WeavePath object.
 */
function reorder(...orderedNames)

/**
 * Sets the session state of the object at the current path or relative to the current path.
 * Any existing dynamically created objects that do not appear in the new state will be removed.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @param state The session state to apply.
 * @return The current WeavePath object.
 */
function state(...relativePath, state)

/**
 * Applies a session state diff to the object at the current path or relative to the current path.
 * Existing dynamically created objects that do not appear in the new state will remain unchanged.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @param diff The session state diff to apply.
 * @return The current WeavePath object.
 */
function diff(...relativePath, diff)

/**
 * Adds a callback to the object at the current path.
 * When the callback is called, a WeavePath object initialized at the current path will be used as the 'this' context.
 * If the same callback is added to multiple paths, only the last path will be used as the 'this' context.
 * @param callback The callback function.
 * @param triggerCallbackNow Optional parameter, when set to true will trigger the callback now.
 * @param immediateMode Optional parameter, when set to true will use an immediate callback instead of a grouped callback.
 * @return The current WeavePath object.
 */
function addCallback(callback, triggerCallbackNow, immediateMode)

/**
 * Removes a callback from the object at the current path or from everywhere.
 * @param callback The callback function.
 * @param everywhere Optional paramter, if set to true will remove the callback from every object to which it was added.
 * @return The current WeavePath object.
 */
function removeCallback(callback, everywhere)

/**
 * Specifies additional variables to be used in subsequent calls to exec() and getValue().
 * The variables will be made globally available for any WeavePath object created from the same Weave instance.
 * @param newVars An object mapping variable names to values.
 * @param temporary Optional parameter. If set to true, these variables will be unset after the next call to exec() or getValue()
 *                  no matter how either function is called, including from inside custom WeavePath functions.
 * @return The current WeavePath object.
 */
function vars(newVars, temporary)

/**
 * Specifies additional libraries to be included in subsequent calls to exec() and getValue().
 * @param libraries An Array (or multiple parameters) specifying ActionScript class names to include as libraries.
 * @return The current WeavePath object.
 */
function libs(...libraries)

/**
 * Evaluates an ActionScript expression using the current path, vars, and libs.
 * The 'this' context within the script will be the object at the current path.
 * @param script The script to be evaluated by Weave under the scope of the object at the current path.
 * @param callback_or_variableName Optional callback function or variable name.
 * - If given a callback function, the function will be passed the result of
 *   evaluating the expression, setting the 'this' value to the current WeavePath object.
 * - If given a variable name, the result will be stored as a variable
 *   as if it was passed as an object property to WeavePath.vars().  It may then be used
 *   in future calls to WeavePath.exec() or retrieved with WeavePath.getValue().
 * @return The current WeavePath object.
 */
function exec(script, callback_or_variableName)

/**
 * Calls a function using the current WeavePath object as the 'this' value.
 * @param func The function to call.
 * @param args An optional list of arguments to pass to the function.
 * @return The current WeavePath object.
 */
function call(func, ...args)

/**
 * Applies a function to each item in an Array or an Object.
 * @param items Either an Array or an Object to iterate over.
 * @param visitorFunction A function to be called for each item in items. The function will be called using the current
 *                        WeavePath object as the 'this' value and will receive three parameters:  item, key, items.
 *                        If items is an Array, the key will be an integer. If items is an Object, the key will be a String.
 * @return The current WeavePath object.
 */
function forEach(items, visitorFunction)

/**
 * Calls a function for each child of the current WeavePath or the one specified by a relativePath. The function receives child names.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @param visitorFunction A function to be called for each child object. The function will be called using the current
 *                        WeavePath object as the 'this' value and will receive three parameters:  name, index, names.
 * @return The current WeavePath object.
 */
function forEachName(...relativePath, visitorFunction)

/**
 * Calls a function for each child of the current WeavePath or the one specified by a relativePath. The function receives child WeavePath objects.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @param visitorFunction A function to be called for each child object. The function will be called using the current
 *                        WeavePath object as the 'this' value and will receive three parameters:  child, index, children.
 * @return The current WeavePath object.
 */
function forEachChild(...relativePath, visitorFunction)

/**
 * Calls weaveTrace() in Weave to print to the log window.
 * @param args A list of parameters to pass to weaveTrace().
 * @return The current WeavePath object.
 */
function trace(...args)

Visualization-specific chainable methods

/**
 * Requests that a panel object be created if it doesn't already exist at the current path.
 * @param type The type of panel requested.
 * @param x A numeric value for the panel X coordinate.
 * @param y A numeric value for the panel Y coordinate.
 * @param width A numeric value for the panel width.
 * @param height A numeric value for the panel height.
 * @return The current WeavePath object.
 */
function requestPanel(type, x, y, width, height)

/**
 * This is a shortcut for pushing the path to a plotter from the current path, which should reference a visualization tool.
 * @param plotterName (Optional) The name of an existing or new plotter.
 *                    If omitted and the current path points to a LayerSettings object, the corresponding plotter will be used.
 *                    Otherwise if omitted the default plotter name ("plot") will be used.
 * @param plotterType (Optional) The type of plotter to request if it doesn't exist yet.
 * @return A new WeavePath object which remembers the current WeavePath as its parent.
 */
function pushPlotter(plotterName, plotterType)

/**
 * This is a shortcut for pushing the path to a LayerSettings object from the current path, which should reference a visualization tool.
 * @param plotterName (Optional) The name of an existing plotter.
 *                    If omitted, either the plotter at the current path or the default plotter ("plot") will be used.
 * @return A new WeavePath object which remembers the current WeavePath as its parent.
 */
function pushLayerSettings(plotterName)

/**
 * Sets the metadata for a column at the current path.
 * @param metadata The metadata identifying the column. The format depends on the data source.
 * @param dataSourceName (Optional) The name of the data source in the session state.
 *                       If ommitted, the first data source in the session state will be used.
 * @return The current WeavePath object.
 */
function setColumn(metadata, dataSourceName)

/**
 * Sets the metadata for multiple columns that are children of the current path.
 * @param metadataMapping An object mapping child names (or indices) to column metadata.
 *                        An Array of column metadata objects may be given for a LinkableHashMap.
 * @param dataSourceName (Optional) The name of the data source in the session state.
 *                       If ommitted, the first data source in the session state will be used.
 * @return The current WeavePath object.
 */
function setColumns(metadataMapping, dataSourceName)

WeavePath properties and non-chainable methods

/**
 * A pointer to the Weave instance.
 */
var weave

/**
 * Returns a copy of the current path Array or the path Array of a descendant object.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names to be appended to the result.
 * @return An Array of successive child names used to identify an object in a Weave session state.
 */
function getPath(...relativePath)

/**
 * Gets an Array of child names under the object at the current path or relative to the current path.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @return An Array of child names.
 */
function getNames(...relativePath)

/**
 * Gets an Array of child WeavePath objects under the object at the current path or relative to the current path.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @return An Array of child WeavePath objects.
 */
function getChildren(...relativePath)

/**
 * Gets the type (qualified class name) of the object at the current path or relative to the current path.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @return The qualified class name of the object at the current or descendant path, or null if there is no object.
 */
function getType(...relativePath)

/**
 * Gets the session state of an object at the current path or relative to the current path.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @return The session state of the object at the current or descendant path.
 */
function getState(...relativePath)

/**
 * Gets the changes that have occurred since previousState for the object at the current path or relative to the current path.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @param previousState The previous state for comparison.
 * @return A session state diff.
 */
function getDiff(...relativePath, previousState)

/**
 * Gets the changes that would have to occur to get to another state for the object at the current path or relative to the current path.
 * @param relativePath An optional Array (or multiple parameters) specifying descendant names relative to the current path.
 *                     A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * @param otherState The other state for comparison.
 * @return A session state diff.
 */
function getReverseDiff(...relativePath, otherState)

/**
 * Returns the value of an ActionScript expression or variable using the current path, vars, and libs.
 * The 'this' context within the script will be set to the object at the current path.
 * @param script_or_variableName The script to be evaluated by Weave, or simply a variable name.
 * @return The result of evaluating the script or variable.
 */
function getValue(script_or_variableName)

Path API Examples

Example 1: Get the names of plot layers on a map tool

var weave = document.getElementById('weave');
var names = weave.path('MapTool','children','visualization','plotManager','plotters')
    .getNames();
console.log(names);

Example 2: Create a scatterplot and a corresponding legend

var weave = document.getElementById('weave');
var path = weave.path();

var sp = 'scatterplot';
path.push(sp)
        .requestPanel('ScatterPlotTool', 50, 0, 50, 100)
    .pop()
    .push('legend')
        .requestPanel('SizeBinLegendTool', 0, 0, 50, 100)
        .state({dynamicScatterPlotTool: sp})
    .pop();

Example 3: When keys are probed (moused over), set the selected keys equal to the probed keys.

var weave = document.getElementById('weave');
var selection = weave.path('defaultSelectionKeySet');
var probe = weave.path('defaultProbeKeySet').addCallback(function(weave){
    selection.state(probe.getState());
});

Example 4: Creating a data source

The ASDoc for CSVDataSource.as is here.

// First, create a CSVDataSource to hold the data
var weave = document.getElementById('weave');
var path = weave.path('My Custom Data').request('CSVDataSource');

// Option 1: Set the data to a CSV file available at a URL:
path.state('url', 'http://www.example.com/mydata.csv');

// Option 2: Set the data using a CSV String.
var csvData = "col1,col2\n" +
    "124,532\n" +
    "389,197\n" 
    "289,349\n";
path.vars({"str": csvData}, true)
    .exec('this.setCSVDataString(str)');
// Alternatively, path.vars({"str": csvData}, true).exec('var rows = WeaveAPI.CSVParser.parseCSV(str); this.setCSVData(rows)');

// Option 3: Set the data using a 2D-Array (list of rows).
var rows = [
    ["col1","col2"],
    [124,532],
    [389,197],
    [289,349]
];
path.state('csvData', rows);
// Alternatively, path.vars({"rows": rows}, true).exec('this.setCSVData(rows)');

// Option 4: Set the data using an Array of Objects.
var records = [
    {"col1": 124, "col2": 532},
    {"col1": 389, "col2": 197},
    {"col1": 289, "col2": 349}
];
path.vars({"records": records}, true)
    .exec('var rows = WeaveAPI.CSVParser.convertRecordsToRows(records); this.setCSVData(rows);');

Example 5: Using stored ActionScript variables.

// linking the zoom of two map tools
weave.path()
    // save a pointer to the first ZoomBounds object under the ActionScript variable zb1
    .push('MapTool').exec('visualization.plotManager.zoomBounds', 'zb1').pop()

    // save a pointer to the second ZoomBounds object under the ActionScript variable zb2
    .push('MapTool2').exec('visualization.plotManager.zoomBounds', 'zb2').pop()

    // link the session state of the two ZoomBounds objects using the previously saved ActionScript variables
    .exec('WeaveAPI.SessionManager.linkSessionState(zb1,zb2)');
// linking the zoom of two map tools (version 2, using JavaScript variables)
var subpath = ['children', 'visualization', 'plotManager', 'zoomBounds'];
var zb1 = weave.path('MapTool').push(subpath);
var zb2 = weave.path('MapTool2').push(subpath);
// Function pointers can be passed between Weave and JavaScript
var linkSessionState = weave.path().getValue('WeaveAPI.SessionManager.linkSessionState');
// WeavePath objects are automatically replaced with their corresponding ILinkableObjects when calling Weave code.
linkSessionState(zb1, zb2);
// adding an ActionScript callback
weave.path('v')
    // Create a LinkableString for testing, which will appear in the session state as "v" 
    .request('LinkableString')

    // Define a custom ActionScript function called "myCallback" 
    .exec("function(){ weaveTrace('v =', this.value); }", 'myCallback')

    // Attach our previously defined ActionScript function as a callback to our LinkableString
    .exec('this.addImmediateCallback(null, myCallback)')

    // Change the session state of the LinkableString so it triggers the callback
    .state('hello world')

Example 6: Extending WeavePath with custom functions via WeavePath.prototype

// Example extending WeavePath.prototype with a new function.
// This function reorders child names by inserting an existing name at a new position.
weave.WeavePath.prototype.insertAt = function(name, index) {
    // "this" will be the WeavePath object
    var names = this.getNames();
    names.splice(names.indexOf(name), 1); // remove from current position
    names.splice(index, 0, name); // insert at new position
    this.reorder(names);
    return this; // allows method chaining to continue after calling this function
};

// Example usage
var names = weave.path('my-data-table')
    .request('DataTableTool')
    .push('columns')
        // create three (empty) columns
        .forEach(['A', 'B', 'C'], function(name){
            this.request(name, 'DynamicColumn');
        })
        // insert object named 'C' at index 1
        .insertAt('C', 1) // <---------- using function defined above
        .getNames();
console.log(names);  // ["A", "C", "B"]

Example 7: Advanced custom function for dynamically updating a statistical line on a bar chart.

/**
 * Adds a mean or median value line to a bar chart and updates it automatically.
 * Must be called from the path of a bar chart tool.
 * @param type Either "mean" or "median".
 * Example usage:  weave.path('CompoundBarChartTool').addBarChartLine('median');
 */
weave.WeavePath.prototype.addBarChartLine = function(type) {
    var statFunc = type == 'median' ? 'getMedian' : 'getMean';
    var label = type == 'median' ? 'Median' : 'Mean';
    var path = this.request('CompoundBarChartTool');
    var updateLine = function(){
        // get mean height and add a callback that will update the avg line when the stats change
        path.pushPlotter('plot')
            .push('heightColumns', 0)
                .exec('WeaveAPI.StatisticsCache.getColumnStatistics(this)', 'heightStats')
                .call(function(){ this.weave.addCallback('heightStats', updateLine); })
                // for convenience below, store the column pointer and the value
                .exec('this', 'heightColumn')
                .exec('heightStats.'+statFunc+'()', 'heightStatsValue')

            .pushPlotter(label + '-line', 'GridLinePlotter')
            .state({
                yOffset: this.getValue('heightStatsValue'),
                lineStyle: {color: {defaultValue: 0xFF0000}}
            })
            .pushLayerSettings().state('selectable', false)

            .pushPlotter(label + '-label', 'AxisLabelPlotter')
            .state({
                maxWidth: 80, // controls word wrapping
                alongXAxis: false,
                offset: this.getValue('heightStatsValue'),
                alignToDataMax: true,
                hAlign: 'left',
                vAlign: 'middle',
                labelFunction: '"' + label + ': ' + this.getValue('ColumnUtils.deriveStringFromNumber(heightColumn, heightStatsValue)') + '"'
            })
            .pushLayerSettings().state('selectable', false);
    };
    // update the avg line when the height columns change
    this.pushPlotter('plot')
        .push('heightColumns')
        .addCallback(updateLine, true);
    return this;
};

Example 8: Advanced function for making an AttributeMenuTool change more than just a column.

/**
 * This sets up callbacks so that when selectionPath changes
 * it will restore the session state for targetPath to what it
 * was the last time selectionPath had its current state.
 * @param selectionPath A WeavePath referring to a LinkableString
 *                      or LinkableNumber which the user can change.
 *                      Example: weave.path(["AttributeMenuTool", "selectedAttribute"])
 * @param targetPath A WeavePath referring to an object which you
 *                   want to associate with the menu selection.
 *                   Example: weave.path(["defaultColorBinColumn", "binningDefinition"])
 */
function rememberStates(selectionPath, targetPath)
{
    var weave = selectionPath.weave;
    if (!weave || !targetPath.weave)
        throw new Error("selectionPath and targetPath must both be WeavePath objects");
    if (weave != targetPath.weave)
        throw new Error("selectionPath.weave must equal targetPath.weave");
    if (['weave.core::LinkableString', 'weave.core::LinkableNumber'].indexOf(selectionPath.getType()) < 0)
        throw new Error("selectionPath must refer to a LinkableString or a LinkableNumber.");

    // initialize a LinkableHashMap to store the states
    var a = JSON.stringify(selectionPath.getPath());
    var b = JSON.stringify(targetPath.getPath());
    var storagePath = weave.path("rememberStates("+[a,b]+")").request("LinkableHashMap");

    // save a pointer to the copySessionState() function
    var copy = weave.path().getValue('WeaveAPI.SessionManager.copySessionState');

    // when the target state changes, save the state
    function save(){
        var name = String(selectionPath.getState());
        copy(targetPath, storagePath.push(name).request('LinkableVariable'));
    }
    targetPath.addCallback(save); // grouped callback

    // when the selection changes, recall previous state
    function recall(){
        var name = String(selectionPath.getState());
        if (storagePath.getType(name))
            copy(storagePath.push(name), targetPath);
        else
            save();
    }
    selectionPath.addCallback(recall, false, true); // immediate callback
}
// Example usage:

var selected_attr = weave.path(["AttributeMenuTool", "selectedAttribute"]);
var color_bin_def = weave.path(["defaultColorBinColumn", "binningDefinition"]);
var line_chart_cols = weave.path(["LineChartTool", "children", "visualization", "plotManager", "plotters", "plot", "columns"]);

rememberStates(selected_attr, color_bin_def);
rememberStates(selected_attr, line_chart_cols);

Example 9: A WeavePath function for adding a geometry label layer to a MapTool.

/**
 * Adds a label layer to an existing map tool.
 * Must be called from the path of a MapTool.
 * @param geomLayerName An existing geometry layer name.
 * @param labelColumnId A column ID specifying the label data.
 * @param color Label color.
 * @example
 *     weave.path('MapTool').addGeomLabels('my-geom-layer', 123, 0xFF0000);
 * @example
 *     weave.path('MapTool').addGeomLabels('my-geom-layer', {name: 'mylabel', dataTable: 'mytable'});
 */
weave.WeavePath.prototype.addGeomLabels = function(geomLayerName, labelColumnId, color)
{
    return this.request('MapTool')
        .pushPlotter(geomLayerName, 'GeometryLabelPlotter')
            .exec('geometryColumn', 'temp')
        .pop()
        .pushPlotter(geomLayerName + '-labels', 'GeometryLabelPlotter')
            .exec('WeaveAPI.SessionManager.copySessionState(temp, geometryColumn)')
            .setColumns({"text": labelColumnId})
            .state('color', 'defaultValue', color)
        .pop();
};

The Direct API

The Direct API is set of functions used internally by the Path API. While the Direct API will continue to be supported by Weave, we recommend using the newer Path API instead.

Example: weave.setSessionState()

Like most of the Direct API functions, the first parameter to setSessionState() specifies a path to an object in the session state as an Array of Strings. A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap. An empty Array can be used to specify the root object, e.g., weave.setSessionState([], newState) would update the entire visualization configuration in Weave with the given session state.

/* 
 * The first parameter to setSessionState() is a path (Array of Strings) to an object in the session state.
 * A child index number may be used in place of a name in the path when its parent object is a LinkableHashMap.
 * The second parameter is the session state to apply.
 * This example code enables "dashboard mode" in Weave.
 */
var weave = document.getElementById('weave');
weave.setSessionState(['WeaveProperties'], { dashboardMode: true });

Example code sample using the Direct API rewritten to use the Path API

Original code using the Direct API

    // Note: our query in the weave admin takes 3 parameters, the indicator id, geotypeid, and year.
    // meaning there is a where clause:
    // select blah from blah WHERE id = ? and geotype = ? and year = ?

    function symbols(indid,geoid,year,mode){
        var plotterLocation = ["MapTool","children","visualization","plotManager","plotters","grad_symbols",
                               "symbolPlotters","symbol"];

        // Make the object
        w().requestObject(plotterLocation, "weave.visualization.plotters::ScatterPlotPlotter");

        //This is the hierarchy for datax and datay, to position the symbols.
        var hp1 = '<hierarchy><category title="Geometry Collections" name="Geometry Collections">'
            + '<attribute dataType="geometry" name="w_grblk_10" title="w_grblk_10" keyType="w_grblk_10"/>'
            + '</category></hierarchy>';

        var locx = ["MapTool","children","visualization","plotManager","plotters","grad_symbols","symbolPlotters","symbol","dataX"];
        var locy = ["MapTool","children","visualization","plotManager","plotters","grad_symbols","symbolPlotters","symbol","dataY"];
        var locRadius = ["MapTool","children","visualization","plotManager","plotters","grad_symbols","symbolPlotters","symbol","screenRadius"];
        var blocksLayer = ["MapTool","children","visualization","plotManager","plotters","grad_symbols"];
        var layerObject = {

                className: "weave.data.AttributeColumns::ReferencedColumn",
                objectName: null,
                sessionState: {
                    dynamicColumnReference:
                        [
                        {
                          className: "weave.data.ColumnReferences::HierarchyColumnReference",
                          objectName: null,
                          sessionState: {
                             dataSourceName: "WeaveDataSource",
                             hierarchyPath: hp1
                          }
                        }
                     ]
            }
        };

        var sqlparams = indid + "," + geoid + "," + year;

        var hp2 = '<hierarchy><category title="Data Tables" name="Data Tables"><category title="bin_data_queries" name="bin_data_queries">'
          + '<attribute dataType="number" title="end" sqlParams="'+sqlparams+'" weaveEntityId="514" '
          + 'name="end" dataTable="bin_data_queries" keyType="w_grblk_10"/></category></category></hierarchy>';

        var layerObjectRadius = {
            className: "weave.data.AttributeColumns::ReferencedColumn",
            objectName: null,
            sessionState: {
                dynamicColumnReference: [
                    {
                        className: "weave.data.ColumnReferences::HierarchyColumnReference",
                        objectName: null,
                        sessionState: {
                            dataSourceName: "WeaveDataSource",
                            hierarchyPath: hp2
                        }
                    }
                ]
            }
        };

        var plotLocation = ["MapTool","children","visualization","plotManager","plotters"];
        var plotterValues = {
            enabledSizeBy: "true",
            maxScreenRadius: "12",
            minScreenRadius: "0",
            defaultScreenRadius: "0" 
        };

        if(mode == "show"){
            var addLayerX = w().getSessionState(locx);
            addLayerX[0] = layerObject;
            var addLayerY = w().getSessionState(locy);
            addLayerY[0] = layerObject;
            var addRad = w().getSessionState(locRadius);
            addRad[0] = layerObjectRadius;
            w().setSessionState(locx, addLayerX);
            w().setSessionState(locy, addLayerY);
            w().setSessionState(locRadius, addRad);
            w().setSessionState(plotterLocation, plotterValues);
            w().setSessionState(["MapTool","children","visualization","plotManager","plotters","grad_symbols",
                                 "symbolPlotters","symbol","fill","alpha","defaultValue"], ".50");
            w().setSessionState(plotterLocation, {absoluteValueColorEnabled: true, absoluteValueColorMax: "13158", absoluteValueColorMin: "13158"});
            w().setSessionState(["MapTool","children","visualization","plotManager","layerSettings","grad_symbols"],
                    {visible: true, selectable: false});
        } else {
            w().removeObject(plotterLocation);
            w().setSessionState(["MapTool","children","visualization","plotManager","layerSettings","grad_symbols","visible"], false);

        }

    }

Rewritten code using the Path API

function getWeave(){ return document.getElementById('weave'); }

function symbols(indid,geoid,year,mode)
{
    var visible = (mode == 'show');

    // geometry column for positioning the symbols
    var hp1 = {dataType: 'geometry', name: 'w_grblk_10', title: 'w_grblk_10', keyType: 'w_grblk_10'};

    // Note: our query in the weave admin takes 3 parameters, the indicator id, geotypeid, and year.
    // meaning there is a where clause:
    // select blah from blah WHERE id = ? and geotype = ? and year = ?
    var hp2 = {weaveEntityId: 514, sqlParams: [indid, geoid, year]};

    var path = getWeave().path('MapTool')
        .pushLayerSettings('grad_symbols')
            .state({visible: visible, selectable: false})
            .pushPlotter()
                .push('symbolPlotters', 'symbol');

    if (!visible)
        return path.remove();

    path.request('ScatterPlotPlotter')
        .state({
            maxScreenRadius: 12,
            minScreenRadius: 0,
            defaultScreenRadius: 0,
            absoluteValueColorEnabled: true,
            absoluteValueColorMax: 13158,
            absoluteValueColorMin: 13158
        })
        .state('fill', 'alpha', 'defaultValue', 0.5)
        .setColumns({dataX: hp1, dataY: hp2, sizeBy: hp2});
}

Helper functions

A set of optional Weave helper functions for JavaScript are available here: weave-tools.js.