Toggle navigation
Wialon Playground
Add library
jQuery latest
Bootstrap 3.3.1
Wialon Javascript SDK
Run
Get code
Fork
Save
Examples
Login
Get units
Change unit icon
Get messages
Get sensors
Edit sensors
Commands
Monitoring notification
Track layer
Get resources
Resources and accounts
Account parameters
Do payment
Management Driver
Create notification
Get geofences
Geofence parameters
Create geofence
Gurtam map
Units on map
Unit trace
Create report template
Execute report
Execute custom report
Create driver
Bind driver to unit
Unit edit fields
Import fillings
Token login for site
Advanced authorization form
Token usage in app
Account hierarchy
Nearest units
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Wialon Playground — Account Tree</title> <script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script> <script type="text/javascript" src="https://hst-api.wialon.host/wsdk/script/wialon.js"></script> </head> <body> <div id='tree-view'></div> <hr> <div id='log'></div> </body> </html>
HTML
p { margin: 0; padding: 0; } #tree-view p > span { cursor: pointer; } #tree-view .tree-view-not-expandable > p > span { cursor: auto; } #tree-view .tree-view-expandable { margin-bottom: 0.3em; }
CSS
/* * Visualize account hierarchy via account_tree dynamic report * * Implementation: * * 1. Load library 'resourceReports' by: * * var session = wialon.core.Session.getInstance(); * session.loadLibrary('resourceReports'); * * 2. Subscribe for resource list with billing properties: * * var resourceFlags = wialon.item.Item.dataFlag.base | wialon.item.Resource.dataFlag.billingProps; * * session.updateDataFlags([ * {type: 'type', data: 'avl_resource', flags: resourceFlags, mode: 0} * ], callback); * * 3. After receiving resources, filter them to get only such resources that is accounts: * * resources = resources.filter(function(resource) { * return resource.getAccountId() === resource.getId(); * }); * * Accounts have same id and accountId. * * 4. Exec dynamic report on some of that resources with the resource id as object id: * * resource.execReport( * template, // JSON of dynamic report template * resource.getId(), * 0, // secondary id, must be 0 * {from: 0, to: 0, flags: 0}, // interval, not needed for account_tree table * callback * ); * * 5. Call .selectRows on received report to get rows. API format: * * https://sdk.wialon.host/wiki/en/kit/remoteapi/apiref/report/select_result_rows */ // Token that will be used for auth // For more info about how to generate token check // http://sdk.wialon.host/playground/demo/app_auth_token var TOKEN = '5dce19710a5e26ab8b7b8986cb3c49e58C291791B7F0A7AEB8AFBFCEED7DC03BC48FF5F8'; // GUI component var treeView; // Print message to log function msg(text) { $("#log").prepend(text + "<br/>"); } // will be called after DOM is ready and we are successfully logged in function init() { var session = wialon.core.Session.getInstance(); session.loadLibrary('resourceReports'); // for reports var resourceFlags = wialon.item.Item.dataFlag.base | // required wialon.item.Item.dataFlag.billingProps; // to receive accountId session.updateDataFlags([ // request resources list {type: 'type', data: 'avl_resource', flags: resourceFlags , mode: 0} ], onResourcesLoad); function onResourcesLoad(error) { if (error) { msg(wialon.core.Errors.getErrorText(error)); return; } var resources = session.getItems('avl_resource'); // get only accounts resources = resources.filter(function(resource) { // if accountId = resourceId, then it is an account return resource.getAccountId() === resource.getId(); }); if (resources.length === 0) { msg('No accounts'); return; } var resource = null; resources.some(function(x) { // select resource associated with current account if (x.getId() === session.getCurrUser().getAccountId()) { resource = x; return true; } }); if (resource === null) { // impossible, but pick some resource = resources[0]; } // request of execution of dynamic report resource.execReport({ // dynamic report id: 0, // some name n: 'some', // type of object ct: 'avl_resource', // report parameters p: '', tbl: [{ // id of table n: "account_tree", // table label l: 'Account tree', // columns c: "type,name", // column names cl: "Type,Name", // statistics table columns/column names s: "", sl: "", // table parameters, described at https://sdk.wialon.host/wiki/en/sidebar/remoteapi/apiref/report/update_report // if we pass "group":"0" here, we will get plain list of type-object, and with grouping we will get tree p: '{"account_tree":{"types":"avl_account,avl_resource,user,avl_unit,avl_unit_group,avl_retranslator,avl_route","group":"1"}}', // for charts, we have no charts sch: { f1: 0, f2: 0, t1: 0, t2: 0, m: 0, y: 0, w: 0 }, // table flags, described at https://sdk.wialon.host/wiki/en/sidebar/remoteapi/apiref/report/exec_report f: 0 }] }, resource.getId(), // Object id, in our case it is resource id 0, // secondary id (for example, driver id, but we don't need this now) {from: 0, to: 0, flags: 0}, // time interval, possible flags can be viewed at https://sdk.wialon.host/wiki/en/kit/remoteapi/apiref/report/exec_report // for account_tree interval is ignored onReportResult); } } // callback for resource.execReport function onReportResult(error, report) { if (error) { msg(wialon.core.Errors.getErrorText(error)); return; } // we have only one table, so get first var accountTreeTable = report.getTables()[0]; // select rows of first level of nesting // first parameter is table id, second — config, format can be viewed at https://sdk.wialon.host/wiki/en/kit/remoteapi/apiref/report/select_result_rows report.selectRows(0, { type: 'range', data: { from: 0, to: accountTreeTable.rows - 1, // inclusive level: 0 } }, function(error, rows) { if (error) { msg(wialon.core.Errors.getErrorText(error)); return; } // add result to the or tree view addRows(report, treeView, rows, []); }); } // recursive function, that gives item, result rows, level of nesting, // creates nodes from result, binding event listeners to load next data and so on function addRows(report, item, rows, path) { // hide GUI `loading...` label item.loaded(); rows.forEach(function(rowData, i) { // get object name or type, if no name (result have no name if there is level of nesting) var text = rowData.c[1]; if (text === '') text = rowData.c[0]; // d parameter contains level of child items, that can be retrieved by report/select_result_rows var isExpandable = rowData.d > 0, collapsedText, expandedText; // GUI stuff to show indicator of collapsed/expanded item and number of children if (isExpandable) { text += ' <span style="color: gray">(' + rowData.d + ')</span>'; collapsedText = '<span style="font-family: monospace"><b>[+]</b></span></b> ' + text; expandedText = '<span style="font-family: monospace"><b>[-]</b></span> ' + text; text = collapsedText; } // add new item var treeViewItem = item.addItem({ html: text, // adds specific CSS classes/toggles onclick event isExpandable: rowData.d > 0, // function that will be called at first expanding, if isExpandable, must call item.loaded(), when finished onFirstExpand: function() { // go to next nesting level var newPath = path.concat(i); // request new rows, when successfully done — add them to the tree doSelectSubRows(report, newPath, function(rows) { addRows(report, treeViewItem, rows, newPath); }); }, onCollapse: function() { treeViewItem.setHtml(collapsedText); }, onExpand: function() { treeViewItem.setHtml(expandedText); } }); }); } // just sugar to request nested report rows function doSelectSubRows(report, path, callback) { // format: https://sdk.wialon.host/wiki/en/kit/remoteapi/apiref/report/select_result_rows report.selectRows(0, { type: 'row', data: { rows: path, level: 0 } }, function(error, rows) { if (error) { msg(wialon.core.Errors.getErrorText(error)); return; } callback(rows); }); } // GUI component for visualization of tree and handling lazy loading function TreeView(options) { var self = this; var rootEl = options.rootEl; /* * addItem(parent:Item - optional, { * html: String, * * isExpandable: Boolean, * * onFirstExpand: Function, * * onCollapse: Function, * onExpand: Function * }):Item */ this.addItem = function(parentItem, options) { // if no options — function was called with 1 argument, add to root node if (!options) return this.addItem(null, parentItem); // create item element DOM structure var el = $('<div class="tree-view-el">'), elP = $('<p>'), elSpan = $('<span>'), elChildren = $('<div>'); el.append(elP.append(elSpan.html(options.html))); el.append(elChildren); // add CSS classes if (options.isExpandable === true) { el.addClass('tree-view-expandable'); } else if (options.isExpandable === false) { el.addClass('tree-view-not-expandable'); } // add element to parent item or to the root if (parentItem) { parentItem.elChildren.append(el); el.css('margin-left', '1em'); } else { // addition to the root rootEl.append(el); } var shown = false, // undefined if not clicked, null if already loaded loadingEl = undefined; // if expandable, handle `click` event options.isExpandable && elSpan.click(function(event) { // stop propagation to prevent click handling in parent elements event.stopPropagation(); // prevent subsequent clicks if (loadingEl) return; if (shown) { // collapse elChildren.hide(); // fire event options.onCollapse(); shown = false; } else { // expand if (loadingEl === undefined) { // indicate loading process loadingEl = $('<p>').text('Loading...') loadingEl.css('margin-left', '1em'); el.append(loadingEl); // fire event options.onFirstExpand(); } elChildren.show(); // fire event options.onExpand(); shown = true; } }); // item api return { // internal elChildren: elChildren, // public methods loaded: function() { // hide loading label if (loadingEl) { loadingEl.remove(); loadingEl = null; } }, setHtml: function(html) { elSpan.html(html); }, addItem: function(options) { // add child item to the current return self.addItem(this, options); } }; }; // to unify root node api with child items api this.loaded = function() {}; } // execute when DOM is ready $(document).ready(function () { // create tree view component treeView = new TreeView({ rootEl: $('#tree-view') }); // init session wialon.core.Session.getInstance().initSession("https://hst-api.wialon.host"); // For more info about how to generate token check // http://sdk.wialon.host/playground/demo/app_auth_token // try to login wialon.core.Session.getInstance().loginToken(TOKEN, "", function (code) { // login callback // if error code - print error message if (code){ msg(wialon.core.Errors.getErrorText(code)); return; } msg("Logged successfully"); // when login suceed then run init() function init(); }); });
JS
Result
Source code of example
Close ✕
×
Source code