Displaying latest Tweets on mywebsite .. User name not coming - twitter

Hi i have integrated twitter api to display recent tweets on my website .
I can able to get the recent tweets but tweets does't contains user name(user who has tweeted on my wall)
below is the code i have used
<div id="twitter_update_list" style="height:300px;width:300px; overflow:auto; overflow-x:hidden">
javascipt
<script type="text/javascript" src="https://twitter.com/javascripts/blogger.js"></script>
<script type="text/javascript" src="https://api.twitter.com/1/statuses/user_timeline.json?screen_name=ABMMyuniverse&include_rts=true&count=4&callback=twitterCallback2"></script>
output :
Aditya Birla Money MyUniverse is now a proud winner of Finnoviti-2012, an award for inspiring innovations in the financial services sector 122 days ago
Team MyUniverse wishes everyone a very # Happy Diwali, May the lights spread joy, peace and prosperity in your life! http://t.co/xbCUSRrT 133 days ago
only tweets text i'm getting .. there is no user details ..How can i get that ??
someone please help me .. thanks in advance !!!

Finally I have integrated . I hope this will help some one :)
<script language="javascript">
$(document).ready(function () {
var username = 'YourTwitterName';
$.getScript('http://api.twitter.com/1/statuses/user_timeline.json?screen_name=' + username + '&callback=twitterCallback2&count=4');
});
function twitterCallback2(twitters)
{
var statusHTML = [];
for (var i=0; i<twitters.length; i++){
var username = twitters[i].user.screen_name;
var profileimage = twitters[i].user.profile_image_url;
var status = twitters[i].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!])/g, function(url) {
return ''+url+'';
}).replace(/\B#([_a-z0-9]+)/ig, function(reply) {
return reply.charAt(0)+''+reply.substring(1)+''; });
statusHTML.push('<table style="border-top:1px dotted #000"><tr><td><a target="_blank" href="http://twitter.com/' + username + '">' + username + ':</a><br/>' + status + ' <br/><small style="color:#737373">' + relative_time(twitters[i].created_at) + '</small></td></tr></table>');
}
$('.loading').fadeOut(800, function() {
$('#userlatest_tweet').append($(statusHTML.join('')).hide().fadeIn(750));
});
}
function relative_time(time_value) {
var values = time_value.split(" ");
time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
var parsed_date = Date.parse(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
delta = delta + (relative_to.getTimezoneOffset() * 60);
if (delta < 60) {
return 'less than a minute ago';
}
else if (delta < 120) {
return 'about a minute ago';
}
else if (delta < (60*60)) {
return (parseInt(delta / 60)).toString() + ' minutes ago';
}
else if(delta < (120*60)) {
return 'about an hour ago';
} else if(delta < (24*60*60)) {
return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
} else if(delta < (48*60*60)) {
return '1 day ago';
else {
return (parseInt(delta / 86400)).toString() + ' days ago';
}
}
}
</script>
<div id="userlatest_tweet" style="height: 300px; overflow: auto; overflow-x: hidden">
<div class="loading">
</div>
</div>
you can add image also by modifying table inside statusHTML.push function ....!!!!
If it is working fine .. then make this as answer which will be helpful for others !!!

Related

Highcharts - Slow Stochastic Indicator Error

I have Highcharts chart rendered on yAxis[0] and whenever the user selects an indicator like Aroon Oscillator, MACD etc. it is added as a new yAxis in the rendering container. Example:
The above snapshot is with the Aroon Oscillator. All good.
When i select Slow Stochastic though i get the following:
First of all both SS$K and SS$D have the same value as you can see in the tooltip which is clearly wrong and both lines have the same color for a reason when they should not because:
I tried to log the p.series.yData[p.point.index] (the currently hovered point yData value) in my console and for my surprise I get the following:
It returns an array (but why) of 2 values, and both plots access the first value, instead of SS%D accessing the second value. This is a Slow Stochastic problem from Highcharts since the Aroon Oscillator which has the same philosophy of many plots on the same yAxis, still works fine as you can see in the first picture (where the lines have the correct color and correct values assigned).
Lastly as you can see with another indicators MACD (which has the same issue as mentioned before with Slow Stochastic) - and VPT which works as intended, when i go full range, those have a gap at start. Why is that happening?
Has anyone come across a similar indicator problem from Highcharts and if so, could anyone give me his/her lights on how to solve the problem?
Thanks in advance, Christopher.
P.S. Those are my tooltip options for highcharts:
tooltip: {
formatter: function() {
let finalDate = '';
let tooltipString = '';
$.each(this.points, function(i, p) {
// console.log(p.series.name, p.series.yData[p.point.index]);
//Starting date
let dateTo = new Date(p.x),
month = '' + (dateTo.getMonth() + 1),
day = '' + dateTo.getDate(),
year = dateTo.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
let intradayTime = '';
if (p.point.isIntradayData) {
let hours = dateTo.getHours();
let minutes = ('0' + dateTo.getMinutes()).slice(-2);
intradayTime += ' ' + hours + ':' + minutes;
}
dateTo = [day, month, year].join('.');
//If we wanna display previous date too:
let dateFrom = '';
if (p.point.previousDate) {
dateFrom = new Date(p.point.previousDate);
month = '' + (dateFrom.getMonth() + 1);
day = '' + dateFrom.getDate();
year = dateFrom.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
dateFrom = [day, month, year].join('.');
dateFrom += ' - ';
}
finalDate = dateFrom + dateTo + intradayTime;
if (p.series.userOptions.compare == 'percent') {
tooltipString +=
'<br>' +
`<span style="color:${p.color}; font-size:10px; font-family:\'Arial\'">` +
p.series.name +
': </span>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
' ' +
p.point.percentageDifference +
`%(${p.y})`;
('</span>');
} else if (
p.series.type == 'candlestick' ||
p.series.type == 'ohlc'
) {
tooltipString +=
'<br>' +
`<span style="color:${p.color}; font-size:10px; font-family:\'Arial\'">` +
p.series.name +
': </span>' +
'<br>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
'Open: ' +
p.point.open +
'<br>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
'High: ' +
p.point.high +
'<br>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
'Low: ' +
p.point.low +
'<br>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
'Close: ' +
p.point.close +
'</span> <br>';
} else {
let pointValueFormatted = p.y.toFixed(2);
tooltipString +=
'<br>' +
`<span style="color:${p.color}; font-size:10px; font-family:\'Arial\'">` +
p.series.name +
': </span>' +
'<span style="font-size:10px; font-family:\'Arial\'">' +
' ' +
pointValueFormatted +
'</span>';
}
});
return (
'<span style=" font-size:10px; font-family:\'Arial\'">' +
finalDate +
'</span>' +
tooltipString
);
},
borderColor: '#7fb7f0',
shared: true,
},
INDICATORS LOGIC
It's impossible to reproduce it in jsfiddle due to the size, the complexity and for security reasons due to policies. So a user can select indicators from a tabmenu like:
and they way the indicators are sorted:
//Sorting indicators.
sortIndicators() {
console.log(`Function Call: sortIndicators()`);
this.cleanIndicators(); // Just clearing the chart yaxises and the indicators array list to iterate over indicators again.
let counter = 0;
//For every indicator
for (let indicator of this.indicators) {
//If it is chart indicator we render it on yAxis[0] with our prices
if (toolsManager.isChartIndicator(indicator)) {
//some indicators have multiple arrays of data instead of one saved in an array called arrayOfObj
if (indicator.arrayOfObj) {
for (let arg of indicator.arrayOfObj) {
this.highchartOptions.series.push(arg);
}
} else {
this.highchartOptions.series.push(indicator);
}
} else {
//If it not chart indicator
this.highchartOptions.chart.height +=
2 * this.yAxisMargin + this.yAxisHeight;
let topCalculation =
456 + (counter + 1) * this.yAxisMargin + counter * this.yAxisHeight;
//yAxis to add
let addedAxis = {
title: {
enabled: false,
},
opposite: true,
min: null,
height: this.yAxisHeight,
top: topCalculation + this.yAxisMargin,
showLastLabel: false,
labels: {
enabled: true,
x: -30,
y: 0,
style: {
fontSize: '10px',
fontFamily: 'Arial',
color: '#999999',
},
},
};
this.highchartOptions.yAxis.push(addedAxis);
if (indicator.arrayOfObj) {
//some indicators have multiple arrays of data instead of one saved in an array called arrayOfObj
for (let arg of indicator.arrayOfObj) {
//for every array of that arrayOfObj
arg.yAxis = counter + 1;
this.highchartOptions.series.push(arg); //push it to series
}
} else {
indicator.yAxis = counter + 1;
if (indicator.id === 'volume') {
indicator.data = this.volumeSeries;
}
this.highchartOptions.series.push(indicator);
}
counter++;
}
}
},
the part where the magic happens is here:
if (indicator.arrayOfObj) {
//some indicators have multiple arrays of data instead of one saved in an array called arrayOfObj
for (let arg of indicator.arrayOfObj) {
//for every array of that arrayOfObj
arg.yAxis = counter + 1;
this.highchartOptions.series.push(arg); //push it to series
}
} else {
indicator.yAxis = counter + 1;
if (indicator.id === 'volume') {
indicator.data = this.volumeSeries;
}
the reason it is implemented like this is because when an indicator is selected an object is returned from the server which may have one of the two following structures:
data structure 1:
data structure 2:
And after sorting out what type of structure I am dealing with, I am pushing it into the series to display. counter variable is just used for the y-axis's. Arron Oscillator and Slow Stochastic both fulfill the first part of the conditional, because both return an object which contains and arrayOfObj (for the line colors etc as you can see in the photo uploaded).

RangeError: Maximum call stack size exceeded with vanilla JS

I'm finishing my first project where I POST data to a server and then retrieve it in the form of a list on a separate page. I have gotten to the point where I can now post and retrieve the data, however I'm getting this error:
Uncaught RangeError: Maximum call stack size exceeded
at renderSearchResults (menu.js:8)
at renderSearchResults (menu.js:38)
My code is below. Any help would be appreciated.
var userInfo = JSON.parse(sessionStorage.getItem('user'));
function search() {
/* var userInfo = JSON.parse(sessionStorage.getItem('user')); */
var xhr = new XMLHttpRequest();
xhr.open('GET', (`https://ict4510.herokuapp.com/api/menus?api_key=${userInfo.user.api_key}` ));
xhr.onload = function renderSearchResults() {
if (this.status == 200) {
var menuInfo = JSON.parse(this.responseText);
var output = '';
for (var i in menuInfo.menu) {
output +=
'<div class="foodItems">' +
'<ul>' +
'<li>Food Item: ' + menuInfo.menu[i].item + '</li>' +
'<li>Description: ' + menuInfo.menu[i].description + '</li>' +
'<li> Price: ' + menuInfo.menu[i].price + '</li>' +
'</ul>' +
+
'</div>';
}
console.log(output);
document.getElementById('foods').innerHTML = output;
}
renderSearchResults();
}
xhr.send();
}
search();

Getting all videos of a channel using youtube API

I want to get all videos of a single channel that i have its Id. The problem that I am getting only the channel informations.
this is the link that I am using:
https://gdata.youtube.com/feeds/api/users/UCdCiB_pNQpR0M_KkDG4Dz5A?v=2&alt=json&q=goal&orderby=published&max-results=10
That link is for the now-retired V2 API, so it will not return any data. Instead, you'll want to use V3 of the API. The first thing you'll need to do is register for an API key -- you can do this by creating a project at console.developers.google.com, setting the YouTube data API to "on," and creating a public access key.
Since you have your user channel ID already, you can jump right into getting the videos from it; note, however, that if you ever don't know the channel ID, you can get it this way:
https://www.googleapis.com/youtube/v3/channels?part=snippet&forUsername={username}&key={YOUR_API_KEY}
With the channel ID, you can get all the videos from the channel with the search endpoint, like this:
https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId={channel id here}&maxResults=25&key={YOUR_API_KEY}
In this case, ordering by date is the same as the old V2 parameter for ordering by "published."
There are also a lot of other parameters you can use to retrieve videos while searching a channel; see https://developers.google.com/youtube/v3/docs/search/list for more details.
I thought I would share my final result using JavaScript. It uses the Google YouTube API key and UserName to get the channel ID, then pulls the videos and displays in a list to a given div tag.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>YouTube Channel Listing</title>
<script type="text/javascript">
function getJSONData(yourUrl) {
var Httpreq = new XMLHttpRequest();
try {
Httpreq.open("GET", yourUrl, false);
Httpreq.send(null);
} catch (ex) {
alert(ex.message);
}
return Httpreq.responseText;
}
function showVideoList(username, writediv, maxnumbervideos, apikey) {
try {
document.getElementById(writediv).innerHTML = "";
var keyinfo = JSON.parse(getJSONData("https://www.googleapis.com/youtube/v3/channels?part=snippet&forUsername=" + username + "&key=" + apikey));
var userid = keyinfo.items[0].id;
var channeltitle = keyinfo.items[0].snippet.title;
var channeldescription = keyinfo.items[0].snippet.description;
var channelthumbnail = keyinfo.items[0].snippet.thumbnails.default.url; // default, medium or high
//channel header
document.getElementById(writediv).innerHTML += "<div style='width:100%;min-height:90px;'>"
+ "<a href='https://www.youtube.com/user/" + username + "' target='_blank'>"
+ "<img src='" + channelthumbnail + "' style='border:none;float:left;margin-right:10px;' alt='" + channeltitle + "' title='" + channeltitle + "' /></a>"
+ "<div style='width:100%;text-align:center;'><h1><a href='https://www.youtube.com/user/" + username + "' target='_blank'>" + channeltitle + "</a></h1>" + channeldescription + "</div>"
+ "</div>";
var videoinfo = JSON.parse(getJSONData("https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId=" + userid + "&maxResults=" + maxnumbervideos + "&key=" + apikey));
var videos = videoinfo.items;
var videocount = videoinfo.pageInfo.totalResults;
// video listing
for (var i = 0; i < videos.length; i++) {
var videoid = videos[i].id.videoId;
var videotitle = videos[i].snippet.title;
var videodescription = videos[i].snippet.description;
var videodate = videos[i].snippet.publishedAt; // date time published
var videothumbnail = videos[i].snippet.thumbnails.default.url; // default, medium or high
document.getElementById(writediv).innerHTML += "<hr /><div style='width:100%;min-height:90px;'>"
+ "<a href='https://www.youtube.com/watch?v=" + videoid + "' target='_blank'>"
+ "<img src='" + videothumbnail + "' style='border:none;float:left;margin-right:10px;' alt='" + videotitle + "' title='" + videotitle + "' /></a>"
+ "<h3><a href='https://www.youtube.com/watch?v=" + videoid + "' target='_blank'>" + videotitle + "</a></h3>" + videodescription + ""
+ "</div>";
}
} catch (ex) {
alert(ex.message);
}
}
</script>
</head>
<body>
<div id="videos"></div>
<script type="text/javascript">
showVideoList("USER_NAME", "videos", 25, "YOUR_API_KEY");
</script>
</body>
</html>
ADDITION - I also wrote a function to handle if you are using a channel ID instead of a UserName based account.
Here is that code:
function showVideoListChannel(channelid, writediv, maxnumbervideos, apikey) {
try {
document.getElementById(writediv).innerHTML = "";
var vid = getJSONData("https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId=" + channelid + "&maxResults=" + (maxnumbervideos + 1) + "&key=" + apikey);
var videoinfo = JSON.parse(vid);
var videos = videoinfo.items;
var videocount = videoinfo.pageInfo.totalResults;
var content = "<div style='height:600px;overflow-y:auto;'>";
for (var i = 0; i < videos.length - 1; i++) {
var videoid = videos[i].id.videoId;
var videotitle = videos[i].snippet.title;
var videodescription = videos[i].snippet.description;
var videodate = videos[i].snippet.publishedAt; // date time published
var newdate = new Date(Date.parse((videodate + " (ISO 8601)").replace(/ *\(.*\)/, "")));
var min = newdate.getMinutes();
if (min < 10) {
min = "0" + min;
}
if (newdate.getHours() > 12) {
newdate = newdate.getMonth() + 1 + "/" + newdate.getDate() + "/" + newdate.getFullYear() + " " + (newdate.getHours() - 12) + ":" + min + " PM";
} else if (newdate.getHours() == 12) {
newdate = newdate.getMonth() + 1 + "/" + newdate.getDate() + "/" + newdate.getFullYear() + " " + newdate.getHours() + ":" + min + " PM";
} else {
newdate = newdate.getMonth() + 1 + "/" + newdate.getDate() + "/" + newdate.getFullYear() + " " + newdate.getHours() + ":" + min + " AM";
}
var videothumbnail = videos[i].snippet.thumbnails.default.url; // default, medium or high
content += "<hr /><div style='width:100%;min-height:90px;'>"
+ "<a href='https://www.youtube.com/watch?v=" + videoid + "' target='_blank'>"
+ "<img src='" + videothumbnail + "' style='border:none;float:left;margin-right:10px;' alt='" + videotitle + "' title='" + videotitle + "' /></a>"
+ "<h3><a href='https://www.youtube.com/watch?v=" + videoid + "' target='_blank'>" + videotitle + "</a></h3>" + videodescription + "<br />"
+ "<span style='color:#738AAD;font-size:Small;'>" + newdate + "</span>"
+ "</div>";
}
content += "</div>";
document.getElementById(writediv).innerHTML = content;
} catch (ex) {
alert(ex.message);
}
}
It is very easy method to get channel videos using your channel API key:
Step 1: You must have an YouTube account.
Step 2: Create your YouTube channel API key
Step 3: Create project console.developers.google.com,
<?php
$API_key = 'Your API key'; //my API key dei;
$channelID = 'Your Channel ID'; //my channel ID
$maxResults = 5;
$video_list =
json_decode(file_get_contents('https://www.googleapis.com/youtube/v3/search?
order=date&part=snippet&channelId='.$channelID.
'&maxResults='.$maxResults.'&key='.$API_key.''));
?>
Example : https://www.googleapis.com/youtube/v3/channelspart=snippet&forUsername=
{username}&key={YOUR_API_KEY}
Here is the way to get all videos with only 2 quotas using YouTube Data API (v3)
First of all do a list on channels with part=contentDetails (1 quota) :
https://youtube.googleapis.com/youtube/v3/channels?part=contentDetails&id=[CHANNEL_ID]&key=[YOUR_API_KEY]
You will get this result :
{
...
"items": [
{
...
"contentDetails": {
"relatedPlaylists": {
"likes": "",
"uploads": "UPLOADS_PLAYLIST_ID"
}
}
}
]
}
Then take UPLOADS_PLAYLIST_ID and do a list on playlistItems with part=contentDetails (1 quota):
https://youtube.googleapis.com/youtube/v3/playlistItems?part=contentDetails&playlistId=[UPLOADS_PLAYLIST_ID]&key=[YOUR_API_KEY]
You will get this result:
{
...
"items": [
{
...
"contentDetails": {
"videoId": "VIDEO_ID",
"videoPublishedAt": "2022-10-27T16:00:08Z"
}
},
...
],
"pageInfo": {
"totalResults": 5648,
"resultsPerPage": 5
}
}
You got the list of the videos under items
You can of course change the size of this list by adding maxResults=50 (max value is 50)

why my label formatter is not working as expected in highcharts

I would like to do dynamic texting for my x axis's label. Basically if the label with same month year has been displayed, I do not want to repeat them.
However, in my jsfiddle example, it somehow doesn't work (even though it does return the wanted text). What am I doing wrong?
http://jsfiddle.net/daxu/md2zk/64/
if (labelYear == -1 || year != labelYear) {
$('#MessagePerformanceChartContainerID').data("FirstYear", year);
if (labelYear == -1)
{
usedLabels = [];
}
usedLabels.push(curr_month + ' ' + curr_year);
$('#MessagePerformanceChartContainerID').data("UsedLabels", usedLabels);
////first one so
return curr_month + ' ' + curr_year;
}
else{
var usedLabel = curr_month + ' ' + curr_year;
if ( $.inArray(usedLabel, usedLabels) != -1)
{
usedLabel = curr_day + ' ' + curr_month + ' ' + curr_year;
return 'a';
}
else
{
usedLabels.push(usedLabel);
$('#MessagePerformanceChartContainerID').data("UsedLabels", usedLabels);
alert(usedLabel);
return usedLabel;
}
}
Just formatter is called twice :) See JS console: http://jsfiddle.net/md2zk/66/ - each timestamp is listed twice.
As solution, I would clean up UsedLabels in tickPositioner:
$('#MessagePerformanceChartContainerID').data("UsedLabels", []);
Demo: http://jsfiddle.net/md2zk/67/

Highstocks tooltip doesnt work when chart is small?

I've created custom formatter function for highstocks.js:
var tooltip = [];
for (key in this.points) {//if point type is portfolio
if ( this.points[key].point.type == 'portfolio' ) {
tooltip[key] = '<span style="color:' + his.points[key].series.color +'">' + this.points[key].series.name + '</span>' + '<br/><b>'+ _('', 'Net assets: ') + _s(this.points[key].point.sum, 2) + '</b>' + '<br/><b>'+ _('', 'Чистые активы: ') + _s(this.points[key].point.netassets, 2) +'</b> (<span style="color:' + ( (this.points[key].point.change < 0 )?'#b86565':'#619000') +'">' + _s(this.points[key].point.change, 0) +'%</span>)<br/>';
} else {
tooltip[key] = '<span style="color:' + this.points[key].series.color +'">' + this.points[key].series.name + '</span>: <b>'+ _s(this.points[key].point.y, 2) +'</b> (<span style="color:' + ( (this.points[key].point.change < 0 )?'#b86565':'#619000') +'">' + _s(this.points[key].point.change, 0) +'%</span>)<br/>';
}
}
var tl = '';
for (key in tooltip) {
tl += tooltip[key]
}
var date = Highcharts.dateFormat('%d %b %Y', this.points[0].point.x);
tl = date + '<br/>' +tl;
return tl;
The feature is that this function usues not only Y of a point, but also some additinal properties, that I have added to the point: such as type.
For points that are "portfolio" type the tooltop shoold be rendered differently and has to have much more data then for "regular" point type.
The problem that I've encountered that when conatiner div has small width, my template doesnt work, although it works fine when div's width is big.
Highstocks.js does default aggregation when renders chart to relativly small area: http://api.highcharts.com/highstock#plotOptions.area.dataGrouping
When points are groupped, they lose all additional attributes, leaving only Y property, so complex tooltop wont work.
To fix it I had to disable data groupping in chart options:
plotOptions: {
series: {
dataGrouping: {
enabled: false
}
}
},
Is ther a way to display complex tooltip on small chart without disabling dataGrouping?
The question is: 'How to group point.type'?
I guess you would like to group point by type, and then display n-points in that place? Or group point as is, but in options count number of types? What if user will define myCustomFancyProperty - what then? Aggregate all own properties from point? It's getting harder and harder.. what can I advice is to create an idea here with some explanation/solution.
You can always get from grouped point x-value (this.x), and then loop over all points (accessible via this.points[0].series.options.data), find the closest point to that timestamp and display required value.
as Pawel Fus suggested, I loop throught all points to find closest value and add additinal attributes for each groupped point.
Here is th whole formmater function.
formatter: function() {
var tooltip = [];
//Тултип
for (var key in this.points) {//Если точка - пользователь
//прочитаем тип
var closestX = 0;
for (var j in this.points[key].series.options.data ) {
if ( Math.abs(this.points[key].series.options.data[j].x - this.points[key].point.x) < diff ) {
closestX = j;
}
var diff = Math.abs(this.points[key].series.options.data[j].x - this.points[key].point.x);
}
this.points[key].point.type = this.points[key].series.options.data[closestX].type;
this.points[key].point.sum = this.points[key].series.options.data[closestX].sum;
this.points[key].point.netassets = this.points[key].series.options.data[closestX].netassets;
if ( this.points[key].point.type == 'portfolio' ) { //если точка не пользователь
tooltip[key] = '<span style="color:' + this.points[key].series.color +'">' + this.points[key].series.name + '</span>' +
'<br/><b>'+ _('', 'Сумма активов: ') + _s(this.points[key].point.sum, 2) + '</b>' +
'<br/><b>'+ _('', 'Чистые активы: ') + _s(this.points[key].point.netassets, 2) +'</b> (<span style="color:' + ( (this.points[key].point.change < 0 )?'#b86565':'#619000') +'">' + _s(this.points[key].point.change, 0) +'%</span>)<br/>';
} else {
tooltip[key] = '<span style="color:' + this.points[key].series.color +'">' + this.points[key].series.name + '</span>: <b>'+ _s(this.points[key].point.y, 2) +'</b> (<span style="color:' + ( (this.points[key].point.change < 0 )?'#b86565':'#619000') +'">' + _s(this.points[key].point.change, 0) +'%</span>)<br/>';
}
}
var tl = '';
for (key in tooltip) {
tl += tooltip[key]
}
//Дата
var date = Highcharts.dateFormat('%d %b %Y', this.points[0].point.x);
tl = date + '<br/>' +tl;
return tl;
},

Resources