How to add a second tooltip to highcharts - javascript

I would like to add an external popover to highcharts. I'm currently looking at using WebUI Popover
So the standard highcharts popover displays the standard data, however, I would like to use WebUI Popover to display some data to explain a specific column, which can be fetched from the DB.
The actual fetching of data etc is fine, but I can't figure out how to display a specific popover for a column
The way WebUI Popover works is that it requires some HTML identifier to know where to show the popover:
$(#identifier).webuiPopover({"content"})
I cant find any identifier to use to link the popover to each column:
<g class="highcharts-series highcharts-tracker" visibility="visible" zIndex="0.1" transform="translate(55,48) scale(1 1)" style="" clip-path="url(#highcharts-3)">
<rect x="63.5" y="33.5" width="119" height="162" stroke="#FFFFFF" fill="rgb(124, 181, 236)" rx="0" ry="0" stroke-width="1" data-target="webuiPopover0"></rect>
<rect x="309.5" y="98.5" width="119" height="97" stroke="#FFFFFF" fill="rgb(124, 181, 236)" rx="0" ry="0" stroke-width="1"></rect>
<rect x="555.5" y="65.5" width="119" height="130" stroke="#FFFFFF" fill="rgb(124, 181, 236)" rx="0" ry="0" stroke-width="1"></rect>
</g>
So I want to show a popover for each coloumn (rect), but I really don't know how. I've tried:
var thePoint = "rect[x='" + 63.5 + "'][y='" + 33.5 + "']";
$(thePoint).webuiPopover(...)
This works to some extent, but obviously I've hard coded the 63,5 and 33,5. I've tried everything to dynamically get the x and y values, but I can never get those exact numbers.
Any other suggestions? Maybe if someone could explain how the built in popover gets the position?

There is this demo of clickable points: http://www.highcharts.com/demo/line-ajax
It uses Highslide.
If you want to use WebUI Popover, then you can find columns' rectangles and add popups. Example: http://jsfiddle.net/j57me5w1/
Looks like popups will start from top left corner.
$(function () {
$('#container').highcharts({
series: [{
type: 'column',
data: [1, 2, 3, 4, 5, 6, 7]
}]
});
var columns = $('.highcharts-tracker > rect');
$.each(columns, function (i, c) {
$(c).webuiPopover({
title: 'test',
content: '<div id="popup">popup content</div>',
closeable: true,
arrow: true,
placement: 'auto'
});
});
});

Related

The XY coordinates in a d3 drag event are inverting

I have a force layout with the following structure:
<svg width="300" height="220">
<g class="scaleWrapper" transform="scale(0.3)">
<g class="transformWrapper" transform="translate(-110, -80)">
<g class="backgroundWrapper">
<rect class="backgroundRect" width="300" height="220"></rect>
</g>
<g class="forceNode"></g>
<g class="forceNode"></g>
<g class="forceLink"></g>
</g>
</g>
</svg>
I also have a drag behavior linked to the rect to drag it around (scaling is handled through a separate slider).
let transformElement = d3.select('.transformWrapper');
let svgBackground = transformElement.append('g')
.classed('backgroundWrapper', true);
function originFunction() {
let d = d3.select('.transformWrapper');
return {
x: d.attr('x'),
y: d.attr('y')
};
}
let svgDrag = d3.behavior.drag()
.origin(originFunction)
.on('dragstart', function(){
d3.event.sourceEvent.stopPropagation();
})
.on('drag', function(){
transformElement.attr("transform", `translate(${d3.event.x}, ${d3.event.y})`);
});
svgBackground.call(svgDrag);
It mostly works, but it jumps around as i drag it. I did a log and saw that the d3.event object is alternating between relative XY coordinates and absolute ones, here's a sample of what I'm seeing:
-111 -80
-29 -6
-110 -80
-29 -5
I don't see any other elements that have behavior bound to them. All the d3.event objects have the 'drag' type property and the same srcElement. How can I silence the events that are returning the relative positions?
Found the problem, it's the same bug as in d3.event.y has strange values during drag behavior
Moving the drag behavior to the transform group fixed it right up.

Highlighting an area of an image map based on search text

This is a new question feeding from another question that was just answered here.
I am working to highlight a <div> based on search text. We've accomplished that, thanks to Alex.
Now, I'm trying to apply the same concept to mapped coordinates on an image map.
There's a jsfiddle here.
Here's the JS(jQuery 1.10.2)...
function doSearch(text) {
$('#content div').removeClass('highlight');
$('#content div:contains(' + text + ')').addClass('highlight');
}
If you want a method without SVG, you can use the Maphilight jQuery plugin (GitHub).
I have updated your jsFiddle.
function doSearch(text) {
$('#content div').removeClass('highlight');
$('#content div:contains(' + text + ')').addClass('highlight');
$('#Map area').mouseout();
$('#Map area[data-text*="' + text + '"]').mouseover();
}
$(function() {
$('#imgmap').maphilight({ stroke: false, fillColor: "ffff00", fillOpacity: 0.6 });
});
Note: For a better result just use a bigger image, because your bunny.jpg is too small and you have forced its size with height/width attributes.
It is not possible with image-maps and area elements, because those are non visible elements, that cannot have child elements, nor styles. You would have to do it a lot more complicated like described here
But it is possible using modern embeded SVGs - Almost every browser does support it nowadays. Even IE.
I tested it with Chromium and Firefox.
It cannot be done with the help of jQuery as far as I know but with usual Javascript. The key is:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="663px" height="663px">
<image xlink:href="http://webfro.gs/south/kb2/images/bunny.jpg" x="0" y="0" width="663" height="663" />
<circle class="office" cx="504" cy="124" r="94" />
<circle class="fire-exit" cx="168" cy="150" r="97" />
<circle class="main-exit" cx="378" cy="589" r="48" />
</svg>
_
var svgns="http://www.w3.org/2000/svg";
var areas = document.getElementsByTagNameNS(svgns, 'circle');
$(areas).each(function(elem) {
if(areas[elem].className.baseVal === text) {
areas[elem].className.baseVal += ' highlightsvg';
} else {
areas[elem].className.baseVal = areas[elem].className.baseVal.replace(' highlightsvg', '');
}
});
See here in the JSFiddle. Is that the way you want it?

Highcharts: locating column group information on mouseover

I'm working on a rather complex Highcharts implementation and have run into a snag. I'm using a grouped column chart, with a series data structure very much like this:
http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/highcharts/demo/column-basic/
e.g.
series: [{
name: 'Tokyo',
data: [49.9, 71.5, 106.4, 129.2, 144.0, 176.0]
}, {
name: 'New York',
data: [83.6, 78.8, 98.5, 93.4, 106.0, 84.5]
},
...
When the user mouses over any of the columns in a particular month, I'm trying to capture the following:
the index of the month group (e.g. Jan == 0, Feb == 1 or something like that)
the x,y and height,width coordinates of the entire group.
The problem is that "this" in plotOptions.column.events.mouseOver contains such a huge volume of data, I've been unable to identify where in the massive data structure that info exists. Also, it appears the mouseOver event is tied to the individual column being moused-over, rather than the group itself.
Any idea? (Thanks in advance!)
Ben
So I spent a bit of time looking into this and you're right, the event object passed into the mouseOver method is not all that helpful. I tried finding a reference to the currently-highlighted column, but to no avail. But, I found an alternate approach, relying on the DOM structure for the chart. This means it would probably break if they ever change the chart layout in a future version, but it should work for now.
The basic structure of the chart looks like this:
<g class="highcharts-series-group">
<g class="highcharts-series">
<rect x="11" y="223" width="5" height="55" />
<rect x="61" y="199" width="5" height="79" />
<rect x="111" y="160" width="5" height="118" />
<rect x="161" y="135" width="5" height="143" />
<rect x="211" y="118" width="5" height="160" />
<rect x="261" y="83" width="5" height="195" />
<!-- More <rect/>'s -->
</g>
<g class="highcharts-series">
<rect x="19" y="185" width="5" height="93" />
<rect x="69" y="191" width="5" height="87" />
<rect x="119" y="169" width="5" height="109" />
<rect x="169" y="175" width="5" height="103" />
<rect x="219" y="161" width="5" height="117" />
<rect x="269" y="184" width="5" height="94" />
<!-- More <rect/>'s -->
</g>
<!-- More <g class="highcharts-series"/>'s -->
</g>
These correspond directly to the series information that was passed in on chart creation, with the x, y, width, and height attributes that I believe you're referring to. We can use this structure to use some old-fashioned event handling to retrieve the information you're looking for.
// Loop over each series element and bind a
// 'mouseover' event to it.
$('.highcharts-series rect').on('mouseover', function() {
var self = $(this);
// Determine the offset (equal to the number of 'rect'
// objects before it)
var xIndex = self.prevAll('rect').length;
var groupInfo = [];
// Retrieve the '.highcharts-series-group' node
// NOTE: $(this).parents('.highcharts-series-group')
// does not appear to work (perhaps a limitation with
// jQuery and SVG?)
$(this.parentNode.parentNode)
// Loop over all series nodes within the current chart
.find('.highcharts-series')
.each(function(){
// Retrieve the matching entry within each series
// (represented by the nth 'rect' node)
var element = $(this).find('rect:eq(' + xIndex + ')');
if (!element.length) {
return;
}
// Populate the Group Info element
groupInfo.push({
x: element.attr('x'),
y: element.attr('y'),
width: element.attr('width'),
height: element.attr('height')
});
});
// Do what you want with the groupInfo object and xIndex here:
console.log(xIndex, groupInfo);
});
In mouseover venet for point, you have access to all parameters about column.
http://jsfiddle.net/amKuZ/
mouseOver: function() {
$report.html('coordinate: x: ' +this.plotX+'coordinate y: ' +this.plotY+'column width' + this.pointWidth + ' x value:'+this.x);
}
http://api.highcharts.com/highcharts#plotOptions.column.point.events.mouseOver

Setting color to a string using javascript

I am building a dynamic array and have the following code, i am trying to add a color to the "name" of the array. Everything else works perfectly apart from "fontcolor("red")" .
if (val < 0) {
myArray.push({
"name" : myVariable.fontcolor("red"),
"size" : -10
});
} else {
myArray.push({
"name" : myVariable,
"size" : 5
});
}
I end up with the following when displayed on thet HTML page:
<font color="red">Strong rubber(minus)</font>
I am actualy drawing a chart and I am using the d3.js to draw the charts, my code that draws up "Dog Toys". myVariable has the value "myVariable"
<g style="cursor: pointer; opacity: 1; " transform="translate(0,0)">
<text x="-6" y="10" dy=".50em" text-anchor="end">Dog Toys</text>
<rect width="478.57142857142867" height="20" style="fill: #4682b4; "></rect>
</g>
Any idea how i could set a color to text, when its displayed on the web page?
Try
myVariable.style.color = "Red"
myVariable.style.color = "red";

Raphael JS Pie: Add ID to path slices

I've seen this question asked over at the Raphael Google Groups, but after hours of searching there, and also on here, and Google, I cannot seem to find a solution.
I would simply like to be able to target my pie chart (svg path) slices using jQuery, but I cannot figure out how to add custom id's to the path tags - there is no ID attribute in there by default:
<path fill="#764c29" stroke="none" d="M350,350L350.6911881148345,94.00093308961084A256,256,0,0,1,561.8463375189659,206.2741175716762Z" style="stroke-width: 1; stroke-linejoin: round;" stroke-width="1" stroke-linejoin="round"/>
What would be ideal would be this:
<path **id="my_id"** fill="#764c29" stroke="none" d="M350,350L350.6911881148345,94.00093308961084A256,256,0,0,1,561.8463375189659,206.2741175716762Z" style="stroke-width: 1; stroke-linejoin: round;" stroke-width="1" stroke-linejoin="round"/>
Has anyone got an idea how this could be achieved?
This is the code I'm using to create the pie chart:
window.onload = function () {
var r = Raphael("holder");
var pie = r.g.piechart(350, 350, 256, [56, 104, 158, 23, 15, 6]);
pie.hover(function () {
this.sector.stop();
this.sector.animate({scale: [1.1, 1.1, this.cx, this.cy]}, 500, "bounce");
}, function () {
this.sector.animate({scale: [1, 1, this.cx, this.cy]}, 500, "bounce");
});
};
Essentially, the reason I need to be able to do this, is so I can create some separate anchor triggers to perform the scale animations shown above.
Any help greatly appreciated.
the piechart object provides 3 ways to reach their sectors.
1) each function
pie.each(function(sector, cover, i) {
sector.attr({/*...*/}); //raphael
$(sector.node).foo(); //jquery
});
2) series object (for styling and transforming)
var i = 0; // 0 = 56, 1 = 104, 2 = 158 …
//raphael way to hide the first sector
pie.series.items[i].attr({ opacity : 0 });
//jquery way to hide the first sector
$(pie.series.items[i].node).hide();
whereby i is the index of your data-array
demo: http://jsbin.com/eriqa5/2/edit
3) covers object (for mouse and touch events)
//raphael way to hover the first sector
pie.covers.items[0].hover(...);
//jquery way to hover the first sector
$(pie.covers.items[0].node).hover(...);
demo: http://jsbin.com/eriqa5/4/edit

Categories