I want to make the value ("v") appear on rollover using the standard HTML title attribute (among placing other attributes for other purposes).
The visualization docs say this can be done via the "p Property". However, from my code below ONLY className get rendered as an attribute in the td tags.
Given the "style" attribute is an example directly copied from the documentation - https://developers.google.com/chart/interactive/docs/reference#cell_object, I assume i'm doing something wrong. Can you see what it might be?
Cell Object:
{
"v": "\/?s=mi+shampoo+adecuado?&submit=Buscar",
"f": "\/?s=m...uscar",
"p": {
"title": "\/?s=mi+shampoo+adecuado?&submit=Buscar",
"style": "border: 1px solid green;",
"className": "randomCls",
"data-title": "\/?s=mi+shampoo+adecuado?&submit=Buscar"
}
},
visualization code
var table = new google.visualization.DataTable();
for(var j=0; j < data[0].length; j++) {
table.addColumn(typeof data[1][j].v,data[0][j]);
}
data.shift();
table.addRows(data);
var ac = new google.visualization.Table(graph.get(0)); // AreaChart
ac.draw(table, {
backgroundColor: {fill:'#d4d4d4'},
colors : ["#999999",'#004087']
});
The Table visualization only supports "className" and "style" properties for cells. If you need to apply additional HTML properties to cells, you will have to write custom code to parse the <table> element created by the visualization and add the properties to <td> elements manually. If you can put the properties on the cell contents instead of the <td> elements, you can set the formatted values of the cells to contain whatever HTML you need.
Thank you #asgallant for clarification on the supported attributes. So, here's the code accordingly:
var wrapper = new google.visualization.ChartWrapper({
chartType: 'Table',
dataTable: table,
options: {backgroundColor: {fill:'#d4d4d4'}, colors : ["#999999",'#004087'], allowHtml:true},
containerId: 'widget'+wid
});
google.visualization.events.addListener(wrapper, 'ready', function() {
graph.find(".tipFlag").each(function(){
var v = $(this).attr("class").substring("tipFlag ".length);
$(this).attr("title", v);
});
});
wrapper.draw();
where the new cell objects look like:
{
"v": "\/?s=mi+shampoo+adecuado?&submit=Buscar",
"f": "\/?s=m...uscar",
"p": {
"className": "tipFlag \/?s=mi+shampoo+adecuado?&submit=Buscar",
}
},
Related
I'm using kendo grid in my ember app. I have introduced export to Excel in kendo. But after downloading the Excel sheet, I want to resize the width of the column within the Excel sheet .. how to deal with it?
Here is my code:
myGrid.bind("excelExport", function (e) {
// console.log(">>"+);
var str = e.sender.columns;
var title = str.map(function(d) { return d['title']; }).indexOf('Action');
var documentKey = str.map(function(d) { return d['field']; }).indexOf('documentKey');
if (!exportFlag) {
e.sender.hideColumn(documentKey);
e.sender.hideColumn(title);
e.preventDefault();
exportFlag = true;
setTimeout(function () {
e.sender.saveAsExcel();
});
} else {
e.sender.showColumn(documentKey);
e.sender.showColumn(title);
exportFlag = false;
}
});
If you want to modify the format of cells during export to excel, you can setup a kendo.ooxml.Workbook.
This way you can modify the format of each cell, row, column etc by building up an array containing columns, rows and cells:
var workbook = new kendo.ooxml.Workbook({
sheets: [
{
columns: [ { width: 100 }, { width: 200 } ],
rows: [
{
cells: [
{ value: "this column is 100px" }, { value: "this column is 200px" }
]
}
]
}
]
});
In your case you will need to build up the data you wish to send to the workbook based on what is in the grid datasource.
I have attached a Dojo example to demonstrate an example of all the above in action.
I am making a custom legend for a Google Charts ColumnChart. I would like it to have the same behavior as the native legend. The native legend has behavior on click and mouseover. When a legend key is clicked, the column of values is selected. I can do this in my custom legend by calling
myChartWrapper.getChart().setSelection([{column: 4}]);
When a legend key is moused over, the column of values gets an outline. I would like to trigger that same outline when mousing over the key in my custom legend.
Is there a way to set that focussed column similar to setting the selection?
I thought I might be able to do it by calling events.trigger(), but I can't get anything to happen at all with that. For example, these don't seem to do anything.
// did nothing:
google.visualization.events.trigger(myChartWrapper, 'select', [{column: 4}]);
// did nothing:
google.visualization.events.trigger(myChartWrapper.getChart(), 'onmouseover', [{column: 4}]);
attempt to cause focus appearance via event trigger
google.charts.load('current', {
callback: function () {
var dataTable = new google.visualization.DataTable({
cols: [
{label: 'Month', type: 'string'},
{label: 'Amount', type: 'number'}
],
rows: [
{c:[{v: 'April'}, {v: 279899811.34}]},
{c:[{v: 'May'}, {v: 205855811}]},
{c:[{v: 'June'}, {v: 10009811}]},
{c:[{v: 'July'}, {v: 79979811}]},
{c:[{v: 'August'}, {v: 175789911}]},
{c:[{v: 'September'}, {v: 99899811}]},
{c:[{v: 'October'}, {v: 149899811}]},
{c:[{v: 'November'}, {v: 80899811}]},
{c:[{v: 'December'}, {v: 60899811}]},
{c:[{v: 'January'}, {v: 225899811}]},
{c:[{v: 'February'}, {v: 148899811}]},
{c:[{v: 'March'}, {v: 150899811}]}
]
});
var chartWrapper = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
containerId: 'chart_div',
dataTable: dataTable,
options: {
legend: {
position: 'bottom'
},
vAxis: {
format: 'short'
}
}
});
google.visualization.events.addOneTimeListener(chartWrapper, 'ready', function () {
// mouseover for custom div
document.getElementById('hover_div').addEventListener('mouseover', function () {
// trigger onmouseover for chart, pass props
google.visualization.events.trigger(chartWrapper.getChart(), 'onmouseover', {
'column': 1,
'row': null,
'test': 'over'
});
}, false);
// mouseout
document.getElementById('hover_div').addEventListener('mouseout', function () {
google.visualization.events.trigger(chartWrapper.getChart(), 'onmouseout', {
'column': 1,
'row': null,
'test': 'out'
});
}, false);
// chart event listeners
google.visualization.events.addListener(chartWrapper.getChart(), 'onmouseover', function (props) {
document.getElementById('msg_div').innerHTML = JSON.stringify(props);
});
google.visualization.events.addListener(chartWrapper.getChart(), 'onmouseout', function (props) {
document.getElementById('msg_div').innerHTML = JSON.stringify(props);
});
});
chartWrapper.draw();
},
packages:['controls', 'corechart']
});
#hover_div {
background-color: magenta;
border: 1px solid lime;
color: cyan;
height: 200px;
text-align: center;
width: 200px;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
<div id="hover_div">HOVER THIS DIV</div>
<div id="msg_div"></div>
Here's a hacky way to highlight bars in a bar chart. It's not a proper solution because it doesn't trigger the chart's native highlight. Instead, it's a way to create your own highlight by manipulating the stroke of the rects with jQuery. I approximated the highlight by setting the stroke to be 2px and grey. The actual highlight appears to be a blur effect with svg. To enhance the highlighting, I applied a slight transparency to the rects themselves.
On mouseover, I get the set of rects for all the bars, and then the subset for the particular column. It turned out to be tricky to get the right set of rects on mouseover, because the user might have selected a bar. When you select a bar with the mouse (i.e., click on it), the rect for it moves around, so you have to select the rects anew each time you mouseover. Plus selecting adds another rect for the white outline, which needs to be filtered out.
For the custom legend, I used colors from the Google Charts palette, which you get here.
I didn't add the part that would trigger a selection on clicking the legend. For that, I will follow this method.
The solution also only works with bar charts. You'd have to do something else with line charts, or other types. So the value of this solution may be limited.
google.charts.load('current', {packages: ['corechart']});
google.charts.setOnLoadCallback(draw_chart);
function draw_chart() {
// Create DataTable object from DataTable constructor or arrayToDatable()
var data = new google.visualization.DataTable({"rows":[{"c":[{"v":"Sacramento"},{"v":97},{"v":79},{"v":67},{"v":100}]},{"c":[{"v":"Montpelier"},{"v":96},{"v":74},{"v":32},{"v":96}]},{"c":[{"v":"Juneau"},{"v":24},{"v":44},{"v":54},{"v":64}]},{"c":[{"v":"Montgomery"},{"v":26},{"v":69},{"v":51},{"v":56}]},{"c":[{"v":"Little Rock"},{"v":87},{"v":69},{"v":78},{"v":41}]}],"cols":[{"type":"string","id":"cities","label":"cities"},{"type":"number","id":"A","label":"A"},{"type":"number","id":"B","label":"B"},{"type":"number","id":"C","label":"C"},{"type":"number","id":"D","label":"D"}]});
// Add formatters, if any
// Create ChartWrapper
var my_chart = new google.visualization.ChartWrapper({
"containerId": "chart_id",
"dataTable": data,
"chartType": "ColumnChart",
"options": {"bar": {"groupWidth": 67}, "chartArea": {"width": 440, "top": 20, "height": 295, "left": 60}, "height": 375, "width": 500, "fontSize": 12, "legend": "none"}
});
var bar_rect_set;
var num_rows = 5;
var num_cols = 4;
var num_series = num_rows * num_cols;
var parent_g;
function get_bar_rect_set() {
// get all the rects in the parent except for the white outline rects
// on selected bars, if any.
bar_rect_set = parent_g.find('rect[fill!="#ffffff"]');
}
google.visualization.events.addOneTimeListener(my_chart, 'ready', function () {
// Get an initial collection of the bar rects, along with their parent.
// Hereafter, get the bar rects with the method above.
// get all rects three layers down, including gridlines and axis
var g_set_1 = $("svg g g g rect");
// slice out the gridlines at the beginning and the axis line at the end
bar_rect_set = g_set_1.slice(g_set_1.length - num_series - 1, g_set_1.length - 1);
parent_g = $(bar_rect_set[0]).parent();
});
my_chart.draw();
function highlight_bars(series_num) {
if (series_num > num_cols - 1) {
return false;
}
get_bar_rect_set();
var start_index = series_num * num_rows;
var end_index = start_index + num_rows;
var series_g_set = bar_rect_set.slice(start_index, end_index)
var styles = {'stroke-width': "1.5px", "stroke": "#AAAAAA", "opacity": .8};
series_g_set.css(styles);
}
function remove_highlight() {
var styles = {'stroke-width': "0", "opacity": 1};
bar_rect_set.css(styles);
}
$("#legend tr").each(function(index, row) {
$(row).mouseover(function() {
highlight_bars(index);
}).mouseout(function() {
remove_highlight();
});
});
}
.color_bar {
width:24px;
height:12px;
margin-right:5px;
vertical-align:middle;
}
#legend td {
font-size:12;
height:19px;
font-family:"Arial";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<table id="legend">
<tr>
<td><div class='color_bar' style="background-color:#3366cc"></div></td>
<td>A</td>
</tr>
<tr>
<td><div class='color_bar' style="background-color:#dc3912"></div></td>
<td>B</td>
</tr>
<tr>
<td><div class='color_bar' style="background-color:#ff9900"></div></td>
<td>C</td>
</tr>
<tr>
<td><div class='color_bar' style="background-color:#109618"></div></td>
<td>D</td>
</tr>
</table>
<div id="chart_id" ></div>
I would like a Google Visualization Table with a fixed width and td cells that wrap. When I specify a width in the draw method a horizontal scroll bar appears. Rather than this, I want wrapping of cells.
This jsfiddle is a working example. In this example I would like for the first column to wrap. I have tried adding a class with word-wrap: break-word;. But this does not work.
Here is relevant js:
function drawChart() {
var cssClassNames = {
'tableCell': 'googlecell'
};
var datatable = new google.visualization.DataTable();
datatable.addColumn('string', 'Keyword', 'col1');
datatable.addColumn('number', 'Pageviews');
datatable.addColumn('number', 'Secs.');
datatable.addRows(3);
datatable.setCell(0, 0, '(not set)');
datatable.setCell(0, 1, 20308);
datatable.setCell(0, 2, 68.74);
datatable.setCell(1, 0, '(not provided)');
datatable.setCell(1, 1, 14410);
datatable.setCell(1, 2, 49.99);
datatable.setCell(2, 0, 'product_type_l1==sdsssijven&+product_type_l2==*');
datatable.setCell(2, 1, 3838);
datatable.setCell(2, 2, 48.35);
var table = new google.visualization.Table(document.getElementById('table_div'));
table.draw(datatable, {
showRowNumber: false,
'allowHtml': true,
'cssClassNames': cssClassNames,
width: 400
});
}
google.load("visualization", "1", {
packages: ["corechart", "table"]
});
google.setOnLoadCallback(drawChart);
And relevant css:
.googlecell {
word-wrap: break-word;
}
What about:
.googlecell {
word-break: break-all;
}
Is that what you are after? (demo)
I am trying to create an interface for traversing tables in a relation database. Each select represents a column. If the column is a foreign key, a new select is added to the right. This keeps happening for every foreign key that the user accesses. The number of selects is dynamic.
I made a buggy implementation that has code that manually adds and removes select views. I think it probably can be replaced with better Ember code (some kind of array object maybe?), I'm just not sure how to best use the framework for this problem.
Here's my JSBin http://jsbin.com/olefUMAr/3/edit
HTML:
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Ember template" />
<meta charset=utf-8 />
<title>JS Bin</title>
<script src="http://code.jquery.com/jquery-1.9.0.js"></script>
<script src="http://builds.emberjs.com/handlebars-1.0.0.js"></script>
<script src="http://builds.emberjs.com/tags/v1.1.2/ember.js"></script>
</head>
<body>
<script type="text/x-handlebars" data-template-name="my_template">
{{view fieldSelects}}
</script>
<div id="main"></div>
</body>
</html>
JavaScript:
App = Ember.Application.create();
var TemplatedViewController = Ember.Object.extend({
templateFunction: null,
viewArgs: null,
viewBaseClass: Ember.View,
view: function () {
var controller = this;
var viewArgs = this.get('viewArgs') || {};
var args = {
template: controller.get('templateFunction'),
controller: controller
};
args = $.extend(viewArgs, args);
return this.get('viewBaseClass').extend(args);
}.property('templateFunction', 'viewArgs'),
appendView: function (selector) {
this.get('view').create().appendTo(selector);
},
appendViewToBody: function () {
this.get('view').create().append();
}
});
var DATA = {};
DATA.model_data = {
"Book": {
"fields": [
"id",
"title",
"publication_year",
"authors"
],
"meta": {
"id": {},
"title": {},
"publication_year": {},
"authors": {
"model": "Author"
}
}
},
"Author": {
"fields": [
"id",
"first_name",
"last_name",
"books"
],
"meta": {
"id": {},
"first_name": {},
"last_name": {},
"books": {
"model": "Book"
}
}
}
};
var Controller = TemplatedViewController.extend({
view: function () {
var controller = this;
return this.get('viewBaseClass').extend({
controller: controller,
templateName: 'my_template'
});
}.property(),
selectedFields: null,
fieldSelects: function () {
var filter = this;
return Ember.ContainerView.extend({
controller: this,
childViews: function () {
var that = this;
var selectedFields = filter.get('selectedFields');
var ret = [];
var model = 'Book';
selectedFields.forEach(function (item, index, enumerable) {
var selection = item;
if (model) {
var select = that.makeSelect(model, that.getPositionIndex(), selection, true).create();
ret.pushObject(select);
model = DATA.model_data[model].meta[selection].model;
}
});
return ret;
}.property(),
nextPositionIndex: 0,
incrementPositionIndex: function () {
this.set('nextPositionIndex', this.get('nextPositionIndex') + 1);
},
getPositionIndex: function () {
var index = this.get('nextPositionIndex');
this.incrementPositionIndex();
return index;
},
setNextPositionIndex: function (newValue) {
this.set('nextPositionIndex', newValue+1);
},
makeSelect: function (modelName, positionIndex, selection, isInitializing) {
var view = this;
return Ember.Select.extend({
positionIndex: positionIndex,
controller: filter,
content: DATA.model_data[modelName].fields,
prompt: '---------',
selection: selection || null,
selectionChanged: function () {
var field = this.get('selection');
// Remove child views after this one
var lastIndex = view.get('length') - 1;
if (lastIndex > this.get('positionIndex')) {
view.removeAt(this.get('positionIndex')+1, lastIndex-this.get('positionIndex'));
view.setNextPositionIndex(this.get('positionIndex'));
}
if (! isInitializing && DATA.model_data[modelName].meta[field].model) {
var relatedModel = DATA.model_data[modelName].meta[field].model;
view.pushObject(view.makeSelect(relatedModel, view.getPositionIndex()).create());
}
// Reset ``isInitializing`` after the first run
if (isInitializing) {
isInitializing = false;
}
var selectedFields = [];
view.get('childViews').forEach(function (item, index, enumerable) {
var childView = item;
var selection = childView.get('selection');
selectedFields.pushObject(selection);
});
filter.set('selectedFields', selectedFields);
}.observes('selection')
});
}
});
}.property()
});
var controller = Controller.create({
selectedFields: ['authors', 'first_name']
});
$(function () {
controller.appendView('#main');
});
Approach:
I would tackle this problem using an Ember Component.
I have used a component because it will be:
Easily reusable
The code is self contained, and has no external requirements on any of your other code.
We can use plain javascript to create the view. Plain javascript should make the code flow easier to understand (because you don't have to know what Ember is doing with extended objects behind the scenes), and it will have less overhead.
Demo:
I have created this JSBin here, of the code below.
Usage
Add to your handlebars template:
{{select-filter-box data=model selected=selected}}
Create a select-filter-box tag and then bind your model to the data attribute, and your selected value array to the selected attribute.
The application:
App = Ember.Application.create();
App.ApplicationController = Ember.ObjectController.extend({
model: DATA.model_data,
selected: ['Author','']
});
App.SelectFilterBoxComponent = Ember.Component.extend({
template: Ember.Handlebars.compile(''), // Blank template
data: null,
lastCount: 0,
selected: [],
selectedChanged: function(){
// Properties required to build view
var p = this.getProperties("elementId", "data", "lastCount", "selected");
// Used to gain context of controller in on selected changed event
var controller = this;
// Check there is at least one property. I.e. the base model.
var length = p.selected.length;
if(length > 1){
var currentModelName = p.selected[0];
var type = {};
// This function will return an existing select box or create new
var getOrCreate = function(idx){
// Determine the id of the select box
var id = p.elementId + "_" + idx;
// Try get the select box if it exists
var select = $("#" + id);
if(select.length === 0){
// Create select box
select = $("<select id='" + id +"'></select>");
// Action to take if select is changed. State is made available through evt.data
select.on("change", { controller: controller, index: idx }, function(evt){
// Restore the state
var controller = evt.data.controller;
var index = evt.data.index;
var selected = controller.get("selected");
// The selected field
var fieldName = $(this).val();
// Update the selected
selected = selected.slice(0, index);
selected.push(fieldName);
controller.set("selected", selected);
});
// Add it to the component container
$("#" + p.elementId).append(select);
}
return select;
};
// Add the options to the select box
var populate = function(select){
// Only populate the select box if it doesn't have the correct model
if(select.data("type")==currentModelName)
return;
// Clear any existing options
select.html("");
// Get the field from the model
var fields = p.data[currentModelName].fields;
// Add default empty option
select.append($("<option value=''>------</option>"));
// Add the fields to the select box
for(var f = 0; f < fields.length; f++)
select.append($("<option>" + fields[f] + "</option>"));
// Set the model type on the select
select.data("type", currentModelName);
};
var setModelNameFromFieldName = function(fieldName){
// Get the field type from current model meta
type = p.data[currentModelName].meta[fieldName];
// Set the current model
currentModelName = (type !== undefined && type.model !== undefined) ? type.model : null;
};
// Remove any unneeded select boxes. I.e. where the number of selects exceed the selected length
if(p.lastCount > length)
for(var i=length; i < p.lastCount; i++)
$("#" + p.elementId + "_" + i).remove();
this.set("lastCount", length);
// Loop through all of the selected, to build view
for(var s = 1; s < length; s++)
{
// Get or Create select box at index s
var select = getOrCreate(s);
// Populate the model fields to the selectbox, if required
populate(select);
// Current selected
var field = p.selected[s];
// Ensure correct value is selected
select.val(field);
// Set the model for next iteration
setModelNameFromFieldName(field);
if(s === length - 1 && type !== undefined && type.model !== undefined)
{
p.selected.push('');
this.notifyPropertyChange("selected");
}
}
}
}.observes("selected"),
didInsertElement: function(){
this.selectedChanged();
}
});
How it works
The component takes the two parameters model and selected then binds an observer onto the selected property. Any time the selection is changed either through user interaction with the select boxes, or by the property bound to selected the view will be redetermined.
The code uses the following approach:
Determine if the selection array (selected) is greater than 1. (Because the first value needs to be the base model).
Loop round all the selected fields i, starting at index 1.
Determine if select box i exists. If not create a select box.
Determine if select box i has the right model fields based on the current populated model. If yes, do nothing, if not populate the fields.
Set the current value of the select box.
If we are the last select box and the field selected links to a model, then push a blank value onto the selection, to trigger next drop down.
When a select box is created, an onchange handler is hooked up to update the selected value by slicing the selected array right of the current index and adding its own value. This will cause the view to change as required.
A property count keeps track of the previous selected's length, so if a change is made to a selection that decreases the current selected values length, then the unneeded select boxes can be removed.
The source code is commented, and I hope it is clear, if you have any questions of queries with how it works, feel free to ask, and I will try to explain it better.
Your Model:
Having looked at your model, have you considered simplifying it to below? I appreciate that you may not be able to, for other reasons beyond the scope of the question. Just a thought.
DATA.model_data = {
"Book": {
"id": {},
"title": {},
"publication_year": {},
"authors": { "model": "Author" }
},
"Author": {
"id": {},
"first_name": {},
"last_name": {},
"books": { "model": "Book" }
}
};
So field names would be read off the object keys, and the value would be the meta data.
I hope you find this useful. Let me know if you have any questions, or issues.
The Controller:
You can use any controller you want with this component. In my demo of the component I used Ember's built in ApplicationController for simplicity.
Explaination of notifyPropertyChange():
This is called because when we are inserting an new string into the selected array, using the push functionality of arrays.
I have used the push method because this is the most efficient way to add a new entry into an existing array.
While Ember does have a pushObject method that is supposed to take care of the notification as well, I couldn't get it to honour this. So this.notifyPropertyChange("selected"); tells Ember that we updated the array. However I'm hoping that's not a dealbreaker.
Alternative to Ember Component - Implemented as a View
If you don't wish to use it in Component format, you could implement it as a view. It ultimately achieves the same goal, but this may be a more familiar design pattern to you.
See this JSBin for implementation as a View. I won't include the full code here, because some of it is the same as above, you can see it in the JSBin
Usage:
Create an instance of App.SelectFilterBoxView, with a controller that has a data and selected property:
var myView = App.SelectFilterBoxView.create({
controller: Ember.Object.create({
data: DATA.model_data,
selected: ['Author','']
})
});
Then append the view as required, such as to #main.
myView.appendTo("#main");
Unfortunately your code doesn't run, even after adding Ember as a library in your JSFiddle, but ContainerView is probably what you're looking for: http://emberjs.com/api/classes/Ember.ContainerView.html as those views can be dynamically added/removed.
this.$().remove() or this.$().append() are probably what you're looking for:
Ember docs.
Consider drawing a column chart and I don't get any data from the data source, How do we draw an empty chart instead of showing up a red colored default message saying "Table has no columns"?
What I do is initialize my chart with 1 column and 1 data point (set to 0). Then whenever data gets added I check if there is only 1 column and that it is the dummy column, then I remove it. I also hide the legend to begin so that it doesn't appear with the dummy column, then I add it when the new column gets added.
Here is some sample code you can plug in to the Google Visualization Playground that does what I am talking about. You should see the empty chart for 2 seconds, then data will get added and the columns will appear.
var data, options, chart;
function drawVisualization() {
data = google.visualization.arrayToDataTable([
['Time', 'dummy'],
['', 0],
]);
options = {
title:"My Chart",
width:600, height:400,
hAxis: {title: "Time"},
legend : {position: 'none'}
};
// Create and draw the visualization.
chart = new google.visualization.ColumnChart(document.getElementById('visualization'));
chart.draw(data,options);
setTimeout('addData("12:00",10)',2000);
setTimeout('addData("12:10",20)',3000);
}
function addData(x,y) {
if(data.getColumnLabel(1) == 'dummy') {
data.addColumn('number', 'Your Values', 'col_id');
data.removeColumn(1);
options.legend = {position: 'right'};
}
data.addRow([x,y]);
chart.draw(data,options);
}
A even better solution for this problem might be to use a annotation column instead of a data column as shown below. With this solution you do not need to use any setTimeout or custom function to remove or hide your column. Give it a try by pasting the given code below into Google Code Playground.
function drawVisualization() {
var data = google.visualization.arrayToDataTable([
['', { role: 'annotation' }],
['', '']
]);
var ac = new google.visualization.ColumnChart(document.getElementById('visualization'));
ac.draw(data, {
title : 'Just a title...',
width: 600,
height: 400
});
}
The way I did this was by disabling the pie slices, turning off tooltips, stuffing in a pretend value and making it gray. I'm sure there are more clever ways to do this, but this worked for me where the other methods didn't.
The only drawback is that it sets both items in the legend to gray as well. I think you could perhaps just add a third item, and make it invisible on the legend only. I liked this way though.
function drawChart() {
// Define the chart to be drawn.
data = new google.visualization.DataTable();
data.addColumn({type: 'string', label: 'Result'});
data.addColumn({type: 'number', label: 'Count'});
data.addRows([
['Value A', 0],
['Value B', 0]
]);
var opt_pieslicetext = null;
var opt_tooltip_trigger = null;
var opt_color = null;
if (data.getValue(1,1) == 0 && data.getValue(0,1) == 0) {
opt_pieslicetext='none';
opt_tooltip_trigger='none'
data.setCell(1,1,.1);
opt_color= ['#D3D3D3'];
}
chart = new google.visualization.PieChart(document.getElementById('mydiv'));
chart.draw(data, {sliceVisibilityThreshold:0, pieSliceText: opt_pieslicetext, tooltip: { trigger: opt_tooltip_trigger }, colors: opt_color } );
}