Converting the Inline Json Data to Remote Json File - json

I used the answer at : YUI 3 -Datatable with Paginator + Query Builder + Sort tried
to for the samples http://jsbin.com/iwijek/10 and http://jsfiddle.net/UwjUt/ which have inline json data. I wanted to parse the remote json file for which I used the .get() as per YUI 3 docs. But bit does not do anything. plz check these examples and help me in parsing the remote json file.
{ var url = "file:///e:/Documents/json-search.txt";
var modelList;
dataSource = new Y.DataSource.Get({ source: url });
// comment
// var modelList = new Y.ModelList();
modelList = new Y.ModelList.Get({
source: url });
modelList.add();
}
json-search.txt
[{
name : 'Joe Bloggs',
company : 'ABC Inc',
state : 'AZ',
cost : 100
},
{
name : 'Jane Mary',
company : 'Bits and Bobs Ltd',
state : 'TX',
cost : 1000
},
{
name : 'Paul Smith',
company : 'PS Clothing PLC',
state : 'TX',
cost :400
},
{
name : 'Jack Jones',
company : 'jackjones.com',
State : 'NY',
cost: 9999
},
{
name : 'Crazy Horse',
company : 'Wacky Places Ltd.',
state : 'MI',
cost : 632
}]
I also tried to pass the datasource to the ModelList
YUI.add(
'datatable-filter',
function(Y) {
/**
Adds support for filtering the table data by API methods
#module datatable
#submodule datatable-filter
#since 3.5.0
**/
var YLang = Y.Lang,
isBoolean = YLang.isBoolean,
isString = YLang.isString,
isArray = YLang.isArray,
isObject = YLang.isObject,
toArray = Y.Array,
sub = YLang.sub;
/**
<pre><code>
var table = new Y.DataTable({
columns: [ 'id', 'username', 'name', 'birthdate' ],
data: [ ... ],
filters: true // this will render a filter input box for every column
});
table.render('#table');
</code></pre>
Setting `filters` to `true` will enable UI filtering for all columns. To enable
UI filtering for certain columns only, set `filters` to an array of column keys,
or just add `filters: true` to the respective column configuration objects.
This uses the default setting of `filters: auto` for the DataTable instance.
<pre><code>
var table = new Y.DataTable({
columns: [
'id',
{ key: 'username', renderFilter: true },
{ key: 'name' },
{ key: 'birthdate', renderFilter: true, filter : "=123", filterFn : customFilterFn }
],
data: [ ... ]
// filters: 'auto' is the default
});
To disable UI filtering for all columns, set `filters` to `false`. This still
permits filtering via the API methods.
filter via api:
var filterBy =
{
username : "=student",
name : "%richard",
birthdate : ">01-01-1975"
}
table.set("filterBy",filterBy);
As new records are inserted into the table's `data` ModelList, they will be checked against the filter to determine if they will be rendered
The current filters are stored in the `filterBy` attribute. Assigning this value at instantiation will automatically filter your data.
Filtering is done by a simple value comparison using '=', '!=', '<', '<=', '>', '>=' on the field value.
If you need custom filtering, add a filter function in the column's `filterFn` property. // TODO...
<pre><code>
function applePiesFilter(a) {
return a.get("type") == 'apple' ? true : false;
}
var table = new Y.DataTable({
columns: [ 'id', 'username', { key: name, filterFn: nameFilter }, 'birthdate' ],
data: [ ... ],
filters: [ 'username', 'name', 'birthdate' ]
});
</code></pre>
See the user guide for more details.
#class DataTable.Filters
#for DataTable
#since 3.5.0
**/
function Filters() {}
Filters.ATTRS = {
// Which columns in the UI should suggest and respond to filtering interaction
// pass an empty array if no UI columns should show filters, but you want the
// table.filter(...) API
/**
Controls which columns can show a filtering input
Acceptable values are:
* "auto" - (default) looks for `renderFilter: true` in the column configurations
* "true" - all columns have a filter field rendered
* "false" - no UI filters are enabled
* {String[]} - array of key names to give filter fields
#attribute filters
#type {String|String[]|Boolean}
#default "auto"
#since 3.5.0
**/
filters: {
value: 'auto',
validator: '_validateFilters'
},
/**
The current filter configuration to maintain in the data.
Accepts column `key` objects with a single property the value of the filter
E.g. `{ username: '%student' }`
E.g. `[{ username : '%student' }, { age : '<40'}]
#attribute filterBy
#type {String|String[]|Object|Object[]}
#since 3.5.0
**/
filterBy: {
validator: '_validateFilterBy'
},
/**
Strings containing language for filtering tooltips.
#attribute strings
#type {Object}
#default (strings for current lang configured in the YUI instance config)
#since 3.5.0
**/
strings: {}
};
Y.mix(Filters.prototype, {
/**
Filter the data in the `data` ModelList and refresh the table with the new
order.
#method filter
#param {String|String[]|Object|Object[]} fields The field(s) to filter by
#param {Object} [payload] Extra `filter` event payload you want to send along
#return {DataTable}
#chainable
#since 3.5.0
**/
filter : function (fields, payload) {
/**
Notifies of an impending filter, either from changing the filter in the UI
header, or from a call to the `filter` method.
The requested filter is available in the `filterBy` property of the event.
The default behavior of this event sets the table's `filterBy` attribute.
#event filter
#param {String|String[]|Object|Object[]} filterBy The requested filter
#preventable _defFilterFn
**/
return this.fire('filter', Y.merge((payload || {}), {
filterBy: fields || this.get('filterBy')
}));
},
/**
Template for the row that will hold the filter inputs
#property FILTERS_HEADER_CELL_TEMPLATE
#type {HTML}
#value
**/
FILTERS_HEADER_ROW_TEMPLATE : '<tr class="{filterRowClassName}" tabindex="0"></tr>',
/**
Template for the row that will hold the filter inputs
#property FILTERS_HEADER_CELL_TEMPLATE
#type {HTML}
#value
//<select><option value="=">=</option><option value="%">%</option><option value="!=">!=</option><option value="!%">!%</option><option value=">">%gt</option><option value=">=">>=</option><option value="<"><</option><option value="<="><=</option></select>
**/
FILTERS_HEADER_CELL_TEMPLATE : '<th class="{className}" tabindex="0" rowspan="1" colspan="1" title="Filter by {colName}">' +
'<div class="{linerClass}" tabindex="0"><input type="text" data-yui3-col-key="{colKey}" class="{inputClass}"/></div></th>',
/**
Template for the row that will doesn't have filter inputs
#property FILTERS_HEADER_CELL_TEMPLATE_NONE
#type {HTML}
#value
**/
FILTERS_HEADER_CELL_TEMPLATE_NONE : '<th class="{className}" tabindex="0" rowspan="1" colspan="1" title="Filtering unavailable on this field"></th>',
//--------------------------------------------------------------------------
// Protected properties and methods
//--------------------------------------------------------------------------
/**
Filters the `data` ModelList based on the new `filterBy` configuration.
#method _afterFilterByChange
#param {EventFacade} e The `filterByChange` event
#protected
#since 3.5.0
**/
_afterFilterByChange: function (e) {
var filters;
// Can't use a setter because it's a chicken and egg problem. The
// columns need to be set up to translate, but columns are initialized
// from Core's initializer. So construction-time assignment would
// fail.
// WHAT DOES THIS MEAN??
this._setFilterBy();
if (this._filterBy.length) {
// build the filter function
this._buildFilterFn();
// get the filtered data
this._filteredData = this.data.filter( { asList : true }, this._filterFn);
} else {
this._filteredData = this.data;
}
// 'hide' the filtered rows
this._hideFilteredData();
},
/**
#description if the row is not in the filtered data hide it, otherwise show it
#method _hideFilteredData
#protected
#since 3.5.0
**/
_hideFilteredData: function () {
var i,len,clientId;
for(i=0, len = this.data.size(); this._filteredData.getById && i < len; ++i) {
clientId = this.data.item(i).get("clientId");
if(this._filteredData.getByClientId(clientId)) {
this.get("contentBox").one("tbody").one("[data-yui3-record=" + clientId + "]").setStyle("display","table-row");
} else {
this.get("contentBox").one("tbody").one("[data-yui3-record=" + clientId + "]").setStyle("display","none");
}
}
},
/**
Applies the filtering logic to the new ModelList if the `newVal` is a new
ModelList.
#method _afterFilterDataChange
#param {EventFacade} e the `dataChange` event
#protected
#since 3.5.0
**/
_afterFilterDataChange: function (e) {
// object values always trigger a change event, but we only want to
// call _initFilterFn if the value passed to the `data` attribute was a
// new ModelList, not a set of new data as an array, or even the same
// ModelList.
if (e.prevVal !== e.newVal || e.newVal.hasOwnProperty('_compare')) {
// this._initFilterFn();
}
},
/**
Checks if any of the fields in the modified record are fields that are
currently being filtered by, and if so, refilters the `data` ModelList.
#method _afterFilterRecordChange
#param {EventFacade} e The Model's `change` event
#protected
#since 3.5.0
**/
_afterFilterRecordChange: function (e) {
var i, len;
for (i = 0, len = this._filterBy.length; i < len; ++i) {
if (e.changed[this._filterBy[i].key]) {
this.data.filter();
break;
}
}
},
/**
Subscribes to state changes that warrant updating the UI, and adds the
click handler for triggering the filter operation from the UI.
#method _bindFilterUI
#protected
#since 3.5.0
**/
_bindFilterUI: function () {
var handles = this._eventHandles;
// 'filterByChange' -> need to update UI
if (!handles.filterAttrs) {
handles.filterAttrs = this.after(
['filtersChange', 'columnsChange'],
Y.bind('_uiSetFilters', this));
}
if (!handles.filterUITrigger && this._theadNode) {
handles.filterUITrigger = this.delegate(['keyup','blur'],
Y.rbind('_onUITriggerFilter', this),
'.' + this.getClassName('filter', 'input'));
}
},
/**
Sets the `filterBy` attribute from the `filter` event's `e.filterBy` value.
#method _defFilterFn
#param {EventFacade} e The `filter` event
#protected
#since 3.5.0
**/
_defFilterFn: function (e) {
this.set.apply(this, ['filterBy', e.filterBy].concat(e.details));
},
/**
Sets up the initial filter state and instance properties. Publishes events
and subscribes to attribute change events to maintain internal state.
#method initializer
#protected
#since 3.5.0
**/
initializer: function () {
var boundParseFilter = Y.bind('_parseFilter', this);
this._parseFilter();
this._setFilterBy();
this._initFilterStrings();
// dataChange : Y.bind('_afterFilterDataChange', this),
//
// filterChange : boundParseFilter
this.after({
'sort' : this._hideFilteredData,
'columnsChange' : boundParseFilter,
'filterByChange' : Y.bind('_afterFilterByChange', this),
'table:renderHeader': Y.bind('_renderFilters', this)});
// this.data.after(this.data.model.NAME + ":change",
// Y.bind('_afterFilterRecordChange', this));
// TODO: this event needs magic, allowing async remote filtering
// this.publish('filter', {
// defaultFn: Y.bind('_defFilterFn', this)
// });
},
/**
Add the filter related strings to the `strings` map.
#method _initFilterStrings
#protected
#since 3.5.0
**/
_initFilterStrings: function () {
// Not a valueFn because other class extensions will want to add to it
this.set('strings', Y.mix((this.get('strings') || {}),
Y.Intl.get('datatable-filter')));
},
/**
#description Fires the `filter` event in response to user changing the UI filters
#method _onUITriggerFilter
#param {DOMEventFacade} e The `mouseout` event
#protected
#since 3.5.0
**/
_onUITriggerFilter: function (e) {
var colKey = e.currentTarget.getAttribute('data-yui3-col-key'),
column = colKey && this.getColumn(colKey),
filterBy = this.get("filterBy") || {},
i, len;
e.halt(); // not doing anything anyway?
if (column) {
filterBy[colKey] = e.currentTarget.get("value");
}
this.set("filterBy",filterBy);
},
/**
#description Build the filter function from the column config, this function is passed to the model list fiter() method
#method _buildFilterFn
#protected
#since 3.5.0
**/
_buildFilterFn: function () {
var i,len,op1,op2, key, filter, filterFn;
filterFn = function(model,index,modelList) {
var key,filter,op1,op2,val,filter,passesFilter = true;
for(i=0,len = this._filterBy.length; i< len && passesFilter; ++i) {
key = this._filterBy[i].key;
filter = this._filterBy[i].filter;
val = model.get(key) || '';
op1 = filter.substr(0,1);
op2 = filter.substr(1,1);
if(op2 == '=') {
switch(op1) {
case '!':
// not equal
if(val.toLowerCase() == filter.substr(2).toLowerCase()) {
passesFilter = false;
}
break;
case '>':
// greater or equal
if(parseInt(val) < parseInt(filter.substr(2))) {
passesFilter = false;
}
break;
case '<':
// less than or equal
if(parseInt(val) > parseInt(filter.substr(2))) {
passesFilter = false;
}
break;
}
} else if (op2 == '%' && op1 =='!') {
// not like
if((val.toLowerCase().indexOf(filter.substr(2).toLowerCase()) > -1)) {
passesFilter = false;
}
break;
} else {
switch(op1) {
case '=':
// equal
if(val.toLowerCase() != filter.substr(1).toLowerCase()) {
passesFilter = false;
}
break;
case '>':
// greater than
if(parseInt(val) <= parseInt(filter.substr(1))) {
passesFilter = false;
}
break;
case '<':
// less than
if(parseInt(val) >= parseInt(filter.substr(1))) {
passesFilter = false;
}
break;
case '%':
// like
if((val.toLowerCase().indexOf(filter.substr(1).toLowerCase()) === -1)) {
passesFilter = false;
}
break;
default:
// consider to be like
if((String(val).toLowerCase().indexOf(String(filter).toLowerCase()) === -1)) {
passesFilter = false;
}
break;
}
}
}
return passesFilter;
};
this._filterFn = Y.bind(filterFn,this);
},
/**
#description Normalizes the possible input values for the `filter` attribute setting up the column config as appropriate
#method _parseFilter
#protected
#since 3.5.0
**/
_parseFilter: function () {
var filters = this.get('filters'),
columns = [],
i, len, col;
col = this._displayColumns.slice();
this._uiFilters = false;
if(filters === 'auto') {
// look for key on columns
col = this._displayColumns.slice();
for(i = 0; i < col.length; i++) {
if(col[i].renderFilter) {
this._uiFilters = true;
}
}
} else if(filters === true) {
// provide UI filters for all cols
col = this._displayColumns.slice();
for(i = 0; i < col.length; i++) {
this._uiFilters = true;
this._displayColumns[i].renderFilter = true;
}
} else if (isArray(filters)) {
// provide UI filters on the specified cols (plural)
for (i = 0, len=filters.length; i < len; ++i) {
if(col = this.getColumn(filters[i])) {
this._uiFilters = true;
col.renderFilter = true;
}
}
} else if (filters) {
// provide UI filter on the specifed 'COL' (singular)
for (i = 0, len = col.length; i < len; ++i) {
if (col[i].key === filters) {
this._uiFilters = true;
this._displayColumns[i].renderFilter = true;
i = len;
}
}
}
},
/**
Initial application of the filters UI.
#method _renderFilters
#protected
#since 3.5.0
**/
_renderFilters: function () {
this._uiSetFilters();
this._bindFilterUI();
},
/**
#description Parses the current `filterBy` attribute and updates the columns
#method _setFilterBy
#protected
#since 3.5.0
**/
_setFilterBy: function () {
var columns = this._displayColumns,
filterBy = this.get('filterBy') || {},
filteredClass = ' ' + this.getClassName('filtered'),
i, len, name, dir, field, column;
this._filterBy = [];
// Purge current filter state from column configs
for (i = 0, len = columns.length; i < len; ++i) {
column = columns[i];
delete columns[i].filter;
if (column.className) {
// TODO: be more thorough
column.className = column.className.replace(filteredClass, '');
}
}
for (key in filterBy) {
if(filterBy[key]!='') {
// Allow filtering of any model field and any column
column = this.getColumn(key) || { _id: key, key: key };
if (column) {
column.filter = filterBy[key];
if (!column.className) {
column.className = '';
}
column.className += filteredClass;
this._filterBy.push(column);
}
}
}
},
/**
Array of column configuration objects of those columns that need UI setup
for user interaction.
#property _filters
#type {Object[]}
#protected
#since 3.5.0
**/
//_filters: null,
/**
Array of column configuration objects for those columns that are currently
being used to filter the data. Fake column objects are used for fields that
are not rendered as columns.
#property _filterBy
#type {Object[]}
#protected
#since 3.5.0
**/
//_filterBy: null,
/**
Replacement `comparator` for the `data` ModelList that defers filtering logic
to the `_compare` method. The deferral is accomplished by returning `this`.
#method _filterComparator
#param {Model} item The record being evaluated for filter position
#return {Model} The record
#protected
#since 3.5.0
**/
_filterComparator: function (item) {
// Defer filtering to ModelList's _compare
return item;
},
/**
Applies the appropriate classes to the `boundingBox` and column headers to
indicate filter state and filterability.
Also currently wraps the header content of filters columns in a `<div>`
liner to give a CSS anchor for filter indicators.
#method _uiSetFilters
#protected
#since 3.5.0
**/
_uiSetFilters: function () {
var columns = this._displayColumns.slice(),
filtersClass = this.getClassName('filters', 'column'),
filtersHidden = this.getClassName("filters","hidden"),
filterRowClass = this.getClassName("filters","row"),
filteredClass = this.getClassName('filtered'),
linerClass = this.getClassName('filter', 'liner'),
i, len, col, node, liner, title, desc;
this.get('boundingBox').toggleClass(
this.getClassName('filters'),
columns.length);
/// NEED TO ADDRESS
if((node = this._theadNode.one("." + filterRowClass))) {
node.remove(true);
}
if(columns.length>0 && this._uiFilters) {
tr = this._theadNode.appendChild(Y.Lang.sub(
this.FILTERS_HEADER_ROW_TEMPLATE, {
filterRowClassName: filterRowClass }));
for (i = 0, len = columns.length; i < len; ++i) {
if(columns[i].renderFilter) {
tr.append(Y.Lang.sub(
this.FILTERS_HEADER_CELL_TEMPLATE, {
className: this.getClassName("filter","cell"),
colKey : columns[i].key,
colName : columns[i].label || columns[i].key,
inputClass : this.getClassName("filter","input"),
linerClass: linerClass
}));
} else {
tr.append(Y.Lang.sub(
this.FILTERS_HEADER_CELL_TEMPLATE_NONE, {
className: this.getClassName("no-filter")
}));
}
}
}
},
/**
Allows values `true`, `false`, "auto", or arrays of column names through.
#method _validateFilters
#param {Any} val The input value to `set("filters", VAL)`
#return {Boolean}
#protected
#since 3.5.0
**/
_validateFilters: function (val) {
return val === 'auto' || isBoolean(val) || isArray(val);
},
/**
Allows strings, arrays of strings, objects, or arrays of objects.
#method _validateFilterBy
#param {String|String[]|Object|Object[]} val The new `filterBy` value
#return {Boolean}
#protected
#since 3.5.0
**/
_validateFilterBy: function (val) {
return val;
return val === null ||
isString(val) ||
isObject(val, true) ||
(isArray(val) && (isString(val[0]) || isObject(val, true)));
}
}, true);
Y.DataTable.Filters = Filters;
Y.Base.mix(Y.DataTable, [Filters]);
},"0.1", {
requires : []});
YUI().use('datatable-sort','datatable-filter',function(Y) {
// comment
//var modelList = new Y.ModelList();
var url = "file:///e:/Documents/json-search.txt";
var modelList, datasource;
modelList = new Y.ModelList();
datasource = Y.DataSource.IO({ source: "file:///e:/Documents/json-search.txt" });
modelList.plug(Y.Plugin.ModelListDataSource, {
source : datasource, });
datasource.sendRequest();
var dataTable = new Y.DataTable (
{
columns : [ {key:"name",label:"Person",renderFilter:true,filter:"Joe"},"company",{key:"state",renderFilter:true},{key:"cost",renderFilter:true}],
data : modelList, sortable : true, filters : 'auto'
}).render("#table");
modelList.item(1).set("id",102);
Y.one("#showhidefilters").on("click",function(e) {e.halt();Y.one("#table").one(".yui3-datatable-filters-row").toggleClass("yui3-datatable-filters-hidden");});
});

Related

Creating a Custom Data Adapter: Importing data adapter

Following the tutorial for creating a custom data adapter:
https://forge.autodesk.com/en/docs/dataviz/v1/developers_guide/advanced_topics/custom_data_adapter/
Getting error in chrome console:
Created file Hyperion.Data.BimapiDataAdapter in the folder forge-dataviz-iot-reference-app-main\node_modules\forge-dataviz-iot-data-modules\client\data based on the Hyperion.Data.Adapter file in the same folder. Then edited on line 371 and changed RestApiDataAdapter to BimapiDataAdapter.
Then trying to import this in BaseApp.jsx on line 34 in the folder forge-dataviz-iot-reference-app-main\node_modules\forge-dataviz-iot-react-components\client\components.
Your Hyperion.Data.BimapiDataAdapter.js is not placed aside forge-dataviz-iot-react-components/BaseApp.jsx, so the package-tool Webpack cannot it by ./Hyperion.Data.BimapiDataAdapter in BaseApp.jsx.
Here is my approach to exposing Hyperion.Data.BimapiDataAdapter.js.
Create Hyperion.Data.BimapiDataAdapter.js under forge-dataviz-iot-reference-app-main\node_modules\forge-dataviz-iot-data-modules\client\data. Here is how it looks like (just copied and pasted the contents of RestApiDataAdapter for the quick demo)
import { DataAdapter } from './Hyperion.Data';
/**
* Data adapter class dealing with sample data.
* #memberof Autodesk.DataVisualization.Data
* #alias Autodesk.DataVisualization.Data.BimapiDataAdapter
* #augments DataAdapter
*/
export class BimapiDataAdapter extends DataAdapter {
/**
* Constructs an instance of BimapiDataAdapter.
*/
constructor(provider = "synthetic", baseName = "") {
super("BimapiDataAdapter", baseName);
/* eslint-disable no-undef */
this._provider = provider;
}
/**
* Loads all DeviceModel objects from the sample REST API.
*
* #returns {Promise<DeviceModel[]>} A promise that resolves to a single
* dimensional array containing a list of loaded DeviceModel objects. If no
* DeviceModel is available, the promise resolves to an empty array.
* #memberof Autodesk.DataVisualization.Data
* #alias Autodesk.DataVisualization.Data.BimapiDataAdapter#loadDeviceModels
*/
async loadDeviceModels() {
const adapterId = this.id;
return fetch(this._getResourceUrl("api/device-models"))
.then((response) => response.json())
.then((rawDeviceModels) => {
/** #type {DeviceModel[]} */
const normalizedDeviceModels = [];
rawDeviceModels.forEach((rdm) => {
// Create a normalized device model representation.
const ndm = new DeviceModel(rdm.deviceModelId, adapterId);
ndm.name = rdm.deviceModelName;
ndm.description = rdm.deviceModelDesc;
// Generate device property representation.
rdm.deviceProperties.forEach((rdp) => {
const propId = rdp.propertyId;
const propName = rdp.propertyName;
const ndp = ndm.addProperty(propId, propName);
ndp.description = rdp.propertyDesc;
ndp.dataType = rdp.propertyType;
ndp.dataUnit = rdp.propertyUnit;
ndp.rangeMin = rdp.rangeMin ? rdp.rangeMin : undefined;
ndp.rangeMax = rdp.rangeMax ? rdp.rangeMax : undefined;
});
normalizedDeviceModels.push(ndm);
});
// Fetch actual devices for each of the device models.
return this.fetchDevicesForModels(normalizedDeviceModels);
});
}
/**
* Fetches actual device IDs and populate DeviceModel objects with them.
*
* #param {DeviceModel[]} deviceModels The DeviceModel objects for which
* actual device IDs are to be populated.
*
* #returns {Promise<DeviceModel[]>} A promise that resolves to the
* DeviceModel objects populated with actual device IDs.
* #memberof Autodesk.DataVisualization.Data
* #alias Autodesk.DataVisualization.Data.BimapiDataAdapter#fetchDevicesForModels
*/
async fetchDevicesForModels(deviceModels) {
const promises = deviceModels.map((deviceModel) => {
const model = deviceModel.id;
return fetch(this._getResourceUrl("api/devices", { model: model }))
.then((response) => response.json())
.then((jsonData) => jsonData.deviceInfo);
});
return Promise.all(promises).then((deviceInfosList) => {
// Assign devices to each device model.
deviceModels.forEach((deviceModel, index) => {
// Turn data provider specific device data format into
// the unified data format stored in Device object.
//
const deviceInfos = deviceInfosList[index];
deviceInfos.forEach((deviceInfo) => {
const device = deviceModel.addDevice(deviceInfo.id);
device.name = deviceInfo.name;
const p = deviceInfo.position;
device.position = new THREE.Vector3(
parseFloat(p.x),
parseFloat(p.y),
parseFloat(p.z)
);
device.lastActivityTime = deviceInfo.lastActivityTime;
device.deviceModel = deviceModel;
device.sensorTypes = deviceModel.propertyIds;
});
});
return deviceModels;
});
}
/**
* Fetches the property data based on the given device ID.
*
* #param {QueryParam} query Parameters of this query.
*
* #returns {Promise<DeviceData>} A promise that resolves to an aggregated
* property data for the queried device.
* #memberof Autodesk.DataVisualization.Data
* #alias Autodesk.DataVisualization.Data.BimapiDataAdapter#fetchDeviceData
*/
async fetchDeviceData(query) {
const pids = query.propertyIds;
const promises = pids.map((pid) => this._fetchPropertyData(query, pid));
return Promise.all(promises).then((deviceDataList) => {
const deviceData = new DeviceData(query.deviceId);
deviceDataList.forEach((devData) => deviceData.mergeFrom(devData));
return deviceData;
});
}
/**
* Fetches data for a single property based on the given device ID.
*
* #param {QueryParam} query Parameters of this query.
* #param {string} propertyId The ID of the property.
*
* #returns {Promise<DeviceData>} A promise that resolves to an aggregated
* property data for the queried device.
*/
async _fetchPropertyData(query, propertyId) {
const url = this._getResourceUrl("api/aggregates", {
device: query.deviceId,
property: propertyId,
startTime: query.dateTimeSpan.startSecond,
endTime: query.dateTimeSpan.endSecond,
resolution: query.dateTimeSpan.resolution,
});
return fetch(url)
.then((response) => response.json())
.then((rawAggregates) => {
// Convert 'rawAggregates' which is in the following format, into 'AggregatedValues'
//
// rawAggregates = {
// timestamps: number[],
// count: number[],
// min: number[],
// max: number[],
// avg: number[],
// sum: number[],
// stdDev: number[]
// }
//
const aggrValues = new AggregatedValues(query.dateTimeSpan);
aggrValues.tsValues = rawAggregates.timestamps;
aggrValues.countValues = rawAggregates.count;
aggrValues.maxValues = rawAggregates.max;
aggrValues.minValues = rawAggregates.min;
aggrValues.avgValues = rawAggregates.avg;
aggrValues.sumValues = rawAggregates.sum;
aggrValues.stdDevValues = rawAggregates.stdDev;
aggrValues.setDataRange("avgValues", getPaddedRange(aggrValues.avgValues));
const deviceData = new DeviceData(query.deviceId);
const propertyData = deviceData.getPropertyData(propertyId);
propertyData.setAggregatedValues(aggrValues);
return deviceData;
})
.catch((err) => {
console.error(err);
});
}
/**
* Gets the resource URL for a given endpoint with query parameters
*
* #param {string} endpoint The endpoint for the URL to generate
* #param {Object.<string, string>} parameters Key-value pairs of query parameters
*
* #returns {string} The string that represents the complete resource URL
* #private
*/
_getResourceUrl(endpoint, parameters) {
parameters = parameters || {};
parameters["provider"] = this._provider;
parameters["project"] = "unused";
const ps = Object.entries(parameters).map(([k, v]) => `${k}=${v}`);
return `${this._baseName}/${endpoint}?${ps.join("&")}`;
}
}
Expose the class BimapiDataAdapter from ``forge-dataviz-iot-reference-app-main\node_modules\forge-dataviz-iot-data-modules\client.js`
export * from "./client/data/Hyperion.Data";
export * from "./client/data/Hyperion.Data.BimapiDataAdapter"; //!<<< add this line
Import BimapiDataAdapter in forge-dataviz-iot-reference-app-main\node_modules\forge-dataviz-iot-react-components\client\components\BaseApp.jsx from where import { ... } from "forge-dataviz-iot-data-modules/client" is
import {
Session,
AzureDataAdapter,
RestApiDataAdapter,
DataView,
DateTimeSpan,
EventType,
DeviceProperty,
DeviceModel,
BimapiDataAdapter //!<<< here it is
} from "forge-dataviz-iot-data-modules/client";
Afterward, re-execute ENV=local npm run dev in your terminal console.
If you have further questions on how Webpack resolves packages, I would advise you to check these out:
https://webpack.js.org/concepts/module-resolution/
https://webpack.js.org/concepts/module-federation/

Fatal error: Non-abstract method NF_Handlers_FieldsetRepeater::isFieldsetData() must contain body in

Would really like some help! I tried removing the semicolon but still getting this error:
Fatal error: Non-abstract method NF_Handlers_FieldsetRepeater::isFieldsetData() must contain body in /home/warstdam/public_html/wp-content/plugins/ninja-forms/includes/Handlers/FieldsetRepeater.php on line 173
/**
* Determine if data matches fieldset repeater construct
*
* When given only a submission value without any meta data, check the
* construct of the value to asssert with some level of confidence that
* the value is from a fieldset repeater.
*
* Logic:
* - is submission empty? then NO, we don't assert is fieldset repeater data
* - can the array key be parsed as a fieldset repeater key? If not, then NO…
* - is each value an array with 'id' and 'value' keys,
* and the `id` matches the id of its parent? If not, then NO...
*
* If all the above conditions are met for every entry in the submission,
* we assert that the submission value is that of a fieldset repeater.
*
*
* #param array $submission
* #return boolean
*/
public function isFieldsetData(array $submission); bool
{
$return = true;
// If not array containing data, not fieldset repeater
if (empty($submission)) {
$return = false;
}
foreach($submission as $key=>$submissionValueArray){
$submissionReference = $this->parseFieldsetFieldReference($key);
if(-1===$submissionReference){
$return = false;
}
if(!isset($submissionValueArray['id'])
|| $key!==$submissionValueArray['id']
|| !isset($submissionValueArray['value'])){
$return = false;
}
}
Here is the end of the code
{
$return = [];
if (!is_array($fieldSubmissionValue)) {
return $return;
}
if(''!==$fieldId and []!== $fieldSettings){
$fieldsetLabelLookup = $this->getFieldsetLabels($fieldId, $fieldSettings);
$fieldsetTypeLookup = $this->getFieldsetTypes($fieldId,$fieldSettings);
}else{
$fieldsetLabelLookup = null;
$fieldsetTypeLookup = null;
}
// $completeFieldsetID is in format {fieldsetRepeaterFieldId}{fieldsetDelimiter}{fieldsetFieldId}{submissionIndexDelimiter}{submissionIndex}
foreach ($fieldSubmissionValue as $completeFieldsetId => $incomingValueArray) {
// value is expected to be keyed inside incoming value array
if (isset($incomingValueArray['value'])) {
$value = $incomingValueArray['value'];
} else {
$value = $incomingValueArray;
}
// attempt parsing of fielsetField; if any fail, exit as data is corrupt
$fieldsetWithSubmissionIndex = $this->parseFieldsetFieldReference($completeFieldsetId);
if (0 == $fieldsetWithSubmissionIndex['fieldsetFieldId']) {
return $return;
}
$parsedSubmissionIds = $this->parseSubmissionIndex($fieldsetWithSubmissionIndex['fieldsetFieldId']);
if (-1 === $parsedSubmissionIds['submissionIndex']) {
return $return;
}
$fieldsetFieldId = $parsedSubmissionIds['fieldsetFieldId'];
$submissionIndex = $parsedSubmissionIds['submissionIndex'];
$idKey = $fieldId . $this->fieldsetDelimiter . $fieldsetFieldId;
if(is_null($fieldsetTypeLookup)){
$fieldsetFieldType='';
}else{
$fieldsetFieldType = $fieldsetTypeLookup[$idKey];
}
if(is_null($fieldsetLabelLookup)){
$fieldsetFieldLabel='';
}else{
$fieldsetFieldLabel = $fieldsetLabelLookup[$idKey];
}
$array = [];
$array['value'] = $value;
$array['type'] = $fieldsetFieldType;
$array['label'] = $fieldsetFieldLabel;
$return[$submissionIndex][$fieldsetFieldId] = $array;
}
return $return;
}
}
Looks like a syntax error.
Change ; bool to : bool.
public function isFieldsetData(array $submission): bool

how to add AngularJS DHTML directive?

dhtml syntax help
this is the syntax used
I do not exhaust the complete dhtmlXGrid API here...
however configure and dataLoaded callbacks let user
add any additional configuration they desire
"use strict";
angular.module('dhxDirectives')
.directive('dhxGrid', function factory(DhxUtils) {
return {
restrict: 'E',
require: 'dhxGrid',
controller: function () {
},
scope: {
/**
* Grid will be accessible in controller via this scope entry
* after it's initialized.
* NOTE: For better design and testability you should use instead the
* configure and dataLoaded callbacks.
*/
dhxObj: '=',
/** Mandatory in current implementation! */
dhxMaxHeight: '=',
/** Optional. Default is 100%. */
dhxMaxWidth: '=',
/**
* Data is given here as an object. Not a filename! Must conform to the
* specified or default dataFormat
*/
dhxData: '=',
/**
* View possible formats here: http://docs.dhtmlx.com/grid__data_formats.html
* Currently supported:
* ['Basic JSON', 'Native JSON'] // 'Basic JSON' is default value
*/
dhxDataFormat: '=',
/** Optional! Recommended! http://docs.dhtmlx.com/api__dhtmlxgrid_setheader.html */
dhxHeader: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setcoltypes.html */
dhxColTypes: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setcolsorting.html */
dhxColSorting: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setcolalign.html */
dhxColAlign: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setinitwidthsp.html */
dhxInitWidths: '=',
/** Optional! http://docs.dhtmlx.com/api__dhtmlxgrid_setinitwidths.html */
dhxInitWidthsP: '=',
/**
* preLoad and postLoad callbacks to controller for additional
* customization power.
*/
dhxConfigureFunc: '=',
dhxOnDataLoaded: '=',
/**
* [{type: <handlerType>, handler: <handlerFunc>}]
* where type is 'onSomeEvent'
* Events can be seen at: http://docs.dhtmlx.com/api__refs__dhtmlxgrid_events.html
* Optional
*/
dhxHandlers: '=',
dhxVersionId: '=',
dhxContextMenu: '='
},
compile: function compile(/*tElement, tAttrs, transclude*/) {
return function (scope, element/*, attrs*/) {
var loadStructure = function () {
$(element).empty();
$('<div></div>').appendTo(element[0]);
var rootElem = element.children().first();
var width = scope.dhxMaxWidth ? (scope.dhxMaxWidth + 'px') : '100%';
var height = scope.dhxMaxHeight ? (scope.dhxMaxHeight + 'px') : '100%';
rootElem.css('width', width);
rootElem.css('height', height);
//noinspection JSPotentiallyInvalidConstructorUsage
if (scope.dhxObj) {
DhxUtils.dhxDestroy(scope.dhxObj);
}
scope.dhxObj = new dhtmlXGridObject(rootElem[0]);
var grid = scope.dhxObj;
grid.setImagePath(DhxUtils.getImagePath());
grid.enableAutoHeight(!!scope.dhxMaxHeight, scope.dhxMaxHeight, true);
grid.enableAutoWidth(!!scope.dhxMaxWidth, scope.dhxMaxWidth, true);
scope.dhxContextMenu ? grid.enableContextMenu(scope.dhxContextMenu) : '';
scope.$watch(
"dhxContextMenu",
function handle( newValue, oldValue ) {
grid.enableContextMenu(newValue);
}
);
scope.dhxHeader ? grid.setHeader(scope.dhxHeader): '';
scope.dhxColTypes ? grid.setColTypes(scope.dhxColTypes): '';
scope.dhxColSorting ? grid.setColSorting(scope.dhxColSorting): '';
scope.dhxColAlign ? grid.setColAlign(scope.dhxColAlign): '';
scope.dhxInitWidths ? grid.setInitWidths(scope.dhxInitWidths): '';
scope.dhxInitWidthsP ? grid.setInitWidthsP(scope.dhxInitWidthsP): '';
// Letting controller add configurations before data is parsed
if (scope.dhxConfigureFunc) {
scope.dhxConfigureFunc(grid);
}
grid.init();
// Finally parsing data
var dhxDataFormat = scope.dhxDataFormat || 'Basic JSON';
switch (dhxDataFormat) {
case 'Basic JSON':
grid.parse(scope.dhxData, 'json');
break;
case 'Native JSON':
grid.load(scope.dhxData, 'js');
break;
}
// Letting controller do data manipulation after data has been loaded
if (scope.dhxOnDataLoaded) {
scope.dhxOnDataLoaded(grid);
}
DhxUtils.attachDhxHandlers(grid, scope.dhxHandlers);
DhxUtils.dhxUnloadOnScopeDestroy(scope, grid);
};
scope.$watch('dhxVersionId', function (/*newVal, oldVal*/) {
console.log('rebuilding...');
loadStructure();
});
}
}
};
});
© 2020 GitHub, Inc.
I do not exhaust the complete dhtmlXGrid API here...
however configure and dataLoaded callbacks let user
add any additional configuration they desire
<dhx-grid
dhx-obj="grid.obj"
style="height: 100%"
dhx-data="gridData"
dhx-col-sorting="'str,str,int'"
dhx-header="'Title,Author,Copies sold'"
dhx-context-menu="contextMenu"
dhx-handlers="grid.handlers"></dhx-grid>
angular.module('myApp')
.controller('GridController', ['$scope' ,function ($scope) {
$scope.grid = {
obj: {},
handlers: [
{type: "onRowSelect", handler: function (id) {
$scope.grid.obj.deleteRow(id);
}}
]
};
$scope.alert = function alert(event_name) {
switch (event_name) {
case "refreshsize":
$scope.grid.obj.setSizes();
}
};
$scope.contextMenu = {};
$scope.gridData = {
rows:[
{ id:1, data: ["Click a row", "John Grasham", "100"]},
{ id:2, data: ["to have it", "Stephen Pink", "2000"]},
{ id:3, data: ["deleted", "Terry Brattchet", "3000"]},
{ id:4, data: ["La la la", "Isaac Zimov", "4000"]},
{ id:5, data: ["La la la", "Sax Pear", "5000"]}
]
};
}]);
"use strict";
/**
* Created by Emanuil on 01/02/2016.
*/
angular.module('dhxDirectives')
.factory('DhxUtils', [function () {
var _imgPath = "bower_components/dhtmlx/imgs/";
/**
* #param dhxObject
* #param dhxHandlers
*/
var attachDhxHandlers = function (dhxObject, dhxHandlers) {
(dhxHandlers || [])
.forEach(function (info) {
dhxObject.attachEvent(info.type, info.handler);
});
};
var getImagePath = function () {
return _imgPath;
};
var setImagePath = function (imgPath) {
_imgPath = imgPath;
};
/**
* I hope to never resort to using that
*/
var createCounter = function () {
var current = -1;
return function () {
current++;
return current;
};
};
var removeUndefinedProps = function(obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && obj[prop] === undefined) {
delete obj[prop];
}
}
};
var dhxDestroy = function (dhxObj) {
var destructorName =
'destructor' in dhxObj
? 'destructor'
:
('unload' in dhxObj
? 'unload'
: null);
if (destructorName === null) {
console.error('Dhtmlx object does not have a destructor or unload method! Failed to register with scope destructor!');
return;
}
dhxObj[destructorName]();
};
var dhxUnloadOnScopeDestroy = function (scope, dhxObj) {
var destructorName =
'destructor' in dhxObj
? 'destructor'
:
('unload' in dhxObj
? 'unload'
: null);
if (destructorName === null) {
console.error('Dhtmlx object does not have a destructor or unload method! Failed to register with scope destructor!');
return;
}
scope.$on(
"$destroy",
function (/*event*/) {
dhxObj[destructorName]();
}
);
};
return {
attachDhxHandlers: attachDhxHandlers,
getImagePath: getImagePath,
setImagePath: setImagePath,
createCounter: createCounter,
removeUndefinedProps: removeUndefinedProps,
dhxUnloadOnScopeDestroy: dhxUnloadOnScopeDestroy,
dhxDestroy: dhxDestroy
};
}]);

How do I use a class variable in the function() method?

Class Variable Name: addPointY
"addPointY" Using Function:
setInterval(function () {
var y = Math.round(Math.random() * 100);
series.addPoint(this.addPointY, true, true);
}, 3000);
I have to find a way to use it.
This is a customer requirement and has not been resolved.
Please tell me another way.
The class variable must be used in any of its methods.
But I could not get the class variable.
Do not you have a smart developer who solved the same problem?
#Injectable()
export class HighChartService implements ChartService {
private addPointY: number = 0;
shiftAddPoint(data: number) {
this.addPointY = data;
console.log(this.addPointY);
}
/**
* #see DynamicChart start function
* #param obj chart Object
* #param title Top Title
* #param type ChartType
* #param yAxisTitle Left Title
* #param series Chart data
* #author jskang
* #since 2017/10/12
*/
dynamicInitOptions(title: string, type: string, yAxisTitle: string, series: Object[]) {
if (!type) { type = "line"; }
let obj = new Chart({
chart: {
type: type,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var y = Math.round(Math.random() * 100);
series.addPoint(this.addPointY, true, true);
}, 3000);
}
}
},
title: { text: title },
xAxis: {
categories: [0,1,2,3,4,5,6],
labels: {
formatter: function () {
let xAxis = "";
if(this.value % 7 == 0){ xAxis = "일"; }
else if(this.value % 7 == 1){ xAxis = "월"; }
else if(this.value % 7 == 2){ xAxis = "화"; }
else if(this.value % 7 == 3){ xAxis = "수"; }
else if(this.value % 7 == 4){ xAxis = "목"; }
else if(this.value % 7 == 5){ xAxis = "금"; }
else if(this.value % 7 == 6){ xAxis = "토"; }
return xAxis;
}
}
},
yAxis: {
title: {
text: yAxisTitle
},
labels: {
formatter: function () {
return this.value;
}
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
series: series
});
return obj;
}
}
The this inside your callback function for setInterval does not point to the current class instance because when you use function () {} syntax it creates its own binding for this based on how it is called.
To fix this use arrow functions which preserves the context and you can access your class properties inside the callback:
load: () => { // Notice arrow function here
// set up the updating of the chart each second
var series = this.series[0];
setInterval(() => { // Notice arrow function here
var y = Math.round(Math.random() * 100);
series.addPoint(this.addPointY, true, true);
}, 3000);
}
Another way you can solve this is by using the that pattern where you capture your this where it points to your class instance and use it wherever you need to refer to your instance:
dynamicInitOptions(title: string, type: string, yAxisTitle: string, series: Object[]) {
if (!type) { type = "line"; }
let that = this; // Capture `this` here
let obj = new Chart({
chart: {
type: type,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var y = Math.round(Math.random() * 100);
series.addPoint(that.addPointY, true, true); // Use `that` instead of `this here
}, 3000);
}
}
}
// ...
});
}

return instance of database in javascript

Hi There best collegue,
i'm doing some experience with Object Oriented Javascript in combination with Mootools and creating a todolist for exercise. i've the following issue.
i've a class called database and looks as followd
var Database = new Class({
initialize:function(db){
this.db = db;
this.prepareDatabase();
this.createTable();
},
/*
* Creates the todo database
* #return {object Database}
* alDone ensures that the function will be called once, because we only want one database
* with the name 'Todo'
*/
prepareDatabase:function(){
var alDone = false;
if(!alDone){
var dbSize = 5 * 1024 * 1024; // 5MB
this.db = openDatabase("Todo", "1.0", "Todo manager", dbSize);
}else{
alDone = true;
}
},
/*
* Creates table 'todo'
* alDone ensures that the function will be called once, because we only want one table
* with the name 'todo'
*/
createTable:function(){
var alDone = false;
if(!alDone){
this.db.transaction(function(tx){
tx.executeSql("CREATE TABLE IF NOT EXISTS todo(ID INTEGER PRIMARY KEY ASC, title TEXT, description TEXT, isDone INTEGER, date DATETIME)", [])
});
}else{
alDone = true;
console.log("functie createTable is al aangeroepen");
}
},
});
and i've created a class todo. the goal I want to achieve is to create a instance of the db and call this in a method in the todolist class. I would be gratefull if someone can help me with this issue.
Tnx in advance.
my todolist class looks like below.
var Todo = new Class(
{
initialize: function(title,description,isDone,date){
this.title = title;
this.description = description;
this.isDone = isDone;
this.date = date;
},
getTitle:function()
{
return this.title;
},
getDescription:function()
{
return this.description;
},
getIsDone:function()
{
return this.isDone;
},
setIsDone:function(value)
{
this.isDone = value;
},
});
I did not understand what you are trying to do here but here is some errors you have:
In class Database you get db param in the constructor and set it to a class property name db: this.db = db; - Then you call prepareDatabase which override that this.db by setting it to openDatabase("Todo", "1.0", "Todo manager", dbSize); - so why sends the constructor db param if you override it in the next operation ?
you want the functions prepareDatabase and createTable will be called once so you set a variable alDone - but this variable is local to the function so in each call to one of this functions alDone will always be false and get executed - what I guess you want is set a class variable that each call to the function wil "remember" it's state so you can do something like this:
end List item (this is stackoverflow bug :))
prepareDatabase:function(){
if(!this.alDone){
this.alDone = true;
var dbSize = 5 * 1024 * 1024; // 5MB
this.db = openDatabase("Todo", "1.0", "Todo manager", dbSize);
}
},
Then again you can't call this.alDone twice so you need to change the name in the other function (createTable)
Continue:
If you want to make your db class "global" (the right term is static) then don't use mootools Class - use regular js objects: (you can use mootools inside of course)
var Database = {
init:function(db){
this.db = db;
this.prepareDatabase();
this.createTable();
},
prepareDatabase:function(){
if(!this.donePrepare){
this.donePrepare = true;
var dbSize = 5 * 1024 * 1024; // 5MB
this.db = openDatabase("Todo", "1.0", "Todo manager", dbSize);
}
},
createTable:function(){
if(!this.doneCreate){
this.doneCreate = true;
this.db.transaction(function(tx){
tx.executeSql("CREATE TABLE IF NOT EXISTS todo(ID INTEGER PRIMARY KEY ASC, title TEXT, description TEXT, isDone INTEGER, date DATETIME)", [])
});
}else{
console.log("functie createTable is al aangeroepen");
}
}
};
Then you can call it from everywhere like this:
Database.init();