I'm new to web programming and until now i was just creating table with rows which have only one radio button or checkbox etc... But now i have to create a table with rows containing different number of radio buttons. My table has only 2 columns. First column will contain indicator names of rows. Second column will contain radio buttons. So how can i create a cell containing multiple radio buttons. Some row would have 10 or more radio buttons so no one would want to append 10 radio buttons one after another, right?
Edit: I created it like this:
List anketScoreList = [{'id': 'university','text': 'University Score'},
{'id': 'gpa', 'text': 'GPA Score'},
{'id': 'language', 'text': 'Language Score'},
{'id': 'success', 'text': 'Success Score'},
{'id': 'fabric', 'text': 'Fabric Score'},
{'id': 'essay', 'text': 'Essay Score'}];
//Radio values
List score3 = ["1", "1.5", "2"];
List score5 = ["1", "2", "3", "4", "5"];
List score10 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
//creating table body
anketScoreList.forEach((a) {
index += 1;
tbody.append(new Element.tr()
..append(new TableCellElement()..text = index.toString())
..append(new TableCellElement()..append(new LabelElement()
..text = a['text']
..setAttribute('for', a['id'])))
..append(createRadioButtons(a)));
});
Element createRadioButtons(metadata){
List m;
if(metadata['id'] == "university"){
m = score3;
} else if(metadata['id'] == "gpa" || metadata['id'] == "language" ||
metadata['id'] == "essay"){
m = score5;
} else if(metadata['id'] == "success" || metadata['id'] == "fabric"){
m = score10;
}
var td = new TableCellElement();
m.forEach((score){
td.append(new InputElement()
..type = "radio"
..id = metadata['id']
..value = score
..name = metadata['id']
..classes.add("radio")
..onSelect.listen((e){
})
);
});
return td;
}
So is there any easier way to do this? Specially for the lists that i created, assuming there will be other values like genders, types etc... ?
In addition i have another little question. I tried onSelect, onClick on my radio input element but it didn't work. I was just testing with something like x = x + 10 so just removed that code from my onSelect.listen function.
What you could do is create a map for the scores:
Map scores = {
'university': score3,
'gpa':, score5,
'language: score5,
'essay: score5,
'success': score10,
'fabric': score10
};
your createRadioButtons could the be simplified to
Element createRadioButtons(metadata){
// or use a switch
//
// List m;
// switch(metadata['id']) {
// case 'university':
// m = score3;
// break;
// case 'gpa':
// case 'language':
// case 'essay':
// m = score5;
// break;
// case 'success':
// case 'fabric':
// m = score10;
// break;
// }
var td = new TableCellElement();
//m.forEach((score) {
scores[metadata['id']].forEach((score){
td.append(new InputElement()
..type = "radio"
..id = metadata['id']
..value = score
..name = metadata['id']
..classes.add("radio")
..onSelect.listen((e){
})
);
});
return td;
}
For change notification you can use onClick or onChange
http://www.dyn-web.com/tutorials/forms/radio/onclick-onchange.php
Related
So my javascript is bad, but I have a datatables need that I cannot figure out. Relevant code here:
$('#lesson-table').DataTable( {
'data': cleanData,
'paging': false,
'order': [[ 8, 'asc' ], [ 3, 'desc' ], [ 1, 'desc' ]],
initComplete: function () {
// this is where we populate the filter dropdowns
this.api().columns([0,1,2,6,7]).every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo( $(column.header()) )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
column.data().unique().sort().each( function ( d, j ) {
var val = $('<div/>').html(d).text();
select.append( '<option value="' + val + '">' + val + '</option>' );
} );
} );
}
} );
// this removes duplicate dropdown values
var usedNames = {};
$("#lesson-table select > option").each(function () {
if (usedNames[this.value]) {
$(this).remove();
} else {
usedNames[this.value] = this.text;
}
});
So the change that was made in my datasource is that columns 1, the second column in the set, is now a comma separated list of items. Most of the time it is one item say: "Entertainment", but sometimes it can be "Entertainment, Sports, Healthcare" At the moment, it will show that list as an option in my dropdown, but what I need it to do is split them up and then filter by contains...not by exact.
Hope that makes sense. Can explain more if needed.
has data
items = {
0: {id:1,name:'foo'},
1: {id:2,name:'bar'},
2: {id:1,name:'foo'}
};
I wont get counted elements like this
result = {
0: {id:1,name:'foo', count:2},
1: {id:2,name:'bar', count:1}
};
lodash has function _.countBy(items, 'name') it's got {'foo': 2, 'bar':1}, i need id too.
If pure JS approach is acceptable, you can try something like this:
Logiic:
Loop over array and copy the object and add a property count and set it to 0.
Now on every iteration update this count variable.
Using above 2 steps, create a hashMap.
Now loop over hashMap again and convert it back to array.
var items = [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}, {
id: 1,
name: 'foo'
}
];
var temp = items.reduce(function(p,c){
var defaultValue = {
name: c.name,
id: c.id,
count: 0
};
p[c.name] = p[c.name] || defaultValue
p[c.name].count++;
return p;
}, {});
var result = [];
for( var k in temp ){
result.push(temp[k]);
}
console.log(result)
I want to display "population" of various countries through the years in the same line chart. The data displayed is based on selections from a multi-select dropdown "Countries". Underlying Data Table has 3 columns:
Year, Country, Population
2012,countryA,33
2013,countryA,35
2014,countryA,40
2012,countryB,65
2013,countryB,70
2014,countryB,75
2012,countryC,15
2013,countryC,20
2014,countryC,25
I am trying to create a pivoted Data View from the underlying Data Table
The code I am using is:
function drawLineChart() {
var arr = $('#country').val();
var lineChartJson = $.ajax({
url: "../json/lineChart.json",
dataType: "json",
async: false
}).responseText;
var lineChartData = new google.visualization.DataTable(lineChartJson);
var view = new google.visualization.DataView(lineChartData);
var viewCols = [0];
for(var i = 0; i < arr.length; i++) {
var viewCols1 = [{
type: 'number',
label: arr[i],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[i]) ? dt.getValue(row, 2) : null;
}
}];
viewCols = viewCols.concat(viewCols1);
}
view.setColumns(viewCols);
var aggCols = [{
column: 1,
type: 'number',
label: view.getColumnLabel(1),
aggregation: google.visualization.data.sum
}];
for(var i = 2; i < 4; i++) {
var aggCols1 = [{
column: i,
type: 'number',
label: view.getColumnLabel(i),
aggregation: google.visualization.data.sum
}];
aggCols = aggCols.concat(aggCols1);
}
var pivotedData = google.visualization.data.group(view, [0], aggCols);
But this does not seem to work as expected and I just get 1 Line in the chart with values for all countries added up (although I can see the legend for 3 countries)
On the other hand if I set my View columns as below, it works as expected.
view.setColumns([0, {
type: 'number',
label: arr[0],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[0]) ? dt.getValue(row, 2) : null;
}
}, {
type: 'number',
label: arr[1],
calc: function (dt, row) {
// return values of C only for the rows where B = "bar"
return (dt.getValue(row, 1) == arr[1]) ? dt.getValue(row, 2) : null;
}
}, {
type: 'number',
label: arr[2],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[2]) ? dt.getValue(row, 2) : null;
}
}]);
What is going wrong in the loop? Is something wrong with "concat" in the loop where I am creating View Columns? I also saw the viewCols array by using console.log and it seems to have the right elements
I was trying to follow the below post:
Creating pivoted DataView from existing google charts DataTable object
the problem has to do with scope
arr[i] is undefined within calc: function (dt, row)
here is another way to pivot the data...
google.charts.load('current', {
callback: function () {
var arr = [
'countryA',
'countryB',
'countryC'
];
var lineChartData = google.visualization.arrayToDataTable([
['Year', 'Country', 'Population'],
[2012,'countryA',33],
[2013,'countryA',35],
[2014,'countryA',40],
[2012,'countryB',65],
[2013,'countryB',70],
[2014,'countryB',75],
[2012,'countryC',15],
[2013,'countryC',20],
[2014,'countryC',25]
]);
// sort by year
lineChartData.sort([{column: 0}]);
// get unique countries
var countryGroup = google.visualization.data.group(
lineChartData,
[1]
);
// build country data table
var countryData = new google.visualization.DataTable({
cols: [
{label: 'Year', type: 'number'},
]
});
// add column for each country
for (var i = 0; i < countryGroup.getNumberOfRows(); i++) {
countryData.addColumn(
{label: countryGroup.getValue(i, 0), type: 'number'}
);
}
// add row for each year / country
var rowYear;
var rowIndex;
for (var i = 0; i < lineChartData.getNumberOfRows(); i++) {
if (rowYear !== lineChartData.getValue(i, 0)) {
rowYear = lineChartData.getValue(i, 0);
rowIndex = countryData.addRow();
countryData.setValue(rowIndex, 0, rowYear);
}
for (var x = 1; x < countryData.getNumberOfColumns(); x++) {
if (countryData.getColumnLabel(x) === lineChartData.getValue(i, 1)) {
countryData.setValue(rowIndex, x, lineChartData.getValue(i, 2));
}
}
}
// draw agg table
new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'table-div',
dataTable: countryData
}).draw();
// draw line chart
new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'chart-div',
dataTable: countryData
}).draw();
},
packages: ['corechart', 'table']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="table-div"></div>
<div id="chart-div"></div>
I could figure out the problem with my code above.
"calc" is the callback function in loop. So only last value of loop variable "i" is visible within the loop.
Putting a wrapper function fixes it:
for(var i = 0; i <= arr.length; i++)(function(i) {
var viewCols1 = [{
type: 'number',
label: arr[i],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[i]) ? dt.getValue(row, 2) : null;
}
}];
viewCols = viewCols.concat(viewCols1);
})(i);
I have placed a textbox widget inside grid cell by using formatter. However, I cannot move my cursor around nor select text inside the textbox.
E.g.
http://jsfiddle.net/g33m9/69/
Does anyone know how to fix this?
Thanks
You need to set the column as 'editable' so that the Grid component will know how to handle keypressed events. So a modification to the layout is in order
from
var layout = [[
{name: 'Column 1', field: 'col1'},
{name: 'Column 2', field: 'col2', width:'200px', formatter: func}
]];
to
var layout = [[
{name: 'Column 1', field: 'col1'},
{name: 'Column 2', field: 'col2', width:'200px', formatter: func, editable: true}
]];
Edit state activates by doubleclick.
Now, OP wants it to be a fully bloated widget, popping up in the editable state. For this to be scaleable up with any number of rows/columns i will restrict this to the edit state, so that the value simply shows text but once double-clicked it will pop a FilteringSelect. Same principle goes with the dijit widget ValidationTextBox.
Currently (1.7.2) the possible celltypes are:
dojox.grid.cells.Bool
dojox.grid.cells.ComboBox
dojox.grid.cells.DateTextBox
dojox.grid.cells.Select
Catch me SEO:
example of custom dojox.grid cellType widget - semi-programmatic
First step - create some data
var i = 0,
data = {
identifier: 'id',
items: [
{ id: i, value: 'val'+i++},
{ id: i, value: 'val'+i++},
{ id: i, value: 'val'+i++},
{ id: i, value: 'val'+i++}
]
},
// The item label which holds visible value and which holds the value to represent
searchAttr = 'value',
valueAttr = data.identifier,
// The store to use for select widget
store = new dojo.data.ItemFileReadStore({ data: data }),
// And the options, reassembling the valid options we will present in dropdown
// Used when cellType is dojox.grid.cells.Select to name the allowable options
options = [];
dojo.forEach(data.items, function(it) { options.push(it[searchAttr])});
Tricky part - Define a cellType
Lets extend the existing dojox.grid.cells.Cell, it has two key features - an edit-state-formatter and the default-formatter. The default would work just fine. Last but not least, we'll override the '_finish' function allthough allow the Cell to process its own definition too.
var whenIdle = function( /*inContext, inMethod, args ...*/ ) {
setTimeout(dojo.hitch.apply(dojo, arguments), 0);
};
var FilteringSelectCell = declare("dojox.grid.cells.FilteringSelect", [dojox.grid.cells.Cell], {
options: null,
values: null,
_destroyOnRemove: true,
constructor: function(inCell){
this.values = this.values || this.options;
},
selectMarkupFactory: function(cellData, rowIndex) {
var h = ['<select data-dojo-type="dijit.form.FilteringSelect" id="deleteme' + rowIndex + '" name="foo">'];
for (var i = 0, o, v;
((o = this.options[i]) !== undefined) && ((v = this.values[i]) !== undefined); i++) {
v = v.replace ? v.replace(/&/g, '&').replace(/</g, '<') : v;
o = o.replace ? o.replace(/&/g, '&').replace(/</g, '<') : o;
h.push("<option", (cellData == v ? ' selected' : ''), ' value="' + v + '"', ">", o, "</option>");
}
h.push('</select>');
return h;
},
textMarkupFactory: function(cellData, rowIndex) {
return ['<input class="dojoxGridInput" id="deleteme' + rowIndex + '" data-dojo-type="dijit.form.ValidationTextBox" type="text" value="' + cellData + '">']
},
// #override
formatEditing: function(cellData, rowIndex) {
this.needFormatNode(cellData, rowIndex);
var h = (cellData == "W1")
? this.textMarkupFactory(cellData, rowIndex)
: this.selectMarkupFactory(cellData, rowIndex);
// a slight hack here, i had no time to figure out when the html would actually be inserted to the '<td>' so.. Use 'debugger' statement and track function to hook into
whenIdle(function() {
dojo.parser.parse(dojo.byId('deleteme' + rowIndex).parentNode);
var w = dijit.byId('deleteme' + rowIndex);
w.focus()
});
return h.join('');
},
// clean up avoiding multiple widget definitions 'hanging'
_finish: function(inRowIndex) {
this.inherited(arguments)
dijit.byId('deleteme' + inRowIndex).destroy();
},
// needed to read the value properly, will work with either variant
getValue: function(rowIndex) {
var n = this.getEditNode(rowIndex);
n = dijit.getEnclosingWidget(n);
return n.get("value");
}
});
Last bit, a new layout
var layout = [[
{ name: 'Column 1', field: 'col1' },
{ name: 'Column 2', field: 'col2',
cellType: FilteringSelectCell, options: options, editable: true
}
]];
Running sample here http://jsfiddle.net/dgbxw/1/
I have bar chart, whose x-axis labels is generated dynamically from db, I am getting these values through ajax call data
'{value:1,text:"x"},{value:2,text:"Vikash"},{value:3,text:"y"},{value:4,text:"z"}'.
How to pass these values to label parameter. I tried passing it as an array and also as json but nothing seems to work.. Any ideas..
Here is my code:
makeBarChart=function() {
animChart = new dojox.charting.Chart2D("animChart");
animChart.setTheme(dojox.charting.themes.MiamiNice)
.addAxis("x",{
labels: [ myLabelSeriesarray ], gap: 20}).
addAxis("y", {
vertical: true,
fixLower: "major",
fixUpper: "major",
includeZero: true
}).
addPlot("default", {
type: "ClusteredColumns",
gap: 10
}).
addSeries("Series A", closedSeries).
addSeries("Series B", othersSeries).
render();
};
dojo.addOnLoad(makeBarChart);
jsp code:
var labelDis = new Array(pieData.length); // pieData is the JSON value getting from Java
for(var i = 0;i<pieData.length;i++){
labelDis[i] = new Array(2);
labelDis[i]['value'] = i + 1;
labelDis[i]['text'] = pieData[i]['axis'];
}
Java/Servlet code:
JSONObject jSONObject = new JSONObject();
jSONObject.put("axis", "value from database");
jSONArray.put(jSONObject);
out.print(jSONArray.toString());
Suppose you have received data in json format through ajax call and you want to create dynamic labels using that data.
var jsonArray= ["label1","label2","label3"];
var labelsArray = [];
for (var i = 0; i < jsonArray.length; i++,) {
var obj = {};
obj.value = i;
obj.text = jsonArray[i];
labelsArray.push(obj);
}
Set the labels in x Axis to this labelsArray
this.chart1.addAxis("x", {
title: "Collection Date",
titleOrientation: "away",
titleGap:20,
labels:labelsArray
})