### Nested JSON Data Set

#### Description

The Spry.Data.NestedJSONDataSet class allows users to create data sets from more complex JSON structures. The Spry.Data.NestedJSONDataSet class provides the same basic functionality for maintaining an array of row objects, destructive and non-destructive filtering, and sorting, with the addition of controlling the flattening of nested repeating nodes.

The Spry.Data.NestedJSONDataSet class derives from Spry.Utils.Notifier so it can also dispatch notifications.

#### File

SpryNestedJSONDataSet.js

#### Inheritance

Notifier --> DataSet

### NestedJSONDataSet constructor

#### Description

Spry.Data.NestedJSONDataSet is the constructor function for the Nested JSON Data Set.

#### Format

Spry.Data.NestedJSONDataSet(dsName, jpath)

#### Arguments

The constructor takes two arguments:

- the name of a regular JSON data set, previously defined.
- the jpath to the nested repeating node.

Options - An optional argument which if specified, must be an object with the option names as properties with values. Properties that can be specified are:

- distinctOnLoad - Boolean. If true, performs a distinct operation on the data after it is loaded.
- distinctFieldOnLoad - String or Array. Used in conjunction with disinctOnLoad. Value is a string that specifies the column to use for the distinct operation, or an array of strings that specify which columns to use for the distinct operation.
- filterFunc - Function Reference. The function to be used to non-destructively filter the data when it is loaded.
- filterDataFunc - Function Reference. The function to be used destructively filter the data when it is loaded.
- loadInterval - Integer. If greater than zero, automatically starts an interval timer that will call loadData() continuously. The value of loadInterval is expressed in milliseconds.
- sortOnLoad - String or Array. If the value is a string, it specifies the column to use when sorting after the data is loaded. If the value is an array, the array contains the names of the columns to use when sorting the data after it is loaded. The sort is done in the order the columns are specified with in the array.
- sortOrderOnLoad - String. Used in conjunction with the sortOnLoad option, the value should be the string "ascending" or "descending". If not specified, "ascending" is used.

#### Returns

N/A

#### Example

    //define a regular JSON Data Set.

    var ds1 = new Spry.Data.JSONDataSet();
    //create a Nested JSON Data Set based on the above.

    var nds2 = new Spry.Data.NestedJSONDataSet(ds1,"products/product/feature",{distinctOnLoad:true});

#### Sample

JSONDataSetSample.html

### distinct

#### Description

This function is used to remove duplicate rows from the Nested JSON Data Set. The distinct function will evaluate all the columns and if it finds 2 or more rows where every value is the same, it will throw away the duplicate rows and keep only one. This function can only be called *after* the data has been loaded into the Nested JSON Data Set.

Distinct can also be run automatically whenever new data is loaded into the Data Set. This is done by specifying the distinctOnLoad constructor option. In case the distinct functionality is need only for specific column(s) they may be defined through the additional parameter distinctFieldsOnLoad.

#### Format

distinct(columnNames)

#### Arguments

columnNames - String or Array. The column(s) of the Nested JSON Data Set to use when determining if a row is distinct. This parameter is optional. If ommited, all columns are used to determine if a row is distinct or not. If specified, must be a string that is the name of the column to use for the distinct process, or, must be an array of column names to used for the distinct process.

#### Returns

N/A

#### Example

    /* After a Nested JSON Data Set is defined and loaded with data, you can call
     * distinct on it.
     */

    varn ds1 = Spry.Data.NestedJSONDataSet(ds1,"jpath");
    ...
    ds1.distinct();

### filter

#### Description

This function is used to non-destructively filter the Nested JSON Data Set based on a filter function provided by the caller. The filter function passed in must have the following interface:

    function myFilterFunc(ds, row, rowIndex)
    {
      ...
    }

The arguments to this function are as follows:

- ds - The name of the Nested JSON Data Set being filtered.
- row - The row to filter.
- rowIndex - The row index of the row within the unfiltered version of the Nested JSON Data Set.

The caller's filter function is called once for each row in the Nested JSON Data Set. If the caller's filter function wishes to add the row to the filtered view of the Nested JSON Data Set, then it must return the row object passed into the function. If it does not want the row to be in the filtered view of the Nested JSON Data Set, then it must return null.

As previously mentioned, this filtering is done non-destructively so internally, the Nested JSON Data Set is using the function to determine if it should add a row to a copy of the row array.

The caller's filter function remains active until it is removed. The filter function can be removed by calling filter with a null value instead of a function reference.

After filtering, a call to the getData function will return the filtered array of rows. To get the unfiltered array of rows, you must call getData, passing in a true for the unfiltered argument.

FilterData is the destructive filter, which actually throws out the filtered data from memory.

#### Format

datasetname.filter(filterFunction);

#### Arguments

filterFunction - Function Reference. The function to use to determine if a row should be filtered out or not.

#### Returns

N/A

#### Example

    var myFilterFunc = function(dataSet, row, rowNumber)
    {
      // Filter out all rows with paths that begin
      // with the letter 's'.

      if (row["@path"].search(/^s/) != -1)
        return row;  // Return the row to keep it in the Nested JSON Data Set.
      return null;   // Return null to remove the row from the Nested JSON Data Set.
    }

    // Filter the data.

    dsPhotos.filter(myFilterFunc);

    ...

    // Remove the filter.

    dsPhotos.filter(null);

#### Sample

Non Destructive Filtering

### filterData

#### Description

This function is used to filter the Nested JSON Data Set based on a filter function provided by the caller. filterData is a destructive method, which means that all rows that are discarded by the filtering is lost. The data can only be retrieved again by loading the data back into the Nested JSON Data Set again.

The filter function passed in must have the following interface:

    function myFilterFunc(ds, row, rowIndex)
    {
      ...
    }

The arguments to this function are as follows:

- ds - The name of the Nested JSON Data Set being filtered.
- row - The row to filter.
- rowIndex - The row index of the row within the unfiltered version of the Nested JSON Data Set.

The caller's filter function is called once for each row in the Nested JSON Data Set. If the caller's filter function wishes to keep the row, then it must return the row object passed into the function. If it does not want to keep the row, then it must return null.

As previously mentioned, this filtering is destructive so internally, the Nested JSON Data Set is modifying its only copy of the row array.

The caller's filter function remains active until it is removed, so if the Nested JSON Data Set is reloaded, the filtering will occur. The filter function can be removed by calling filter with a null value instead of a function reference.

filter is the non-destructive version of this function.

#### Format

datasetname.filterData(filterFunction);

#### Arguments

filterFunction - Function Reference. The function to use to determine if a row should be kept or discarded.

#### Returns

N/A

#### Example

    var myFilterFunc = function(dataSet, row, rowNumber)
    {
      // Filter out all rows with paths that begin
      // with the letter 's'.

      if (row["@path"].search(/^s/) != -1)
        return row;  // Return the row to keep it in the Nested JSON Data Set.
      return null;   // Return null to remove the row from the Nested JSON Data Set.
    }

    // Filter the data.

    dsPhotos.filterData(myFilterFunc);

    ...

    // Remove the filter.

    dsPhotos.filterData(null);

#### Samples

N/A

### findRowsWithColumnValues

#### Description

Finds all rows within the Nested JSON Data Set that have the same column values contained in the specified object.

#### Format

findRowsWithColumnValues(valueObj, firstMatchOnly, unfiltered)

#### Arguments

valueObj - Object. Object containing the names of the columns and their values which each row must contain to be considered a match.

firstMatchOnly - Boolean. Optional argument. If true, causes the function to return the row object that first matched the values specified in valueObj. If not match was found, returns null.

unfiltered - Boolean. Optional argument. If true the function does its find through the unfiltered set of rows within the Nested JSON Data Set. If false or undefined, the find is done through the filtered set of rows.

#### Returns

The value returned by this function depends on the value of the firstMatchOnly argument. If firstMatchOnly is true, the function will return either the first row object that matches, or null. If firstMatchOnly is false or undefined, the function will return an array of all matches. This array may be empty (length == 0) if no matches were found.

#### Example

    var ds = new Spry.Data.NestedJSONDataSet();

    ..

    // Look for all rows that have a column called "color" with a value of "red"
    // and a column called "type" with a value of "sports".

    var matchingRows = ds.findRowsWithColumnValues({ color: "red", type: "sports"

    alert("Found " + matchingRows.length + "match(es).");

    //Look for the first row that matches:

    var firstMatchingRow = ds.findRowsWithColumnValues({ color: "red", type: "sports" }, true);

    if (firstMatchingRow != null)
      alert("Found a match!");
    else
      alert("Failed to find a match!");

### getColumnType

#### Description

This function returns the column type of the specified column.

#### Format

getColumnType(columnName);

#### Arguments

columnName - String. The name of the column.

#### Returns

The column type of the specified column, as a string:

- "string"
- "number"
- "date"
- "html"

#### Example

    var ds = new Spry.Data.NestedJSONDataSet();

    ...

    var colType = ds.getColumnType("firstname");

### getCurrentRow

#### Description

This function returns the object that is the 'currentRow' in the Nested JSON Data Set. By default, the current row is the first row of the Nested JSON Data Set, but this can be changed by calling the function setCurrentRow() or setCurrentRowNumber().

#### Format

getCurrentRow()

#### Arguments

N/A

#### Returns

The row object or null.

Developers should note that the row object returned is the Nested JSON Data Set's internal row object. Any changes to the properties of this object results in a change to the data within the Nested JSON Data Set.

#### Example

    var row = ds1.getCurrentRow();

    if (row["@title"] == "Me, Myself and I")
    ...

### getCurrentRowID

#### Description

This function returns the row ID of the current row.

Developers should not confuse the ID of a row with the index of the row. The ID is a column that contains a unique identifier for the row. This identifier does not change if the rows of the Nested JSON Data Set are sorted, where as the row index for a given row will change if the rows are sorted.

#### Format

getCurrentRowID()

#### Arguments

N/A

#### Returns

Integer or String that represents the row ID.

The actual type of the row ID is left up to the implementor, but it must be an integer or string that can be used as a key into an associative array.

#### Example

    var rowID = ds.getCurrentRowID();

    alert("Current row is: " + rowID);

### getCurrentRowNumber

#### Description

This function returns the row index for the current row.

Developers should not confuse the row number for a row with its ID. The ID is a column that contains a unique identifier for the row. This identifier does not change if the rows of the Nested JSON Data Set are sorted, where as the row index for a given row may change if the rows are sorted.

#### Format

getCurrentRowNumber()

#### Arguments

N/A

#### Returns

Returns an integer index (row number) of the row within the Nested JSON Data Set.

#### Example

    var rowNumber = ds.getCurrentRowNumber();

    alert("Current row number is: " + rowNumber);

### getData

#### Description

This function returns an array of the internal row objects that store the data in the Nested JSON Data Set. Modifying any property of a row object results in a modification of the data in the Nested JSON Data Set. Users should keep in mind that some Nested JSON Data Sets load their data asynchronously, so they should check if it is ok to access the data, with a call to getDataWasLoaded(), before attempting to call getData().

#### Format

getData(unfiltered)

#### Arguments

unfiltered - Boolean. Optional argument. If true, getData() returns the unfiltered data array. If false or undefined, it returns the filtered version of the rows array.

#### Returns

Returns an array of row objects.

#### Example

    // Run through all of the rows in the Nested JSON Data Set. For each row,
    // get the value in the "name" column and check to see if it
    // is equal to the string "Spry". If it is, return the ID of
    // the matching row.

    var rows = ds.getData();

    for (var i = 0; i < rows.length; i++)
    {
      if (rows[i]["name"] == "Spry")
        return rows[i]["ds_RowID"];
    }

### getRowByID

#### Description

This method returns the row object associated with the specified row ID.

#### Format

getRowByID(rowID)

#### Arguments

rowID - Integer or String. The ID of the row.

#### Returns

Returns the row object with the given rowID or null if it is not found.

#### Example

    // Get the row with the ID of 10.

    var row = ds.getRowByID(10);

    // If we have a match, extract out the value
    // of the firstname column.

    if (row)
      var firstname = row.firstname;

### getRowByRowNumber

#### Description

This method returns the row object at the specified row number within the Nested JSON Data Set.

#### Format

getRowByRowNumber(rowNumber, unfiltered)

#### Arguments

rowNumber - Integer. The row number of the row to fetch.

unfiltered - Boolean. If true, the Nested JSON Data Set will return the row object at the given row number in the internal unfiltered data array. Otherwise, it returns the row object at the given row number in the filtered data array.

#### Returns

Returns the row object at the given row number or null if it is not found.

#### Example

    // Get row 10 of the unfiltered data.

    var row = ds.getRowByRowNumber(10, true);

    // If we have a match, extract out the value
    // of the firstname column.

    if (row)
      var firstname = row.firstname;

### getRowCount

#### Description

This function returns the number of rows in the Nested JSON Data Set. If the Nested JSON Data Set has a non-destructive filter, this function returns the number of filtered rows. Users can pass an optional boolean argument to this function. If true, it will return the number of unfiltered rows. If false it will return the number of filtered rows.

#### Format

getRowCount(unfiltered);

#### Arguments

unfiltered - Boolean. Optional argument. If true, getRowCount the number of rows in the unfiltered data array. Otherwise, it returns the number of rows in the filtered data array.

#### Returns

An integer that is the number of rows in the Nested JSON Data Set.

#### Example

    var filteredRowCount = ds.getRowCount();
    var unfilteredRowCount = ds.getRowCount(true);

### getRowNumber

#### Description

This function returns the row number for the specified row object in the Nested JSON Data Set. If the Nested JSON Data Set has an active non-destructive filter, the row number returned is of the row within the filtered data array. An optional boolean argument can be passed to the function which tells the function to return the row number for the row within the unfiltered data array.

#### Format

getRowNumber(rowObject, unfiltered)

#### Argument

rowObject - Object. The row to look for.

unfiltered - Boolean. Optional argument. If true the row number returned for the specified row is its row index within the unfiltered data array. Otherwise, it returns the index of the row within the filtered data array.

#### Returns

An integer that is the number of the specified row in the Nested JSON Data Set. Returns -1 if the row is not found within the Nested JSON Data Set.

### getSortColumn

#### Description

This function returns the name of the column that was used when the Nested JSON Data Set was last sorted. This function will return an empty string if the Nested JSON Data Set was never sorted.

#### Format

getSortColumn()

#### Arguments

N/A

#### Returns

A string that is the name of the column last used for a primary sort. If the Nested JSON Data Set has never been sorted, an empty it returns an empty string.

#### Example

    var columnName = ds.getSortColumn();

### getSortOrder

#### Description

This function returns the name of the sort order that was used when the Nested JSON Data Set was last sorted. This function will return an empty string if the Nested JSON Data Set was never sorted.

#### Format

getSortOrder()

#### Arguments

N/A

#### Returns

The current sort order of the Nested JSON Data Set:

- "ascending"
- "descending "
- ""

#### Example

    var sortOrderName = ds1.getSortOrder();

### loadData

#### Description

The default implementation for this function fires off asynchronous notifications for "onPostLoad" and "onDataChanged" events. Classes that derive from Spry.Data.NestedJSONDataSet are expected to override this function to trigger async loading of the data for the Nested JSON Data Set.

#### Format

loadData()

#### Arguments

N/A

#### Returns

NA

#### Example

    ds.setURL("newJSON.JSON");
    ds.loadData();"

#### Sample

Region States Sample

### setColumnType

#### Description

This function is used to set a column type for a data column. This is used to tell the Nested JSON Data Set the type of data it is dealing with. A common application is for setting numeric data as 'number'. This ensures that the column will sort numerically, and not alpha-numerically.

The valid column types are:

- "date"
- "html"
- "number"
- "string"

The 'html' column type results in the automatic entity decoding of values stored in a column of that type when the data is first loaded.

#### Format

setColumnType(columnName, type)

#### Arguments

columnName - String or Array of Strings. The name(s) of the column(s) to set.

type - String. One of the following values:

- "date"
- "html"
- "number"
- "string"

#### Returns

N/A

#### Example

    var ds1 = new Spry.Data.JSONDataSet("myJSON.JSON","races/standings");

    // Example of setting the type of one column:

    ds1.setColumnType("start", "date");

    // Example of setting the type of multiple columns
    // with one call:

    ds1.setColumnType(["rank","place"],"number");

### setCurrentRow

#### Description

Sets the current row of the Nested JSON Data Set to the row with the specified row ID.

This method will cause an "onCurrentRowChanged" notification to be sent to all observers.

#### Format

setCurrentRow(rowID)

#### Arguments

rowID - Integer or String. The row ID of the row that is to become the current row.

#### Returns

N/A

#### Example

    // Set the current row of the Nested JSON Data Set
    // to the row with the integer ID of 13:

    ds.setCurrentRow(13);

### setCurrentRowNumber

#### Description

This function makes the row, at the specified row number (index), the current row of the Nested JSON Data Set. Spry uses a zero based counting system for row numbers.

Developers should not confuse the ID of a row with the index of the row. A row ID is a unique identifier that is stored within the row in a column called "ds_RowID". This identifier does not change even if the rows of the Nested JSON Data Set are sorted, where as the row index for a given row can change if the rows are sorted.

#### Format

setCurrentRowNumber(rowNumber)

#### Arguments

rowNumber - Integer. The row number of the row that will become the current row.

#### Returns

N/A

#### Example

    // Make the 3rd row of the Nested JSON Data Set the current row. Remember
    // that the row number is zero based.

    ds.setCurrentRowNumber(2);

#### Sample

Set Current Row Sample

### sort

#### Description

Sorts the Nested JSON Data Set using the specified column(s) and sort order.

Developers specify what columns to sort by passing in a single column name string, or an array of column name strings as the first argument to the function. By specifying more than one column name, developers are able to perform secondary, tertiary, etc, sorts on the data.

Valid sort orders are:

- "ascending"
- "descending"
- "toggle"

The "toggle" sort order will sort the Nested JSON Data Set in "ascending" order if it has not been previously sorted, otherwise, it causes the Nested JSON Data Set to sort in the opposite direction from the last sort.

#### Format

sort(column, order)

#### Arguments

column - String or Array of Strings. The column names to sort.

order - The sort order to be used during the sort. Values for order must be one of the following:

- "ascending"
- "descending"
- "toggle"

#### Returns

N/A

#### Example

    // An example of sorting a Nested JSON Data Set in ascending order
    // based on the values in a single column called "lastname":

    ds.sort("lastname", "ascending");

    // An example of toggling the sort of a Nested JSON Data Set based
    // on the values in multiple columns. Since 3 columns are
    // specified, the Nested JSON Data Set will perform a tertiary sort:

    ds.sort(["firstname", "lastname", "@id"], "toggle");

Copyright © 2007. Adobe Systems Incorporated.
All rights reserved.