how to change highcarts sunburst slice/level without clicking levels - javascript

I have a Sunburst Highcharts in my project. I was wondering if it is possible to change the level without clicking on them.
for example, I have a sunburst like this which has 4 levels.
var data = [{
id: '0.0',
parent: '',
name: 'The World'
}, {
id: '1.3',
parent: '0.0',
name: 'Asia'
}, {
id: '1.1',
parent: '0.0',
name: 'Africa'
}, {
id: '1.2',
parent: '0.0',
name: 'America'
}, {
id: '1.4',
parent: '0.0',
name: 'Europe'
}, {
id: '1.5',
parent: '0.0',
name: 'Oceanic'
},
/* Africa */
{
id: '2.1',
parent: '1.1',
name: 'Eastern Africa'
},
{
id: '3.1',
parent: '2.1',
name: 'Ethiopia',
value: 104957438
}, {
id: '3.2',
parent: '2.1',
name: 'Tanzania',
value: 57310019
}, {
id: '3.3',
parent: '2.1',
name: 'Kenya',
value: 49699862
}, {
id: '3.4',
parent: '2.1',
name: 'Uganda',
value: 42862958
}, {
id: '3.5',
parent: '2.1',
name: 'Mozambique',
value: 29668834
}, {
id: '3.6',
parent: '2.1',
name: 'Madagascar',
value: 25570895
}, {
id: '3.226',
parent: '2.22',
name: 'Samoa',
value: 196440
}, {
id: '3.227',
parent: '2.22',
name: 'Tonga',
value: 108020
}, {
id: '3.228',
parent: '2.22',
name: 'American Samoa',
value: 55641
}, {
id: '3.229',
parent: '2.22',
name: 'Cook Islands',
value: 17380
}, {
id: '3.230',
parent: '2.22',
name: 'Wallis and Futuna',
value: 11773
}, {
id: '3.231',
parent: '2.22',
name: 'Tuvalu',
value: 11192
}, {
id: '3.232',
parent: '2.22',
name: 'Niue',
value: 1618
}, {
id: '3.233',
parent: '2.22',
name: 'Tokelau',
value: 1300
}];
// Splice in transparent for the center circle
Highcharts.getOptions().colors.splice(0, 0, 'transparent');
Highcharts.chart('container', {
chart: {
height: '100%'
},
title: {
text: 'World population 2017'
},
subtitle: {
text: 'Source <href="https://en.wikipedia.org/wiki/List_of_countries_by_population_(United_Nations)">Wikipedia</a>'
},
series: [{
type: "sunburst",
data: data,
allowDrillToNode: true,
cursor: 'pointer',
dataLabels: {
format: '{point.name}',
filter: {
property: 'innerArcLength',
operator: '>',
value: 16
}
},
levels: [{
level: 1,
levelIsConstant: false,
dataLabels: {
filter: {
property: 'outerArcLength',
operator: '>',
value: 64
}
}
}, {
level: 2,
colorByPoint: true
},
{
level: 3,
colorVariation: {
key: 'brightness',
to: -0.5
}
}, {
level: 4,
colorVariation: {
key: 'brightness',
to: 0.5
}
}]
}],
tooltip: {
headerFormat: "",
pointFormat: 'The population of <b>{point.name}</b> is <b>{point.value}</b>'
}
});
Problem is
I want to go to specific levels without clicking on sunburst. for example, I create a button that if the user clicks on it, will do the same action as if I was clicking on Eastern Africa level of my sunburst.
<button onclick="clickOnEasternAfrica()">Do click here</button>
What code should I use for clickOnEasternAfrica() method!?

You can use fireEvent to trigge a click event:
document.getElementById('easternAfrica').addEventListener('click', function(){
var series = chart.series[0];
Highcharts.fireEvent(series, 'click', { point: series.points[6] });
});
Live demo: https://jsfiddle.net/BlackLabel/dLb5hert/
API Reference: https://api.highcharts.com/class-reference/Highcharts#.fireEvent%3CT%3E

Related

How do you set tooltip labels for multiple series using Apache Echarts?

I'm trying to generate a line chart that uses date for the x-axis and two different y-axis. I have it mostly working, but I can't get the tooltip to display the label properly for the second line.
To see this, go to the ECharts Demo Editor and enter the following code:
option = {
xAxis: {
type: 'time'
},
yAxis: [
{
type: 'value'
},
{
type: 'value'
}
],
dataset: {
source: [
{ date: '2020-01-24', orders: 4, sales: 250 },
{ date: '2020-01-25', orders: 3, sales: 250 },
{ date: '2020-01-26', orders: 2, sales: 375 },
{ date: '2020-01-27', orders: 2, sales: 380 },
{ date: '2020-01-28', orders: 4, sales: 325 },
{ date: '2020-01-29', orders: 5, sales: 375 },
{ date: '2020-01-30', orders: 6, sales: 500 },
{ date: '2020-01-31', orders: 4, sales: 425 },
{ date: '2020-02-01', orders: 2, sales: 280 },
{ date: '2020-02-03', orders: 3, sales: 580 },
{ date: '2020-02-04', orders: 4, sales: 250 },
{ date: '2020-02-05', orders: 4, sales: 350 }
]
},
series: [
{
type: 'line',
yAxisIndex: 0,
dimensions: [
{
type: 'time',
name: 'date',
displayName: ''
},
{
type: 'float',
name: 'orders',
displayName: 'Orders'
}
]
},
{
type: 'line',
yAxisIndex: 1,
dimensions:[
{
type: 'time',
name: 'date',
displayName: ''
},
{
type: 'int',
name: 'sales',
displayName: 'Sales'
}
]
}
],
tooltip: {
trigger: 'axis'
}
};
As you can see, the lines render correctly, as do both y axes, but the label for the second series (green line) is empty rather than Sales. However, if I delete the first series from the array, Sales becomes the blue line and the label works correctly in the tooltip, so there seems to be something I'm missing when using multiple series.
I suspect the fix for this is quite simple and obvious, but I've spent a fair amount of time on it and haven't had any luck. Any help would be greatly appreciated.
Give name to series instead of displayName to dimension.
series: [
{
type: 'line',
yAxisIndex: 0,
name:'Orders', // Here
dimensions: [
{
type: 'time',
name: 'date'
},
{
type: 'float',
name: 'orders'
}
]
},
{
type: 'line',
yAxisIndex: 1,
name:'Sales', // Here
dimensions:[
{
type: 'time',
name: 'date'
},
{
type: 'int',
name: 'sales'
}
]
}
]

Highcharts drill down to detailed graph

I would like to create a drill-down highchart.
You can find the jsfiddle link which is not working but the sample data is in it.
data: [{
name: '6',
y: 14
}, {
name: '7',
y: 19
}, ...
}]
},
{
name: 'B1',
data: [{
name: '6',
y: 14
}, {
name: '7',
y: 19
}, ...
},
{
name: 'C1',
data: [{
name: '6',
y: 14
}, {
name: '7',
y: 19
}, ...
}
]
The vice versa is running here:
datanormal = [{
name: '6',
data: [{
name: 'A1',
y: 14,
drilldown: 'Details1'
}, {
name: 'B1',
y: 19,
drilldown: 'Details1'
}, {
name: 'C1',
y: 21,
drilldown: 'Details1'
}]
},
{
name: '7',
data: [{
name: 'A1',
y: 5,
drilldown: 'Details1'
} ...]
}];
datadrill =
[{
id: 'Details1',
name: 'Details1',
data: [
['D1', 4],
['D2', 2],
['D3', 1],
['D4', 4]
]
}];
I need the opposite, from the basic to complex.
This is the main column chart image
This is the detailed drill-down chart image
If you look fot the working example there is another object for the datadrill:
datadrill =
[{
id: 'Details1',
name: 'Details1',
data: [
['D1', 4],
['D2', 2],
['D3', 1],
['D4', 4]
]
}]
You need to do the same on your code.
Could you check this? Is that what you want?
This is jsfiddle link => https://jsfiddle.net/burakkp/ytkqzfos/2/
$(document).ready(function() {
var datadrill;
datadrill = [{
name: 'A1',
data: [{
name: '6',
y: 14
}, {
name: '7',
y: 19
}, {
name: '8',
y: 21
}, {
name: '9',
y: 34
}, {
name: '10',
y: 5
}, {
name: '11',
y: 9
}]
},
{
name: 'B1',
data: [{
name: '6',
y: 14
}, {
name: '7',
y: 19
}, {
name: '8',
y: 21
}, {
name: '9',
y: 34
}, {
name: '10',
y: 5
}, {
name: '11',
y: 9
}]
},
{
name: 'C1',
data: [{
name: '6',
y: 14
}, {
name: '7',
y: 19
}, {
name: '8',
y: 21
}, {
name: '9',
y: 34
}, {
name: '10',
y: 5
}, {
name: '11',
y: 9
}]
}];
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Highcharts multi-series drilldown'
},
subtitle: {
text: 'The <em>allowPointDrilldown</em> option makes point clicks drill to the whole category'
},
xAxis: {
type: 'category'
},
plotOptions: {
series: {
borderWidth: 0,
dataLabels: {
enabled: true
}
}
},
series: datadrill
});
});
Would you like to achieve something like this? Please test the drilldown only for the first point (A1).
Demo: https://jsfiddle.net/BlackLabel/wn65fkxj/
I did some changes in your data, like:
datadrill = [{
id: 'Details1',
name: 'A1',
data: [{
name: '6',
y: 14
}, {
name: '7',
y: 19
}, {
name: '8',
y: 21
}, {
name: '9',
y: 34
}, {
name: '10',
y: 5
}, {
name: '11',
y: 9
}]
},
{
id: 'Details2',
name: 'B1',
data: [{
name: '6',
y: 14
}, {
name: '7',
y: 19
}, {
name: '8',
y: 21
}, {
name: '9',
y: 34
}, {
name: '10',
y: 5
}, {
name: '11',
y: 9
}]
},
{
id: 'Details3',
name: 'C1',
data: [{
name: '6',
y: 14
}, {
name: '7',
y: 19
}, {
name: '8',
y: 21
}, {
name: '9',
y: 34
}, {
name: '10',
y: 5
}, {
name: '11',
y: 9
}]
}
];
Also, I added null points to trigger different drilldown to each.
API: https://api.highcharts.com/highcharts/drilldown.allowPointDrilldown

I can't get cytoscape.js to display my chart at all

I built a chart in web webpage using the JavaScript chart program cytoscape.js. It does not display anything at all. But it doesn't' give syntax errors either, other than a warning about taking over the mouse for zooming purposes.
Here is the code:
<style type="text/css">
#cy {
width: 90%;
height: 300px;
display: block;
}
</style>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.14.0/cytoscape.min.js"></script>
<script type="text/javascript">
var cy = cytoscape({
container: document.getElementById('cy'), // container to render in
style: [ // the stylesheet for the graph
{
selector: 'node',
style: {
'background-color': '#666',
'label': 'data(id)'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle'
}
}
],
// initial viewport state:
zoom: 1,
pan: { x: 0, y: 0 },
// interaction options:
minZoom: 1e-50,
maxZoom: 1e50,
zoomingEnabled: true,
userZoomingEnabled: true,
panningEnabled: true,
userPanningEnabled: true,
boxSelectionEnabled: true,
selectionType: 'single',
touchTapThreshold: 8,
desktopTapThreshold: 4,
autolock: false,
autoungrabify: false,
autounselectify: false,
// rendering options:
headless: false,
styleEnabled: true,
hideEdgesOnViewport: false,
textureOnViewport: false,
motionBlur: false,
motionBlurOpacity: 0.2,
wheelSensitivity: 1,
pixelRatio: 'auto'
});
let options = {
name: 'breadthfirst',
fit: true, // whether to fit the viewport to the graph
directed: false, // whether the tree is directed downwards (or edges can point in any direction if false)
padding: 30, // padding on fit
circle: false, // put depths in concentric circles if true, put depths top down if false
grid: false, // whether to create an even grid into which the DAG is placed (circle:false only)
spacingFactor: 1.75, // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap)
boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space
nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm
roots: undefined, // the roots of the trees
maximal: false, // whether to shift nodes down their natural BFS depths in order to avoid upwards edges (DAGS only)
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled,
animateFilter: function (node, i) { return true; }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready: undefined, // callback on layoutready
stop: undefined, // callback on layoutstop
transform: function (node, position) { return position; } // transform a given node position. Useful for changing flow direction in discrete layouts
};
cy.layout(options);
var eles1 = cy.add([
{ group: 'nodes', data: { id: 'E1'} },
{ group: 'nodes', data: { id: 'E2'} },
{ group: 'nodes', data: { id: 'E3'} },
{ group: 'nodes', data: { id: 'E4'} },
{ group: 'nodes', data: { id: 'E5'} },
{ group: 'nodes', data: { id: 'E6'} },
{ group: 'nodes', data: { id: 'E7'} },
{ group: 'nodes', data: { id: 'E8'} } ]);
var eles2 = cy.add([
{ group: 'nodes', data: { id: 'LH1'} },
{ group: 'nodes', data: { id: 'RH1'} },
{ group: 'nodes', data: { id: 'LH2'} },
{ group: 'nodes', data: { id: 'LH3'} },
{ group: 'nodes', data: { id: 'RH2'} },
{ group: 'nodes', data: { id: 'LH4'} },
{ group: 'nodes', data: { id: 'RH3'} },
{ group: 'nodes', data: { id: 'RH4'} } ]);
var eles4 = cy.add([
{ group: 'edges', data: { id: 'edge0', source: 'E4', target: 'E5' } },
{ group: 'edges', data: { id: 'edge1', source: 'E6', target: 'E7' } },
{ group: 'edges', data: { id: 'edge2', source: 'LH1', target: 'E1' } },
{ group: 'edges', data: { id: 'edge3', source: 'LH1', target: 'RH1' } },
{ group: 'edges', data: { id: 'edge4', source: 'LH2', target: 'E4' } },
{ group: 'edges', data: { id: 'edge5', source: 'LH3', target: 'E4' } },
{ group: 'edges', data: { id: 'edge6', source: 'LH4', target: 'E6' } },
{ group: 'edges', data: { id: 'edge7', source: 'RH1', target: 'E2' } },
{ group: 'edges', data: { id: 'edge8', source: 'RH1', target: 'E3' } },
{ group: 'edges', data: { id: 'edge9', source: 'RH2', target: 'E5' } },
{ group: 'edges', data: { id: 'edge10', source: 'RH3', target: 'E7' } },
{ group: 'edges', data: { id: 'edge11', source: 'RH4', target: 'E8' } } ]);
</script>
<center>
<div id="cy" >
</div>
</center>
My code is actually generated in an asp.net page, but that should not make a difference.
You are adding the elements to the graph after the layout has been run. That's why all your nodes are piled up on the upper left corner.
You have two choices here:
Supply both the layout at the elements on the constructor.
Initialize the graph first, then add the elements (e.g. using cy.json()) and then tell cytoscape to run the layout with cy.layout(...).run().
Documentation for cy.layout() is here, and for cy.json() here.
The following snippet uses the first approach, but I have left the second one commented in case you cannot supply the elements on the constructor call (i.e. if you have to fetch them asynchronously).
var nodeArray = [
{ group: 'nodes', data: { id: 'E1'} },
{ group: 'nodes', data: { id: 'E2'} },
{ group: 'nodes', data: { id: 'E3'} },
{ group: 'nodes', data: { id: 'E4'} },
{ group: 'nodes', data: { id: 'E5'} },
{ group: 'nodes', data: { id: 'E6'} },
{ group: 'nodes', data: { id: 'E7'} },
{ group: 'nodes', data: { id: 'E8'} },
{ group: 'nodes', data: { id: 'LH1'} },
{ group: 'nodes', data: { id: 'RH1'} },
{ group: 'nodes', data: { id: 'LH2'} },
{ group: 'nodes', data: { id: 'LH3'} },
{ group: 'nodes', data: { id: 'RH2'} },
{ group: 'nodes', data: { id: 'LH4'} },
{ group: 'nodes', data: { id: 'RH3'} },
{ group: 'nodes', data: { id: 'RH4'} }
];
var edgeArray = [
{ group: 'edges', data: { id: 'edge0', source: 'E4', target: 'E5' } },
{ group: 'edges', data: { id: 'edge1', source: 'E6', target: 'E7' } },
{ group: 'edges', data: { id: 'edge2', source: 'LH1', target: 'E1' } },
{ group: 'edges', data: { id: 'edge3', source: 'LH1', target: 'RH1' } },
{ group: 'edges', data: { id: 'edge4', source: 'LH2', target: 'E4' } },
{ group: 'edges', data: { id: 'edge5', source: 'LH3', target: 'E4' } },
{ group: 'edges', data: { id: 'edge6', source: 'LH4', target: 'E6' } },
{ group: 'edges', data: { id: 'edge7', source: 'RH1', target: 'E2' } },
{ group: 'edges', data: { id: 'edge8', source: 'RH1', target: 'E3' } },
{ group: 'edges', data: { id: 'edge9', source: 'RH2', target: 'E5' } },
{ group: 'edges', data: { id: 'edge10', source: 'RH3', target: 'E7' } },
{ group: 'edges', data: { id: 'edge11', source: 'RH4', target: 'E8' } }
];
var stylesArray = [{
selector: 'node',
style: {
'background-color': '#666',
'label': 'data(id)'
}
},{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle'
}
}];
var layout = {name: 'breadthfirst'};
// You used mostly default options, there's no need to redefine them
var cy = cytoscape({
container: document.getElementById('cy'),
style: stylesArray,
// If you want to apply the layout on the constructor
// you must supply the elements too
layout: layout,
elements: {
nodes: nodeArray,
edges: edgeArray
}
});
// Or add the elements afterwards, it's your choice
// But then you need to re-run the layout
/*
cy.json({
elements: {
nodes: nodeArray,
edges: edgeArray
}
});
// Tell cytoscape to apply the layout when ready
cy.ready(function () {
cy.layout(layout).run();
});
*/
#cy {
width: 90%;
height: 300px;
display: block;
}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.14.0/cytoscape.min.js"></script>
<div id="cy"></div>

How to update value of nested array of objects

This is my actual array :
let mainArray= [
{
value: '/AG_TURF-123',
label: 'Ag & Turf',
checked: false,
id:123,
children: [
{
value: '/AG_TURF-123/TRACTOR-456',
label: 'Tractors',
checked: false,
id:456,
children: [
{
value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series',
label: 'Large (7, 8, 9) Series',
checked: false,
id:789,
children: [{
value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor',
label: '7 Family Tractor',
checked: false,
id:101112
},{
value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor',
label: '8 Family Tractor',
checked: false,
id:131415
},{
value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor',
label: '9 Family Tractor',
checked: false,
id:161718
}],
},
{
value: '/app/Http/routes.js',
label: 'routes.js',
checked: false,
id:181920
},
],
},
{
value: '/app/Providers',
label: 'Providers',
checked: false,
id:212223,
children: [{
value: '/app/Http/Providers/EventServiceProvider.js',
label: 'EventServiceProvider.js',
checked: false,
id:242526
}],
},
],
},
{
value: '/config',
label: 'config',
checked: false,
id:272829,
children: [
{
value: '/config/app.js',
label: 'app.js',
checked: false,
id:303132
},
{
value: '/config/database.js',
label: 'database.js',
checked: false,
id:333435
},
],
},
{
value: '/public',
label: 'public',
checked: false,
id:353637,
children: [
{
value: '/public/assets/',
label: 'assets',
checked: false,
id:383940,
children: [{
value: '/public/assets/style.css',
label: 'style.css',checked: false,
id:404142
}],
},
{
value: '/public/index.html',
label: 'index.html',
checked: false,
id: 434445
},
],
},
{
value: '/.env',
label: '.env',
checked: false,
id: 464748
},
{
value: '/.gitignore',
label: '.gitignore',
checked: false,
id: 495051
},
{
value: '/README.md',
label: 'README.md',
checked: false,
id: 525354
},
];
This is my list of value :
const ids=[525354,123,131415];
I want to set checked to true if id matched.
My main array may go to 6 to 7 step deep.
What I've done till yet :
setCheckedFlagToItems(checkList, items) {
return items.map((item) => {
const node = item;
if (checkList.indexOf(node.id) !== -1) {
node.checked = true;
}
if ((node.children) && (Array.isArray(node.children) && node.children.length > 0)) {
this.setCheckedFlagToItems(checkList, node.children);
}
return node;
}, this);
}
But it not working as usual.
You could use an iterative and recursice approach with a named function as callback for Array#forEach.
let mainArray = [
{
value: '/AG_TURF-123',
label: 'Ag & Turf',
checked: false,
id: 123,
children: [
{
value: '/AG_TURF-123/TRACTOR-456',
label: 'Tractors',
checked: false,
id: 456,
children: [
{
value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series',
label: 'Large (7, 8, 9) Series',
checked: false,
id: 789,
children: [
{
value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor',
label: '7 Family Tractor',
checked: false,
id: 101112
},
{
value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor',
label: '8 Family Tractor',
checked: false,
id: 131415
},
{
value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor',
label: '9 Family Tractor',
checked: false,
id: 161718
}
]
},
{
value: '/app/Http/routes.js',
label: 'routes.js',
checked: false,
id: 181920
}
]
},
{
value: '/app/Providers',
label: 'Providers',
checked: false,
id: 212223,
children: [
{
value: '/app/Http/Providers/EventServiceProvider.js',
label: 'EventServiceProvider.js',
checked: false,
id: 242526
}
]
}
]
},
{
value: '/config',
label: 'config',
checked: false,
id: 272829,
children: [
{
value: '/config/app.js',
label: 'app.js',
checked: false,
id: 303132
},
{
value: '/config/database.js',
label: 'database.js',
checked: false,
id: 333435
}
]
},
{
value: '/public',
label: 'public',
checked: false,
id: 353637,
children: [
{
value: '/public/assets/',
label: 'assets',
checked: false,
id: 383940,
children: [
{
value: '/public/assets/style.css',
label: 'style.css',
checked: false,
id: 404142
}
]
},
{
value: '/public/index.html',
label: 'index.html',
checked: false,
id: 434445
}
]
},
{
value: '/.env',
label: '.env',
checked: false,
id: 464748
},
{
value: '/.gitignore',
label: '.gitignore',
checked: false,
id: 495051
},
{
value: '/README.md',
label: 'README.md',
checked: false,
id: 525354
}
],
ids = [525354, 123, 131415];
mainArray
.forEach(
function iter(a) {
if (ids.includes(a.id)) {
a.checked = true;
}
Array.isArray(a.children) && a.children.forEach(iter);
}
);
console.log(mainArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If your ids are "unique" (there's only one unique object for each id property), you could also split this action in to two steps:
Make a new data structure that flattens all items in to one object of id: item
Loop through the ids to retrieve the items from this object.
If you find yourself looking up many objects by id, it might be easier to create this interim representation.
The creation of the map uses recursion similar to the other answer: whenever an item contains a children array, it adds those to the map object before it returns.
const mainArray = [{ value: '/AG_TURF-123', label: 'Ag & Turf', checked: false, id: 123, children: [{ value: '/AG_TURF-123/TRACTOR-456', label: 'Tractors', checked: false, id: 456, children: [{ value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series', label: 'Large (7, 8, 9) Series', checked: false, id: 789, children: [{ value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor', label: '7 Family Tractor', checked: false, id: 101112 }, { value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor', label: '8 Family Tractor', checked: false, id: 131415 }, { value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor', label: '9 Family Tractor', checked: false, id: 161718 }] }, { value: '/app/Http/routes.js', label: 'routes.js', checked: false, id: 181920 }] }, { value: '/app/Providers', label: 'Providers', checked: false, id: 212223, children: [{ value: '/app/Http/Providers/EventServiceProvider.js', label: 'EventServiceProvider.js', checked: false, id: 242526 }] }] }, { value: '/config', label: 'config', checked: false, id: 272829, children: [{ value: '/config/app.js', label: 'app.js', checked: false, id: 303132 }, { value: '/config/database.js', label: 'database.js', checked: false, id: 333435 }] }, { value: '/public', label: 'public', checked: false, id: 353637, children: [{ value: '/public/assets/', label: 'assets', checked: false, id: 383940, children: [{ value: '/public/assets/style.css', label: 'style.css', checked: false, id: 404142 }] }, { value: '/public/index.html', label: 'index.html', checked: false, id: 434445 }] }, { value: '/.env', label: '.env', checked: false, id: 464748 }, { value: '/.gitignore', label: '.gitignore', checked: false, id: 495051 }, { value: '/README.md', label: 'README.md', checked: false, id: 525354 }];
// We reduce the array of nested items in to one object of:
// { id: item }
const idMap = mainArray.reduce(function merge(map, node) {
map[node.id] = node;
if (Array.isArray(node.children)) {
node.children.reduce(merge, map);
}
return map;
}, {});
const ids = [525354, 123, 131415];
// Whenever you need an item, you can get it
// using idMap[id]
const items = ids.map(id => idMap[id]);
items.forEach(item => item.checked = true);
// or: ids.forEach(id => idMap[id].checked = true)

'this' not resolved correctly in submit handler in Sencha touch/JavaScript

I am trying to create a form through sencha touch that simply takes the text that the user enters and does a search for jobs on a website. Although everything else is working properly including the reset button but whenever I do this.getComponent('keywords') in the submitbuttonhandler it gives me an error saying Uncaught
TypeError: Object # has no method 'getComponent'.
Ext.ns('SearchJobsForm'); // register our namespace
var resetButtonHandler = function (btn, evt) {
this.getComponent('keywords').reset();
this.getComponent('dposted').reset();
this.getComponent('jtitle').reset();
this.getComponent('jcategory').reset();
this.getComponent('salaryf').reset();
this.getComponent('salaryt').reset();
this.getComponent('jscategory').reset();
this.getComponent('ptype').reset();
}
Here is the block of code that is the problem. The following block of code is not resolving 'this' the way reset button handler above is.
var submitButtonHandler = function(btn,evt) {
var temp = this.getComponent('keywords').getValue();
//query('#jcategory').getValue();
alert(temp);
//alert('In Progress');
}
The following is just creating the form.
SearchJobsForm.form = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this, {
floating: true,
width: 250,
height: 370,
scroll: 'vertical',
centered: true,
modal: true,
hideOnMaskTap: false,
items: [{
xtype: 'textfield',
itemId: 'keywords',
label: 'Keywords',
labelAlign: 'top',
labelWidth: '100%',
name: 'Keywords'
},{
xtype: 'textfield',
label: 'Job Title',
itemId: 'jtitle',
labelAlign: 'top',
labelWidth: '100%',
name: 'Job Title'
},{
xtype: 'selectfield',
label: 'Job Category',
itemId: 'jcategory',
labelAlign: 'top',
labelWidth: '100%',
options: [{
text: '-- ANY --', value: 'ANY'
}, {
text: 'Technical', value: 'Technical'
}, {
text: 'Non-Technical', value: 'Non-Technical'
}, {
text: 'Tech Start-up', value: 'Tech Start-up'
}, {
text: 'Life Science', value: 'Life Science'
}, {
text: 'Digital Media', value: 'Digital Media'
}, {
text: 'Accelerator Centre', value: 'Accelerator Centre'
}
]
},{
xtype: 'selectfield',
label: 'Job Sub-Category',
itemId: 'jscategory',
labelAlign: 'top',
labelWidth: '100%',
options: [{
text: '-- ANY --', value: 'ANY'
}, {
text: 'Developer', value: 'Developer'
}, {
text: 'Quality Assurance', value: 'Quality Assurance'
}, {
text: 'Project Manager', value: 'Project Manager'
}, {
text: 'Tester', value: 'Tester'
}, {
text: 'IT Help Desk', value: 'IT Help Desk'
}, {
text: 'Health Care', value: 'Health Care'
}, {
text: 'Transportation and Logistics', value: 'Transportation and Logistics'
}, {
text: 'Management', value: 'Management'
}, {
text: 'Network', value: 'Network'
}, {
text: 'Administration', value: 'Administration'
}, {
text: 'General', value: 'General'
}
]
},{
xtype: 'selectfield',
label: 'Position Type',
itemId: 'ptype',
labelAlign: 'top',
labelWidth: '100%',
options: [{
text: '-- ANY --', value: 'ANY'
}, {
text: 'Part Time', value: 'Part Time'
}, {
text: 'Part Time Contract', value: 'Part Time Contract'
}, {
text: 'Full Time', value: 'Full Time'
}, {
text: 'Full Time Contract', value: 'Full Time Contract'
}
]
},{
xtype: 'selectfield',
label: 'Salary (CAD$): From',
itemId: 'salaryf',
labelAlign: 'top',
labelWidth: '100%',
options: [{
text: '-- ANY --', value: 'ANY'
}, {
text: '20000', value: '20000'
}, {
text: '30000', value: '30000'
}, {
text: '40000', value: '40000'
},{
text: '50000', value: '50000'
}, {
text: '60000', value: '60000'
}, {
text: '70000', value: '70000'
}, {
text: '80000', value: '80000'
}, {
text: '90000', value: '90000'
}, {
text: '100000', value: '100000'
}, {
text: '100000+', value: '100000+'
}
]
},{
xtype: 'selectfield',
label: 'to',
itemId: 'salaryt',
labelAlign: 'top',
labelWidth: '100%',
options: [{
text: '-- ANY --', value: 'ANY'
}, {
text: '20000', value: '20000'
}, {
text: '30000', value: '30000'
}, {
text: '40000', value: '40000'
},{
text: '50000', value: '50000'
}, {
text: '60000', value: '60000'
}, {
text: '70000', value: '70000'
}, {
text: '80000', value: '80000'
}, {
text: '90000', value: '90000'
}, {
text: '100000', value: '100000'
}, {
text: '100000+', value: '100000+'
}
]
},{
xtype: 'selectfield',
label: 'Posted in last (Days):',
itemId: 'dposted',
labelAlign: 'top',
labelWidth: '100%',
options: [{
text: '30', value: '30'
}, {
text: '60', value: '60'
}, {
text: '90', value: '90'
}
]
}
],
dockedItems: [{
xtype: 'toolbar',
itemId: 'toolbar',
dock: 'bottom',
height: '36',
items: [
{ xtype: 'button', text: 'Reset',itemId: 'reset',scope: this,
handler: resetButtonHandler },
{ xtype: 'spacer'},
{ xtype: 'button', text: 'Submit',
handler: submitButtonHandler
}
]
}]
});
SearchJobsForm.form.superclass.initComponent.call(this);
// alert(SearchJobsForm.form.getValues(true));
this.items.get(2).on({
change: this.onChange,
scope: this
});
},
onChange: function(selectField, value){
this.items.get(1).disable();
} //end of function onChange
});
Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function(){
var form = new SearchJobsForm.form();
form.show();
}
});
this.getComponent(childId) browses through the children components of the current object. In resetButtonHandler(), this should be considered as the reset button.
SearchJobsForm is the declaration of an object not its instance. Otherwise you would have used the "new" command. SearchJobsForm.fieldName doesn't refers to a field.
So, in the submitButtonHandler() method's context, this is equivalent to : Ext.getCmp('reset');
You can use the id field (not itemId) of the component to address it in a quick and dirty way :
SearchJobsForm.form = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this, {
id: 'form', // add an id to use Ext.getCmp()
floating: true,
...
}
});
// So later you can use
Ext.getCmp('keywords')
Or go all the way up from the resetButton context to the form panel and then down to the input keywords. No need to add an attribute in this case.
var form = this.el.up('.x-panel');
var input_keyword = form.down('.x-input-text[name=Keywords]').getValue();
Regards

Categories

Resources