Displaying AMCharts inside an HTML table cell - html

I am trying to display AMCharts inside an HTML table cell. I'm looping through data and creating a chart for each data item. Here is my HTML code:
<table id="theTable" class="display table table-bordered">
<thead>
<tr>
<th>Department</th>
<th>Number of Employees</th>
<th>Number of Volunteers</th>
<th>Chart</th>
</tr>
</thead>
<tbody>
<tr>
<td>IT</td>
<td>30</td>
<td>5</td>
<td><div id="chart_1"></div></td>
</tr>
<tr>
<td>HR</td>
<td>35</td>
<td>14</td>
<td><div id="chart_2"></div></td>
</tr>
<tr>
<td>LG</td>
<td>100</td>
<td>65</td>
<td><div id="chart_3"></div></td>
</tr>
</tbody>
</table>
And here is my Javascript code:
var emp = [30, 35, 100];
var vol = [5, 14, 65];
for (var j = 0; j < 3; j++) {
var str = "chart_" + j.toString();
var chart = AmCharts.makeChart(str, {
"type": "pie",
"dataProvider": [{
"type": "Employees",
"per": parseFloat(emp[j]),
"color": "#54e83a"
}, {
"type": "Volunteers",
"per": parseFloat(vol[j]),
"color": "#41ba2c"
}],
"valueField": "per",
"titleField": "type",
"colorField": "color",
"balloon": {
"fixedPosition": true
},
"export": {
"enabled": true
},
"startDuration": 0
});
}
What am I doing wrong? Any help is appreciated! Here is a JSFiddle
(Please ignore this text the Editor is saying my post is mostly code so I'm adding non-code text hoping to trick it...This is unprofessional I know.)

AmChart divs must have dimensions specified through CSS, otherwise they won't display. Set the sizes and you're all set, for example:
#chart_1, #chart_2, #chart_3 {
width: 300px;
height: 100px;
}
You also need to adjust your loop logic as you're starting from chart_0, when your divs are starting from chart_1. Either update your html or fix your string creation, e.g. var str = "chart_" + (j + 1); (note you don't need toString())
Updated fiddle

Related

Match and replace every 7th instance of a <td> tag

I'm struggling to wrap my head around how to get this regex working in Visual Studio Code.
I'm trying to match every 7th instance of <td> tag to then replace it with <td data-order="">.
Original
<tr>
<td>1</td>
<td>Name</td>
<td>Owner</td>
<td>Value</td>
<td>Total</td>
<td>Percent</td>
<td>Ratio</td>
<td>Final</td>
</tr>
What I want
<tr>
<td>1</td>
<td>Name</td>
<td>Owner</td>
<td>Value</td>
<td>Total</td>
<td>Percent</td>
<td data-order="">Ratio</td>
<td>Final</td>
</tr>
I've tried variations on ((?:.*<td>){1}), but any number greater than 1 just gives me a "No results" message.
[You say "match every 7th instance" but I think you mean match the seventh instance, not the 7th, 14th, 21st, etc. Assuming that you mean the 7th only..."]
If your data is really as regular and structured as you showed, you could use this as the regex in a Find
Find: (?<=<tr>\n(?:<td>.*<\/td>\n){6})(<td)
Replace: <td data-order=""
If you might have newlines within a <td>...\n...</td> tag, use this
Find: (?<=<tr>\n(?:<td>[^/]*<\/td>\n){6})(<td)
Replace: <td data-order=""
Vscode's find/replace (in one file) can use a non-fixed length lookbehind like
(?<=<tr>\n(?:<td>.*<\/td>\n){6})
The search across files cannot do that so this regex would not work there. Also sites like regex101.com can't use it either so I'll show a demo in vscode itself:
You can use the extension Select By. And use the command moveby.regex.
In your keybindings.json define a keybinding to search for the next <td> tag.
{
"key": "ctrl+i ctrl+u", // or any other key combo
"when": "editorTextFocus",
"command": "moveby.regex",
"args": {
"regex": "<td[^>]*>",
"properties": ["next", "end"]
}
}
Select the first <tr> tag of where you want to start
Select every following <tr> tag with:
command: Add Selection to Next Find Match(Ctrl+D - editor.action.addSelectionToNextFindMatch)
menu option: Selection > Select All Occurrences
Apply the key binding as many times as you want
Your cursors are now after the n-th <td> tag
Make any edits you want
Press Esc to leave Multi Cursor mode
In Select By v1.2.0 you can specify a repeat count. The count can be fixed or asked from the user.
{
"key": "ctrl+i ctrl+u", // or any other key combo
"when": "editorTextFocus",
"command": "moveby.regex",
"args": {
"regex": "<td[^>]*>",
"properties": ["next", "end"],
"repeat": "ask"
}
}
If you leave out the property "regex" you are asked for a regular expression too.
Edit
Using a regular expression takes quite some time to get it correct
let testStr =`<tr>
<td>1</td>
<td>Name</td>
<td>Owner</td>
<td>Value</td>
<td>Total</td>
<td>Percent</td>
<td>Ratio</td>
<td>Final</td>
</tr>`;
var replace = '$1<td class="red">$2';
var regex = new RegExp("(<tr>[\n\r\s]*(?:<td[^>]*>(?:.|[\n\r\s])*?</td>[\n\r\s]*){6})<td>((?:.|[\n\r\s])*</tr>)");
var newstr=testStr.replace(regex,replace);
console.log(newstr);
document.getElementById("test").innerHTML=newstr
.red {
color: red
}
<table>
<tbody >
<tr id="test">
</tr>
</tbody>
</table>
I was interested in this as I don't know much of regex and need to learn, but I manged to make it so in two goes.
I hope someone will correct me and help with correct one way.
I tried to folow this: but cant make it to work: Find Nth Occurrence of Character
let testStr = '<td>1</td><td>Name</td><td>Owner</td><td>Value</td><td>Total</td><td>Percent</td><td>Ratio</td><td>Final</td>';
var replace = '<td class="red">';
var regex = new RegExp("((<td>.*?)){7}");
// tried with a lot of (?:...) combinations here but none works :(
var newstr=testStr.replace(regex,replace);
var regex2 = new RegExp("((</td>.*?)){6}");
var newstr2=testStr.match(regex2);
console.log(newstr);
console.log(newstr2[0]);
document.getElementById("test").innerHTML=newstr2[0]+newstr
.red {
color: red
}
<table>
<tbody >
<tr id="test">
</tr>
</tbody>
</table>
EDIT:
Got something :)
let testStr = '<td>1</td><td>Name</td><td>Owner</td><td>Value</td><td>Total</td><td>Percent</td><td>Ratio</td><td>Final</td>';
var replace = '<td class="red">';
var regex = new RegExp("(?:[</td>]){6}(<td>)");
var newstr=testStr.replace(regex,replace);
console.log(newstr);
document.getElementById("test").innerHTML=newstr
.red {
color: red
}
<table>
<tbody >
<tr id="test">
</tr>
</tbody>
</table>
And with #rioV8's help:
let testStr = '<td>1</td><td>Name</td><td>Owner</td><td>Value</td><td>Total</td><td>Percent</td><td>Ratio</td><td>Final</td>';
var replace = '$1<td class="red">';
var regex = new RegExp("((?:.*?</td>){6})<td>");
var newstr=testStr.replace(regex,replace);
console.log(newstr);
document.getElementById("test").innerHTML=newstr
.red {
color: red
}
<table>
<tbody >
<tr id="test">
</tr>
</tbody>
</table>

Why is DataTables stripping custom attributes in render function?

I'm working on a .Net MVC website and in one of the views a table is rendered using DataTables which makes an ajax call to an API. However, when the table is rendered the custom attributes I supply in the render function are being stripped out:
Here is the HTML:
<table id="table-rate-headers" class="table table-bordered table-fit table-hover table-sm" style="margin-top: 0px; width: 100%;">
<thead class="text-nowrap">
<tr>
<th>Domain</th>
<th>Project</th>
<th>Union</th>
<th>Union Local</th>
<th>Trade Class</th>
<th>Trade Class Description</th>
<th>Date From</th>
<th>Date To</th>
</tr>
</thead>
<tbody class="text-nowrap"></tbody>
</table>
And the js:
var ratesDataTable = $('#table-rate-headers').DataTable({
dom: 'rftp',
pageLength: 5,
select: true,
ajax: {
url: '/api/rates/rateheadersnormalized',
dataSrc: ""
},
columnDefs: [
{
className: 'row-border'
}
],
columns: [
{
"data": "rateDomain",
render: function (data, type, row) {
return '<td rateheadersid="' + row.rateHeaderSID + '">' + row.rateDomain + '</td>';
}
},
{
"data": "project"
},
{
"data": "union"
},
{
"data": "unionLocal"
},
{
"data": "tradeClass"
},
{
"data": "tradeClassDescription"
},
{
"data": "effectiveDateFrom",
render: function (data, type, row) {
return moment(row.effectiveDateFrom).format("MM/DD/YYYY");
}
},
{
"data": "effectiveDateTo",
render: function (data, type, row) {
return moment(row.effectiveDateTo).format("MM/DD/YYYY");
}
}
]
});
When the page is rendered, I expect to see in the dom:
<td rateheadersid="1">Labor</td>
But what I actually see is:
<td class="sorting_1">Labor</td>
Something is stripping out the custom attribute and not rendering the element as I'd expect. I tried adding "orderClasses": false but it just got rid of the class="sorting_1" and nothing else. Also tried taking out all the css classes I specified for the table and that didn't make a difference. I've also compared the setup of the table to all the previous ones I've created and I can' spot anything out of order. Any guidance appreciated.
The DataTables columns option is already inside the <td> and </td> tags of the HTML table cells it is trying to populate. So, it can only populate the cells content - not the cell's HTML attributes.
HTML does not let you embed another <td> inside a <td> - which is what the code is effectively trying to do.
The simplest fix is to change your <td> to a <span>:
return '<span rateheadersid="' + row.rateHeaderSID + '">' + row.rateDomain + '</span>';
That may be sufficient for your needs. If not, then you may need to provide more info in the question.

Kendo Grid Row Grouping Not Working

I am using Kendo for the first time and am attempting to convert an HTML table to a Kendo grid. Upon initialization, I want the table to be grouped by a specific column and not be groupable by any other column. Below is a contrived example of a table of cars to be grouped by the car's make which demonstrates how I am attempting to group by a specific column upon initialization.
This attempt does not cause the table to be grouped. I know the kendoGrid call is working, because if I set groupable to true I am able to group by any column via drag and drop, but the initial grouping still does not occur. I suspect that somehow the group field "make" is not being tied to my make column, but examples I've seen seem to indicate this can be accomplished using data-field as I have done.
<table id="carsGrid">
<thead>
<tr>
<th>Year</th>
<th>Color</th>
<th data-field="make">Make</th>
</tr>
</thead>
<tbody>
<tr>
<td>2010</td>
<td>Red</td>
<td>Dodge</td>
</tr>
<tr>
<td>2014</td>
<td>Blue</td>
<td>Ford</td>
</tr>
<tr>
<td>2016</td>
<td>Black</td>
<td>Dodge</td>
</tr>
</tbody>
</table>
And in the document's ready function:
$('#carsGrid').kendoGrid({
datasource: { group: { field: "make" } },
groupable: false //I do not want grouping on other columns
});
I found some solution for your problem: Check this example http://dojo.telerik.com/OhEta
You should add data-groupable="false" attribute in <th> element:
<thead>
<tr>
<th data-field="year" data-groupable="false">Year</th>
<th data-field="color" data-groupable="false">Color</th>
<th data-field="make">Make</th>
</tr>
</thead>
Instead of using an html <table> you can setup the columns and their values in the javascript.
First you can replace your entire <table></table> section with:
<div id="grid"></div>.
Then in your document's ready function, you can throw your values for each column into an array:
var productsArray = [{Year: 2010, Color: "Red", Make: "Dodge"},
{Year: 2014, Color: "Blue", Make: "Ford"},
{Year: 2016, Color: "Black", Make: "Dodge"}]
And update where you set the kendo grid with:
$("#grid").kendoGrid({
dataSource: {
data: productsArray,
group: {field: "Make"}
},
columns: [
{ field: "Year" },
{ field: "Color" },
{ field: "Make" }
]
});
Click Here for a working example that you can test with.

AngularJS table using data from REST API

I want to display a table using AngularJS. The data source for the table will be a REST API. Here is an example response:
{
"value": 43,
"C_class": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13
],
"C_name": [
"C_1",
"C_2",
"C_3",
"C_4",
"C_5",
"C_6",
"C_7",
"C_8",
"C_9",
"C_10",
"C_11",
"C_12",
"C_13"
]
}
I want to display the data in the format below:
<tr><td> 1</td><td>C_1<td>
<td>2<td><td>C_2<td>
<td>3<td><td>C_3<td>
<td>4<td><td>C_4<td>
<td>5<td><td>C_5<td>.....
I have tried using ng-repeat, but unable to fetch. Thank you
<table class="table" border="1" style="width: 100%;" id="detail_table">
<tbody><tr ng-repeat="value in tests">
<td>{{value.C_name}}</td>
<td>{{value.C_class}}</td>
</tr></tbody></table>
You are not using ng-repeat in correct way. You can take help from the below code to display your table:
<table class="table" border="1" style="width: 100%;" id="detail_table">
<tbody>
<tr ng-repeat="value in tests.C_class">
<td ng-bind="tests.C_class[$index]"></td>
<td ng-bind="tests.C_name[$index]"></td>
</tr>
</tbody>
</table>
I'll suggest you study a little bit about using ng-repeat.
Try using ng-bind instead of {{}}. see here
This worked for me.
http://plnkr.co/edit/7gLpeyrtyMgnqtdXDxAu?p=preview
<body ng-controller="myCtrl">
<div class="container">
<table class="table table-striped" style="height: 100px; width: 100px;">
<tr ng-repeat="(key,value) in new_c_obj">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
</div>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.response = {
"value": 43,
"C_class": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
"C_name": [ "C_1", "C_2", "C_3", "C_4", "C_5", "C_6", "C_7", "C_8", "C_9", "C_10", "C_11", "C_12", "C_13"]
};
$scope.c_obj = {};
$scope.new_c_obj = {};
$scope.c_obj.c_class = $scope.response["C_class"];
$scope.c_obj.c_name = $scope.response["C_name"];
for($scope.i = 0; $scope.i <= $scope.c_obj.c_class.length-1; $scope.i++){
$scope.new_c_obj[$scope.c_obj.c_class[$scope.i]] = $scope.c_obj.c_name[$scope.i];
}
});
You can use the $index in your ng-repeat (as suggested by B.A.B.U) or properly reformat your data into a new array :
var orgArray = your_data;
var newArray = [];
orgArray.C_class.forEach(function (p, i) {
newArray.push({ C_class: p, C_name: orgArray.C_name[i] });
});
and from there you can apply ng-repeat on the new array to display the fields.
You can simply add those two into another object array..
var mainObjC = array();
C_class.forEach(myFunction);
var x = 0;
function myFunction(){
var obj = {
C_name : C_name[x],
C_class : C_class[x]
}
x++;
mainObjC.push(obj);
}
And your html would be
<table class="table" border="1" style="width: 100%;" id="detail_table">
<tbody>
<tr ng-repeat="value in mainObjC">
<td>{{value.C_name}}</td>
<td>{{value.C_class}}</td>
</tr>
</tbody>
</table>
The format of the data being returned from your API doesn't lend itself well to what you're trying to achieve. You'd have to make assumptions about the the relationship of data between the two arrays. A better structure would be like this:
[
{
"class": 1,
"name": "C_1"
},
{
"class": 2,
"name": "C_2"
},
{
"class": 3,
"name": "C_3"
},
{
"class": 4,
"name": "C_4"
},
{
"class": 5,
"name": "C_5"
}
]
I've created a fiddle which might help, it uses the above data and displays a table with the data: https://jsfiddle.net/9ypkv77x/

how to vertically populate data cells in angularjs

I need to vertically populate data cells with array.
This is a simple html table
<table>
<th>Name</th>
<th>Value</th>
</table>
Existing table:
Name Value
X
Y
Expected output:
Name Value
X 54
Y 48
I need to fill the data cells for value. I have calculated values for it and stored in array. How to populate the values using angularjs?
You want to use ngRepeat to add a new row for each element in your list. See the docs here for examples of how to use this directive.
<tr ng-repeat="row in data">
<td>{{row.name}}</td>
<td>{{row.value}}</td>
</tr>
Use directive for this. Look
var app = angular.module("App", []);
app.controller("AppController", function($scope) {
$scope.data = [1, 2, 3, 4, 5];
}).directive('indexItemTable', function($timeout) {
return {
link: function(scope, element, attrs) {
var data = scope.data;
angular.element(element).find("td").each(function(index, item){
console.log(item)
angular.element(this).parent().append('<td>' + data[index] + '</td>');
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController">
<table index-item-table>
<thead>
<th>Name</th>
<th>Value</th>
</thead>
<tbody>
<tr>
<td>A</td>
</tr>
<tr>
<td>B</td>
</tr>
<tr>
<td>C</td>
</tr>
<tr>
<td>D</td>
</tr>
<tr>
<td>E</td>
</tr>
</tbody>
</table>
</div>