AmCharts: How do i check if graph is hidden? - javascript

I got ONE balloon only in my chart, and I want to check if not only the graph it belongs to is hidden, but if ANY graph is hidden. How do I check this attribute?
function adjustBalloonText(graphDataItem, graph){
var data = graphDataItem.dataContext;
var date = ""; //some kind of getDateInScrollbar here
console.log(graphDataItem);
var distance = data.distance; // some kind of getGraphsValue here
var duration = ""; // some kind of getGraphsValue here as well
return distance;
}
Please help me out.

Related

Unable to pass value from C# to amcharts JavaScript function

I created a chart with the help of amCharts that shows temperature from the examples on their site. The chart displayed correctly.
Now I am getting the temperature from a database with C# and I am trying to pass the value to the function where temperature was hard coded, so I get dynamic values. However, I just get the chart and the needle is still at 0 and does not show the temperature.
I have tried 3 ways so far:
I used a hidden field, assigned the value to hidden field in C# and called the JavaScript function showing the charts. It only shows chart. The needle does not change.
I used script manager and Web API, (I don't know Web API and just used code on the Internet), it is the same result however the function in c# keeps on being continuously called.
I put the entire amCharts code in a JavaScript function . I got values in c# and then used
String script = "window.onload = function() { UpdateTemp('" + dt.Rows[0][0].ToString()+ "'); };";
ClientScript.RegisterStartupScript(this.GetType(), "UpdateTemp", script, true);
which again shows same result, map is shown needle stays on 0.
This is my code for the 3rd approach:
ASPX page, JavaScript function
<script>
function UpdateTemp(temp) {
am4core.ready(function() {
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// create chart
var chart = am4core.create("chartdiv", am4charts.GaugeChart);
chart.hiddenState.properties.opacity = 0; // this makes initial fade in effect
chart.innerRadius = -25;
var axis = chart.xAxes.push(new am4charts.ValueAxis());
axis.min = 0;
axis.max = 100;
axis.strictMinMax = true;
axis.renderer.grid.template.stroke = new am4core.InterfaceColorSet().getFor("background");
axis.renderer.grid.template.strokeOpacity = 0.3;
var colorSet = new am4core.ColorSet();
var range0 = axis.axisRanges.create();
range0.value = 0;
range0.endValue = 50;
range0.axisFill.fillOpacity = 1;
range0.axisFill.fill = colorSet.getIndex(0);
range0.axisFill.zIndex = - 1;
var range1 = axis.axisRanges.create();
range1.value = 50;
range1.endValue = 80;
range1.axisFill.fillOpacity = 1;
range1.axisFill.fill = colorSet.getIndex(2);
range1.axisFill.zIndex = -1;
var range2 = axis.axisRanges.create();
range2.value = 80;
range2.endValue = 100;
range2.axisFill.fillOpacity = 1;
range2.axisFill.fill = colorSet.getIndex(4);
range2.axisFill.zIndex = -1;
var hand = chart.hands.push(new am4charts.ClockHand());
// using chart.setTimeout method as the timeout will be disposed together with a chart
chart.setTimeout(randomValue, 2000);
function randomValue(temp) {
hand.showValue(temp, 1000, am4core.ease.cubicOut);
chart.setTimeout(randomValue, 2000);
}
}); // end am4core.ready()
};
</script>
C# function to get temperature and call JavaScript function
public void BindGrid(String charttype)
{
string constring = "Data Source=********.DOMAIN.ORG01;Initial Catalog=Temperature;Integrated Security=SSPI;";
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("SELECT Temperature,HighestPoint,LowestPoint FROM Temperature", con))
{
cmd.CommandType = CommandType.Text;
con.Open();
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
temp1.Value = dt.Rows[0][0].ToString();
con.Close();
String script = "window.onload = function() { UpdateTemp('" + dt.Rows[0][0].ToString()+ "'); };";
ClientScript.RegisterStartupScript(this.GetType(), "UpdateTemp", script, true);
}
}
}
The quality code should be revised but I managed to make it work.
I made 2 changes:
1 : I used the method "PageLoad" instead of "BindGrid" (do you really need this one ?)
2 : I filled the raw temperature value directly as a parameter (as it is a float on my side), you englobed your datarow value with simple quote, that's interpreted as string by javascript and the method "showValue" from "hand" seems to not tolerate it.
Code:
Result:
Some ideas to improve your code:
Put your connection string in configuration file (never in code !)
If you use the "using" do not matter calling the method "close" of your resource, it's automatically called by it. (behind the using it's in fact a try-catch-finally, the close is called anyway in the finally ;) )
If possible separate the data access from the rendering page, create a separate class that manages it, it will improve readability and evolution of your code.
If the variable "temp1" is not used, just remove it.
When you get a data (no matter the source, could be a webservice or database or else), check always if it's null before access it and log it, it doesn't cost a lot and you avoid escalation of exceptions.
We are in 2019, you could use Dapper to get directly object as result from your queries instead of a generic datarow. (check the website if interested they have a lot of interesting tutorials).
Kr,
Ali

Bokeh: trigger callback update for multiple graphs

I have data with three dimensions x, y and z. I display them as a bokeh gridplot with three separate graphs below each other. The x-axes are linked so that if I pan in one of the graphs, the other ones are updated:
time = np.arange(len(data))
labels = ["x","y","z"]
plots = []
for i in range(3):
if i != 0:
fig = figure(plot_width=900, plot_height=150, x_range=first.x_range)
else:
fig = figure(plot_width=900, plot_height=150)
# First figure is saved as other figures are linked to this one
first = fig
source = ColumnDataSource({'x': time, 'y': data[:,i]})
fig.line('x','y', source=source)
fig.yaxis.axis_label = labels[i]
plots.append([fig])
p = gridplot(([plots[0], plots[1], plots[2]]))
show(p)
I also implemented a callback for the x-axes ranges which updates the graph each time the x-range changes so that the plot fills the complete graph on the y-axis:
fig.x_range.callback = CustomJS(args=dict(source=source, xrange=fig.x_range,
yrange=fig.y_range), code=adjust_y_range_js)
In this code, the range objects are set with the newly calculated ranges, which triggers an update in the graph from which the callback originated. I.e. if I zoom in on the first of the three graphs, the y-range of the first graph will be updated so that it fills the plot. Due to the link with the other plots, the x-ranges of the other two plots will change as well. However, their x_ranges won't trigger the callback. I tried passing the other ranges in the callback JS code and updating them in the following manner, but unsuccessfully:
xrange_other.trigger('change');
This will make the box selection tool freeze for some reason, i.e. it will permanently try to make a selection. Any ideas how to update the whole plot in another way?
The code for the callback is the following (taken from someone's github, but can't find the original source unfortunately):
adjust_y_range_js = """
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
var data = source.get('data');
var start = yrange.get('start');
var end = yrange.get('end');
var time_start = xrange.get('start');
var time_end = xrange.get('end');
var pre_max_old = end;
var pre_min_old = start;
var time = data['x'];
var pre = data['y'];
t_idx_start = time.filter(function(st){return st>=time_start})[0];
t_idx_start = time.indexOf(t_idx_start);
t_idx_end = time.filter(function(st){return st>=time_end})[0];
t_idx_end = time.indexOf(t_idx_end);
var pre_interval = pre.slice(t_idx_start, t_idx_end);
pre_interval = pre_interval.filter(function(st){return !isNaN(st)});
var pre_max = Math.max.apply(null, pre_interval);
var pre_min = Math.min.apply(null, pre_interval);
var ten_percent = (pre_max-pre_min)*0.1;
pre_max = pre_max + ten_percent;
pre_min = pre_min - ten_percent;
if((!isNumeric(pre_max)) || (!isNumeric(pre_min))) {
pre_max = pre_max_old;
pre_min = pre_min_old;
}
yrange.set('start', pre_min);
yrange.set('end', pre_max);
// This is what I tried. When using these variables, I passed them in the CustomJS args dict, of course.
//yrange_other1.trigger('change');
//yrange_other2.trigger('change');
//xrange_other1.trigger('change');
//xrange_other2.trigger('change');
//soure_other1.trigger('change');
//soure_other2.trigger('change');
"""
I'm using python 2.7.10 and Bokeh version 0.12.3.

Google Script: Format URL in Array.Push

I have a working script that upon form submit, specific rows move from one sheet to another. One of the fields I'm pushing is a url.
On the second sheet, the link is listed and it is hyperlinked, but it's really ugly and I really want to format it so that it shows "Edit" with a hyperlink. I've tried a number of ways, but my knowledge is limited so all I get are errors. I'm hoping someone can point me in the right direction.
Here is my code. I'm very new at this so the script is not at all sophisticated. Any help/suggestions would be appreciated!
function copyAdHoc(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = SpreadsheetApp.setActiveSheet(ss.getSheetByName("Form Responses 1"));
var data = sh.getRange(2, 1, sh.getLastRow() - 1, sh.getLastColumn()).getValues();
// Grab the Headers from master sheet
var headers = sh.getRange(1,1,1,sh.getLastColumn()).getValues();
var date = headers[0].indexOf('Effective Date');
var name = headers[0].indexOf('Employee Name');
var loc = headers[0].indexOf('Location');
var issue = headers[0].indexOf('Description/Question/Issue');
var add = headers[0].indexOf('Additional Information');
var change = headers[0].indexOf('Is this a Qualifying Life Event?');
var url = headers[0].indexOf('Form URL');
var category = headers[0].indexOf('Primary Category');
var status = headers[0].indexOf('Current Status');
var users = headers[0].indexOf('Users');
// Grab only the relevant columns
for(n = 0; n < data.length; ++n ) { // iterate in the array, row by row
if (data[n][change] !== "Yes" & data[n][category] !== "Employee Relations" & data[n][date] !== "") { // if condition is true copy the whole row to target
var arr = [];
arr.push(data[n][url]);
arr.push(data[n][users]);
arr.push(data[n][date]);
arr.push(data[n][loc]);
arr.push(data[n][name]);
arr.push(data[n][category]);
arr.push(data[n][issue] + ". " + data[n][add]);
arr.push(data[n][status]);
var sh2 = SpreadsheetApp.setActiveSheet(ss.getSheetByName("Ad Hoc")); //second sheet of your spreadsheet
sh2.getRange(sh2.getLastRow()+1,2,1,arr.length).setValues([arr]); // paste the selected values in the 2cond sheet in one batch write
}
}
}
It's a bit messy but the only way I know to achieve what you're trying to do would be to insert a column to the left of the hyperlink with the word Edit right justified and then remove the borders between the two.
From your description I am assuming you want the word "Edit" to be Hyperlinked. To do so, try this:
function getHyperlink(url)
{
return "=HYPERLINK(\""+url+"\","+"\"Edit\""+")";
}
function mainFunct()
{
//Do necessary steps
var tarLink = "https://www.google.com";
var tarRng = tarSheet.getRange(rowNum, colNum).setValue(getHyperlink(tarLink));
//perform other steps
}
EDIT:
Forgot to mention, since you're pushing your values to the array... you can do it in a similar way by either just storing the hyperlink in a variable or directly pushing it to the array like all the other values. Or if you're dealing with a hyperlink that has a static and dynamic part, For example: https://stackoverflow.com/questions/post_id, where post_id keeps changing but most of the URL is static, you can easily handle it by just passing the post_id to the getHyperlink function and getting the required Hyperlink in return. Hope this helps.

Update data on an amChart graph from data within a DIV element

I am having some problems with my JavaScript and amCharts graph.
What I am trying to achieve is to reload an amChart line graph with new data from a DIV element. In my final page this DIV element will be dynamically updated and hidden so will not been seen by the end user. The graph needs to be redrawn without reloading the page.
I have an JSFiddle page with an example of my attempts to reload the data.
http://jsfiddle.net/gnuoynomis/Se2UE/1/
I have tried to:
Make objects of the points and add them into a string creating a string of objects but this does not seem to load into the graph.
function LoadNewDataFromDIV_V1()
{
//This function attempts to use a string of objects to pass to the dataprovider setting
var ChartData = document.getElementById("NewData").innerHTML;
var CD = ChartData.split("},{"); //Split the string on the different day elements
var NewChartData = "";
for(i=0; i<CD.length; i++)
{
var D = CD[i];
D = D.replace("{",""); //Remove any additional { that may exist to help with the formating later
D = D.replace("}",""); //Remove any additional } that may exist to help with the formating later
D = "{" + D + "}"; //Add a { and } to reformat the line correctly from the splitting
if(NewChartData != "")
NewChartData += ",";
NewChartData += JSON.parse(D); //Add the parsed object to the data string
}
chart.dataProvider = NewChartData; //Update graph data
chart.validateData(); //Revalidate chart data
}
I have also tried adding the objects into an array and tried passing this but still no luck.
function LoadNewDataFromDIV_V2()
{
//This function attempts to use an array to store the data and pass this to the dataprovider setting
var ChartData = document.getElementById("NewData").innerHTML;
var CD = ChartData.split("},{"); //Split the string on the different day elements
var NewChartDataArray = [];
for(i=0; i<CD.length; i++)
{
var D = CD[i];
D = D.replace("{",""); //Remove any additional { that may exist to help with the formating later
D = D.replace("}",""); //Remove any additional } that may exist to help with the formating later
D = "{" + D + "}"; //Add a { and } to reformat the line correctly from the splitting
NewChartDataArray.push(D); //Push the data to the array
}
chart.dataProvider = NewChartDataArray; //Update graph data
chart.validateData(); //Revalidate chart data
}
My reset of the graph works perfectly if I add the entire string straight in manually and this is what I am trying to replicate with the other methods.
If anyone is able to point out what I am doing wrong then I would be most grateful. I am also open to any suggestions if you think that I could be doing this in a better way.
working fiddle
http://jsfiddle.net/Se2UE/2/
the core of my change is here
var NewChartDataArray = [];
for(i=0; i<CD.length; i++)
{
var D = CD[i];
D = D.replace("{","");
D = D.replace("}","");
D = "{" + D + "}";
NewChartDataArray.push(JSON.parse(D));
}
declare NewChartDataArray as array and not string then add an object to array.
You had an array of strings, your library expects an array of objects
refer this

How to add figure at particular location in draw2d?

I want to add label at start or end position of connection. But here I did not found locator except ManhattanMidpointLocator. So how can I do this? How can I place label at where on connection?
Please find my code as below,
draw2d.LabelConnection = function() {
draw2d.Connection.call(this);
this.sourcePort = null;
this.targetPort = null;
this.lineSegments = [];
this.setColor(new draw2d.Color(0, 255, 0));
this.setLineWidth(2);
var label = new draw2d.Label("Message");
label.setBackgroundColor(new draw2d.Color(230, 230, 250));
label.setBorder(new draw2d.LineBorder(1));
this.addFigure(label, new draw2d.Locator());
};
draw2d.LabelConnection.prototype = new draw2d.Connection();
draw2d.LabelConnection.prototype.type = "draw2d.LabelConnection";
The above code shows label at (0,0) position.
plz help me out.
Use:
Connection.getStartPoint() to determine the start poit of the connection instead
to retrieve all segments of the connection.
Greetings
I'm not sure about what you mean by "any location" but if you implement your own locator it's pretty straightforward.
Look at the code of the ManhattanMidpointLocator. In the relocate function you know everything about the connection on the canvas. From that you just invent a calculation for the position of the label.
Now working with Graphiti in place of Draw2D but the code for your locator should look as follow (didn't tested) :
draw2d.StartConnectionLocator=function(/*:draw2d.Connection*/ connection)
{
draw2d.ConnectionLocator.call(this,connection);
};
draw2d.StartConnectionLocator.prototype.relocate=function(/*:draw2d.Figure*/ target)
{
var conn = this.getConnection();
var points = conn.getPoints();
var index = Math.floor((points.getSize() -2) / 2);
if (points.getSize() <= index+1)
return;
var startPoint = points.get(0);
var myPosition = new draw2d.Point();
myPosition.x = startPoint.x +5;
myPosition.y = startPoint.y +5;
target.setPosition(myPosition.x,myPosition.y);
};

Categories