Disable labels for a single line in morris line - morris.js

I have a Morris chart with two lines. I would like to disable the labels for one of the lines, but allow labels for the other line.
I found the "hideHover" option in the documentation, but it appears to be a global setting that cannot be applied to individual lines:
...
pointFillColors: [ '#039be5', '#C9302C'],
pointStrokeColors: [ '#039be5', '#C9302C'],
hideHover: "always"
...
Then I tried this, thinking that it might work:
...
pointFillColors: [ '#039be5', '#C9302C'],
pointStrokeColors: [ '#039be5', '#C9302C'],
hideHover: ["always",'auto'],
...
From the image above you will see the label I am trying to remove.
Alas, no success.
Does anyone know a way to do this?

You can use the hoverCallback to achieve your goal. Loop trough the content element and get only the header and exclude the line you don't want like this:
hoverCallback: function (index, options, content, row) {
var finalContent = "";
var indexHeader = 0;
var indexLineToIgnore = 1;
// Get the data
$(content).each(function (i, e) {
if (i == indexHeader) {
finalContent += e.outerHTML;
} else {
if (i != indexLineToIgnore) {
finalContent += e.outerHTML;
}
}
});
return finalContent;
}
Please try the following snippet:
var data = [
{ "date": "1/1/2010", "a": "5", "b": null },
{ "date": "5/2/2010", "a": "6", "b": "20" },
{ "date": "6/3/2010", "a": "7", "b": "1" },
{ "date": "7/4/2010", "a": "8", "b": "9" },
{ "date": "8/5/2010", "a": "9", "b": "4" },
{ "date": "9/6/2010", "a": "10", "b": "2" }
];
new Morris.Line({
element: 'chart',
data: data,
xkey: 'date',
ykeys: ['a', 'b'],
labels: ['Series A', 'Series B'],
hideHover: 'auto',
parseTime: false,
resize: true,
pointFillColors: ['#039be5', '#C9302C'],
pointStrokeColors: ['#039be5', '#C9302C'],
hoverCallback: function (index, options, content, row) {
var finalContent = "";
var indexHeader = 0;
var indexLineToIgnore = 1;
// Get the data
$(content).each(function (i, e) {
if (i == indexHeader) {
finalContent += e.outerHTML;
} else {
if (i != indexLineToIgnore) {
finalContent += e.outerHTML;
}
}
});
return finalContent;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css" rel="stylesheet"/>
<div id="chart"></div>

Related

Comparing two JSON objects with order of fields and subarrays shuffled in Karate [duplicate]

This question already has an answer here:
Asserting and using conditions for an array response in Karate
(1 answer)
Closed 2 years ago.
I want to loop through below nested json structure and want to update all the required fields, however I could achieve this through typescript but want to do this in karate JS, I do not see any examples how to nested for each works.
I want to update 26 periods data(here for readability i used 3), based on index I want to update period field, i.e. if(index == key), these 26 periods are under each car attribute.(NOTe: you again have multiple cars and multiple car attributes and each car attribute you have 26 periods data)
I cannot use this Karate - Match two dynamic responses only when you have single array list and have less data
[
{
"cars": [
{
"name": "car 1",
"periodsData": [
{
"period": "5ed73ed31a775d1ab0c9fb5c",
"index": 1
},
{
"period": "5ed73ed31a775d1ab0c9fb5d",
"index": 2
},
{
"period": "5ed73ed31a775d1ab0c9fb5e",
"index": 3
}
]
},
{
"name": "car 2",
"periodsData": [
{
"period": "5ed73ed31a775d1ab0c9fb5c",
"index": 1
},
{
"period": "5ed73ed31a775d1ab0c9fb5d",
"index": 2
},
{
"period": "5ed73ed31a775d1ab0c9fb5e",
"index": 3
}
]
},
{
"name": "car 3",
"periodsData": [
{
"period": "5ed73ed31a775d1ab0c9fb5c",
"index": 1
},
{
"period": "5ed73ed31a775d1ab0c9fb5d",
"index": 2
},
{
"period": "5ed73ed31a775d1ab0c9fb5e",
"index": 3
}
]
}
],
"totalPeriodEprps": [
{
"period": "5ed73ed31a775d1ab0c9fb5c",
"index": 1
},
{
"period": "5ed73ed31a775d1ab0c9fb5d",
"index": 2
},
{
"period": "5ed73ed31a775d1ab0c9fb5e",
"index": 3
}
]
}
carId ="dfd"
]
This above array repeats
Type script code
//periods is a map of index and values
async modifyCarsData(mid, id, periods, campaignData) {
//carData is a json file
carData.forEach(element => {
element.carId= id;
// Update all egrp periods
element.totalPeriodEGRPs.forEach(eGrpPeriod => {
// egrprd.period =
if (periods.size === element.totalPeriodEGRPs.length) {
periods.forEach((value, key) => {
if (key === eGrpPeriod.index.toString()) {
eGrpPeriod.period = value;
return true;
}
});
}
});
element.cars.forEach(carCell => {
// Logic for updating periods data
carCell .periodsData.forEach(periodAttribute => {
if (periods.size === carCell.periodsData.length) {
periods.forEach((value, key) => {
if (key === periodAttribute.index.toString()) {
periodAttribute.period = value;
return true;
}
});
}
});
});
});
Don't think of this as an update, but as a transform. I'm not using your example because it is un-necessarily complicated. Here is a simpler example that gives you all the concepts you need:
* def data = [{ name: 'one', periods: [{ index: 1, value: 'a' },{ index: 2, value: 'b' }]}, { name: 'two', periods: [{ index: 1, value: 'c' },{ index: 2, value: 'd' }]}]
* def fnPeriod = function(x){ x.value = x.value + x.index; return x }
* def fnData = function(x){ return { name: x.name, periods: karate.map(x.periods, fnPeriod) } }
* def converted = karate.map(data, fnData)
* print converted
Which prints:
[
{
"name": "one",
"periods": [
{
"index": 1,
"value": "a1"
},
{
"index": 2,
"value": "b2"
}
]
},
{
"name": "two",
"periods": [
{
"index": 1,
"value": "c1"
},
{
"index": 2,
"value": "d2"
}
]
}
]
If this doesn't work for you, please look for another tool. Karate is designed for testing and assertions, not doing what you normally do in programming languages. And I suspect that you have fallen into the trap of writing "over-smart tests", so please read this: https://stackoverflow.com/a/54126724/143475
Also refer: https://stackoverflow.com/a/53120851/143475

Karate - How to use nested for each in karate similar to javascript [duplicate]

This question already has an answer here:
Asserting and using conditions for an array response in Karate
(1 answer)
Closed 2 years ago.
I want to loop through below nested json structure and want to update all the required fields, however I could achieve this through typescript but want to do this in karate JS, I do not see any examples how to nested for each works.
I want to update 26 periods data(here for readability i used 3), based on index I want to update period field, i.e. if(index == key), these 26 periods are under each car attribute.(NOTe: you again have multiple cars and multiple car attributes and each car attribute you have 26 periods data)
I cannot use this Karate - Match two dynamic responses only when you have single array list and have less data
[
{
"cars": [
{
"name": "car 1",
"periodsData": [
{
"period": "5ed73ed31a775d1ab0c9fb5c",
"index": 1
},
{
"period": "5ed73ed31a775d1ab0c9fb5d",
"index": 2
},
{
"period": "5ed73ed31a775d1ab0c9fb5e",
"index": 3
}
]
},
{
"name": "car 2",
"periodsData": [
{
"period": "5ed73ed31a775d1ab0c9fb5c",
"index": 1
},
{
"period": "5ed73ed31a775d1ab0c9fb5d",
"index": 2
},
{
"period": "5ed73ed31a775d1ab0c9fb5e",
"index": 3
}
]
},
{
"name": "car 3",
"periodsData": [
{
"period": "5ed73ed31a775d1ab0c9fb5c",
"index": 1
},
{
"period": "5ed73ed31a775d1ab0c9fb5d",
"index": 2
},
{
"period": "5ed73ed31a775d1ab0c9fb5e",
"index": 3
}
]
}
],
"totalPeriodEprps": [
{
"period": "5ed73ed31a775d1ab0c9fb5c",
"index": 1
},
{
"period": "5ed73ed31a775d1ab0c9fb5d",
"index": 2
},
{
"period": "5ed73ed31a775d1ab0c9fb5e",
"index": 3
}
]
}
carId ="dfd"
]
This above array repeats
Type script code
//periods is a map of index and values
async modifyCarsData(mid, id, periods, campaignData) {
//carData is a json file
carData.forEach(element => {
element.carId= id;
// Update all egrp periods
element.totalPeriodEGRPs.forEach(eGrpPeriod => {
// egrprd.period =
if (periods.size === element.totalPeriodEGRPs.length) {
periods.forEach((value, key) => {
if (key === eGrpPeriod.index.toString()) {
eGrpPeriod.period = value;
return true;
}
});
}
});
element.cars.forEach(carCell => {
// Logic for updating periods data
carCell .periodsData.forEach(periodAttribute => {
if (periods.size === carCell.periodsData.length) {
periods.forEach((value, key) => {
if (key === periodAttribute.index.toString()) {
periodAttribute.period = value;
return true;
}
});
}
});
});
});
Don't think of this as an update, but as a transform. I'm not using your example because it is un-necessarily complicated. Here is a simpler example that gives you all the concepts you need:
* def data = [{ name: 'one', periods: [{ index: 1, value: 'a' },{ index: 2, value: 'b' }]}, { name: 'two', periods: [{ index: 1, value: 'c' },{ index: 2, value: 'd' }]}]
* def fnPeriod = function(x){ x.value = x.value + x.index; return x }
* def fnData = function(x){ return { name: x.name, periods: karate.map(x.periods, fnPeriod) } }
* def converted = karate.map(data, fnData)
* print converted
Which prints:
[
{
"name": "one",
"periods": [
{
"index": 1,
"value": "a1"
},
{
"index": 2,
"value": "b2"
}
]
},
{
"name": "two",
"periods": [
{
"index": 1,
"value": "c1"
},
{
"index": 2,
"value": "d2"
}
]
}
]
If this doesn't work for you, please look for another tool. Karate is designed for testing and assertions, not doing what you normally do in programming languages. And I suspect that you have fallen into the trap of writing "over-smart tests", so please read this: https://stackoverflow.com/a/54126724/143475
Also refer: https://stackoverflow.com/a/53120851/143475

Lodash: filter multiple properties

I am new to lodash.
I am having trouble filtering with lodash. I have a deep nested json object that I want to filter if productName = 'Lotto' and the board selectionMethod = "AUTOPICK"
When I try the solution below, it returns all results instead of filtering. I have tried multiple ways to do this but I always get all results returning.
Could anyone offer a suggestion?
var results = {
"buyTicketDetails": {
"result": 0,
"message": "Success",
"product": [
{
"productName": "Lotto",
"displayPromoMessage": false,
"drawDetails": [
{
"drawTypeDescription": "REGULAR DRAW",
"drawAttribute": "EVENING",
"drawStartDate": "2019-01-12T00:00:00.000-05",
"drawEndDate": "2019-01-12T00:00:00.000-05"
},
{
"drawTypeDescription": "SPECIAL DRAW",
"drawAttribute": "EVENING",
"drawStartDate": "2019-01-12T00:00:00.000-05",
"drawEndDate": "2019-01-12T00:00:00.000-05"
}
],
"board": [
{
"boardType": "REGULAR",
"selectionMethod": "AUTOPICK",
"selectionSet": [
"2",
"4",
"10",
"12",
"17",
"31"
]
},
{
"boardType": "RAFFLE",
"selectionMethod": "SYSTEMPICK",
"selectionSet": [
"40001722-01"
]
}
]
},
{
"productName": "Encore",
"displayPromoMessage": false,
"drawDetails": [
{
"drawTypeDescription": "REGULAR DRAW",
"drawAttribute": "EVENING",
"drawStartDate": "2019-01-12T00:00:00.000-05",
"drawEndDate": "2019-01-12T00:00:00.000-05"
}
],
"board": [
{
"boardType": "REGULAR",
"selectionMethod": "SYSTEMPICK",
"selectionSet": [
"3440514"
]
}
]
}
]
}
}
const filterCat = _.filter(results, { product: [
{
productName: "Lotto",
board: {
selectionMethod: "AUTOPICK"
}}
]
}
);
console.log(filterCat);
With Pure JS.
You can do this with Javascript's filter function too.
filter function actually works on Arrays, so we use map loop to add objects into arrays first, then we use filter function to get only the data we need!.
let Product = results.buyTicketDetails.product
let getSelectionMethods=(index) => Product[index].board.map((d,i)=>d.selectionMethod)
let getTargetedProducts =(Name,Method)=> Product.map((d,i)=>{
if(Product[i].productName==Name && getselectionMethods(i).indexOf(Method) !==-1){
return d
}
})
let FilteredProducts = getTargetedProducts("Lotto","AUTOPICK").filter((d)=>d !==undefined)
console.log(FilteredProducts)

jsaTypeError: GoogleTiledMap is not a constructor

I define a class and then use it to create a layer.but it has error.but I don't know where it was wrong?
define(["dojo/_base/declare","esri/SpatialReference","esri/layers/TiledMapServiceLayer","esri/geometry/webMercatorUtils","esri/geometry/Extent",
"esri/layers/TileInfo"],function(declare,SpatialReference,TiledMapServiceLayer,webMercatorUtils,Extent,TileInfo){
declare("extras.layer.GoogleTiledMap", [TiledMapServiceLayer], {
online: false,
mapStyle: "roadmap",
constructor: function(a) {
this.spatialReference = new esri.SpatialReference({
wkid: 102113
});
this.online = a.online || false;
this.mapStyle = a.mapStyle || "roadmap";
this.layerId = a.layerId;
this.suffix = a.suffix || ".png";
this.tile_url = a.tile_url;
this.fullExtent = new Extent( - 20037508.342787, -20037508.342787, 20037508.342787, 20037508.342787, this.spatialReference);
this.initialExtent = new Extent(12557877.595482401, 2596928.9267310356, 12723134.450635016, 2688653.360673282);
this.tileInfo = new TileInfo({
"rows": 256,
"cols": 256,
"compressionQuality": 0,
"origin": {
"x": -20037508.342787,
"y": 20037508.342787
},
"spatialReference": {
"wkid": 102113
},
"lods": [{
"level": 3,
"scale": 73957190.948944,
"resolution": 19567.8792409999
},
{ ...
I use it in html file.
require([
"esri/map",
"extras/layer/GoogleTiledMap",
"dojo/domReady!"
], function(map,GoogleTiledMap) {
var layer=new GoogleTiledMap({
"id": "100",
"layerId":"GXX_XXXXX",
"online":false,
"name": "谷歌电子地图",
"suffix": "png",
"tileSize": "256",
"tileType": "googlemap",
"mapStyle":"roadmap",
"tile_url": "127.0.0.1:8080"
});
Just declaring is not sufficient, you need to return it as well. Like below
define(["dojo/_base/declare",...], function(declare,...){
return declare([...], {
//you module here
});
});

Use object instead of array in datatables

When using datatables, I get 'no data available in table' when using an object instead of array:
var data1 =
{
"status": "success",
"districts": {
"1": {
"district_number": "1",
"district_name": "district one"
},
"2": {
"district_number": "2",
"district_name": "district two"
}
},
"time": "1.109s"
};
var table1 = jQuery("#data_table1").DataTable({
"data": data1.districts,
"aoColumns": [
{ "mData": "district_number" },
{ "mData": "district_name" }
]
});
I can get an array to display in a datatable using mData as follows:
var data2 =
{
"status": "success",
"districts": [
{
"district_number": "1",
"district_name": "district one"
},
{
"district_number": "2",
"district_name": "district two"
}
],
"time": "1.109s"
};
var table2 = jQuery("#data_table2").DataTable({
"data": data2.districts,
"aoColumns": [
{ "mData": "district_number" },
{ "mData": "district_name" }
]
});
https://jsfiddle.net/w93gubLv/
Is there a way to get datatables to utilize the object in the original format, or must I convert the object to an array?
You can write your own function to convert one format to another, for example:
function formatData(data){
var result = [];
for(prop in data){
if(data.hasOwnProperty(prop)){
result.push( data[prop] );
}
}
return result;
}
You can then later use it to pass data to jQuery DataTables as shown below.
var table1 = jQuery("#data_table1").DataTable({
"data": formatData(data1.districts),
"aoColumns": [
{ "mData": "district_number" },
{ "mData": "district_name" }
]
});
See updated jsFiddle for code and demonstration.