Laravel send data from view to JavaScript file - javascript

i want to send data that i get it from controller to javascript file that exist in public/js/maps.js
how can i do this can any one help
my code
Controller :
public function index()
{
$userIp = "45.153.242.129";
$locationData = \Location::get($userIp);
return view('maps.index',[
'location' => $locationData
]);
}
view page:
<div id="world-map"></div>
maps.js
var handleVectorMap = function() {
"use strict";
if ($('#world-map').length !== 0) {
$('#world-map').vectorMap({
map: 'world_mill',
scaleColors: [COLOR_GREY_DARKER, COLOR_GREY_LIGHTER],
normalizeFunction: 'polynomial',
hoverOpacity: 0.5,
hoverColor: false,
zoomOnScroll: true,
markerStyle: {
initial: {
fill: COLOR_RED,
stroke: 'transparent',
r: 3
}
},
regionStyle: {
initial: {
fill: COLOR_DARK_LIGHTER,
"fill-opacity": 1,
stroke: 'none',
"stroke-width": 0.4,
"stroke-opacity": 1
},
hover: {
"fill-opacity": 0.8
},
selected: {
fill: 'yellow'
},
selectedHover: { }
},
backgroundColor: 'transparent',
markers: [
{latLng: [41.90, 12.45], name: 'Vatican City'},
{latLng: [43.73, 7.41], name: 'Monaco'},
]
});
}
};
so i want to display data in markers that exist in the javascript file.

If it was in a single blade file, you could echo de json_encoded variables
<div id="world-map"></div>
<script>
const data = JSON.parse('{{ json_encode($data); }}');
</script>
If it's in a separate js file, you either need to get it through an ajax request or store the data in an html element to query inside your js file.
Something like
<div id="world-map" data-maps='{{ json_encode($data) }}'></div>
const data = JSON.parse(document.getElementById('world-map').dataset.maps);
I think blade has a #json directive just for such a scenario.

in normanl case when you call a data from controller usually we use
{{ $data }}
but if you want to call the same data but inside a javascript code or file i recommend using
function (index, value) { data = '<p>'+value.data+'</P>' }

Related

How can my Chart.js just update when data in SQL change?

I build a web app in MVC using SignalR to update real-time data. I can display my chart with real-time data from SQL but it just updates by the time set in setInterval. But now I want my chart to just update when my data in SQL SERVER changes. I have tried many ways but it's not correct. Can you help me with the algorithm? Thank you.
Here is my code :
<!--Chart-->
<script>
var ctx = document.getElementById("percent-chart2");
var colorarray = ['#00b5e9', '#fa4251', '#006400'];
var pre_vals = 0;
//
var myVar = setInterval(GetValue, 1000);
function GetValue() {
var val1 = parseFloat(document.getElementById("tblValue").innerHTML);
var val2 = parseFloat(document.getElementById("tblValue1").innerHTML);
var vals = [val1, val2, 2000];
return vals;
}
if (ctx) {
ctx.height = 209;
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
datasets: [
{
label: "My First dataset",
//data: [GetValue, GetValue, GetValue],
data: GetValue(),
backgroundColor: [
'#00b5e9',
'#fa4251',
'#006400'
],
hoverBackgroundColor: [
'#00b5e9',
'#fa4251',
'#006400'
],
borderWidth: [
0, 0, 0
],
hoverBorderColor: [
'transparent',
'transparent',
'transparent'
]
}
],
labels: [
'STATION 1',
'STATION 2',
'STATION 3'
]
},
options: {
maintainAspectRatio: false,
responsive: true,
cutoutPercentage: 57,
animation: {
animateScale: true,
animateRotate: true
},
legend: {
display: false,
position: 'bottom',
labels: {
fontSize: 14,
fontFamily: "Poppins,sans-serif"
}
},
tooltips: {
titleFontFamily: "Poppins",
xPadding: 15,
yPadding: 10,
caretPadding: 0,
bodyFontSize: 16,
}
}
});
}
function UpdateChart(datachart, data, color) {
datachart.data.datasets.pop();
datachart.data.datasets.push({
data: data,
backgroundColor: color,
hoverBackgroundColor: color
});
datachart.update();
}
setInterval(function () {
const my_val = GetValue();
//var updatedata = [my_val, my_val, 2000];
var updatedata = my_val;
UpdateChart(myChart, updatedata, colorarray);
}, 10000);
</script>
The way I handle this is by adding a client call with the dataset after the database update has completed. This way you only update when that update is called.
Here is a rough example off the top of my head:
public void UpdateDB(int updatedData)
{
//DB work to commit the updatedData
....
//Query your dataset into an serialized updatedDataset
....
//Call a method to create an array (updatedColors) of colors based on the the Count of updatedDataset
....
//Send data to client(s)
Clients.All.yourclientfunction(updatedDataset, updatedColors);
}

How to pass 2 values to json style in leaflet

I need to pass 2 styles, i currently have:
First style:
function style(feature) {
return {
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7,
fillColor: getColor(feature.properties.density)
};
}
The I do:
var classNameMap = <?php echo JSON_encode($classesForCountries); ?>;
geojson = L.geoJson(statesData, {
style: style,
style: function(feature) {
var classes = classNameMap[feature.properties.name];
return {className: classes};
},
onEachFeature: onEachFeature
}).addTo(map);
But that ignores the first style
I tried by passing it as an array:
geojson = L.geoJson(statesData, {
style: [style, function(){
var classes = classNameMap[feature.properties.name];
return {className: classes};
}],
onEachFeature: onEachFeature
}).addTo(map);
But yet, first style is ignored.
leaflet docs if this can help, here
This is the solution:
var classNameMap = <?php echo JSON_encode($classesForCountries); ?>;
function style(feature) {
var classes = classNameMap[feature.properties.name];
return {
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7,
fillColor: getColor(feature.properties.density),
className: classes
};
}
geojson = L.geoJson(statesData, {
style: style,
onEachFeature: onEachFeature
}).addTo(map);
Not familiar with leaflet, but looking from js perspective using duplicate key will definitely override its value with the last key entry.
If you are trying append the style1 and style2, since both the functions of style returns an object, you can do so by $.extend.
function style_1(feature) {
return {
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7,
fillColor: getColor(feature.properties.density)
};
}
...
style: function(feature) {
// Now the logic is a simple hashmap look-up
var style1 = style_1(feature);
var classes = classNameMap[feature.properties.name];
var finalStyle = $.extend(style1, {className: classes});
return finalStyle;
}
...
You're putting duplicate keys in the object initializer. Don't.
See How to generate a JSON object dynamically with duplicate keys? , Finding duplicate keys in JavaScript object

different style for different ports in vector map

Hi guys this is my JavaScript code to make ip marker for vector map to show online ip..
all ips have 3 different port like: ip1:1020 or ip2:5050 or ip3:6969
the format for my ips that i can read from ip.txt file like is :
{"relays":[{
"or_addresses":["2.176.82.122:1020"],"latitude":35.6961059570313,"longitude":51.423095703125},
{"or_addresses":["2.177.37.250:5050"],"latitude":35.6961059570313,"longitude":51.423095703125},
{"or_addresses":["2.178.57.250:6969"],"latitude":35.6961059570313,"longitude":51.423095703125},
{"or_addresses":["2.18.5.20:5050"],"latitude":35.6961059570313,"longitude":51.423095703125},
{"or_addresses":["2.78.7.25:1020"],"latitude":35.6961059570313,"longitude":51.423095703125}
]}
and this is my main script
<script>
$(document).ready(function(){
$('#worldmap').vectorMap({
map: 'world_mill_en',
scaleColors: ['#C8EEFF', '#0071A4'],
normalizeFunction: 'polynomial',
hoverOpacity: 0.7,
hoverColor: false,
markerStyle: {
initial: {
fill: '#cc6600',
stroke: '#222222',
r: 2
}
},
backgroundColor: '#CCC',
markers: [
]
});
map = $('#worldmap').vectorMap('get', 'mapObject');
$.getJSON('http://127.0.0.1/bantools/ip/ip.txt', function(data){
$.each(data.relays, function(idx, relay)
{
map.addMarker(relay.or_addresses[0], {'latLng' : [relay.latitude, relay.longitude], "name" : relay.or_addresses[0]});
});
});
});
</script>
my question is how i can make different style for different PORTS ????!
my means i want to use this style for port = 1020 :
markerStyle: {
initial: {
fill: '#cc6600',
stroke: '#222222',
r: 2
}
}
and for port = 5050 i want to use this style :
markerStyle: {
initial: {
fill: '#aaa',
stroke: '#bbb',
r: 2
}
}
and for other port...
http://jsbin.com/womoqa/edit?js,output
$(function(){
$('#world-map-markers').vectorMap({
map: 'world_mill_en',
scaleColors: ['#C8EEFF', '#0071A4'],
normalizeFunction: 'polynomial',
hoverOpacity: 0.7,
hoverColor: false,
backgroundColor: '#383f47',
markers: [
{latLng: [41.90, 12.45], name: 'Vatican City',
style: {
fill: '#cc6600',
stroke: '#222222',
r: 5
}},
{latLng: [17.11, -61.85], name: 'Antigua and Barbuda',
style: {
fill: '#ff0000',
stroke: '#222222',
r: 8
}},
{latLng: [0.33, 6.73], name: 'São Tomé and Príncipe',
style:{
fill: '#F8E23B',
stroke: '#383f47'
}}
]
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script src="http://jvectormap.com/js/jquery-jvectormap-2.0.2.min.js"></script>
<script src="http://jvectormap.com/js/jquery-jvectormap-world-mill-en.js"></script>
<link rel="stylesheet" href="http://jvectormap.com/css/jquery-jvectormap-2.0.2.css">
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="world-map-markers" style="width: 720px; height: 400px"></div>
</body>
</html>
I think to set the initial marker style you would need to go through all the data and build a scale (grouping), which is then used by jvectormap to get the values for the marker.
Your script to get json data looks good, so you are first showing the map and then put the markers over them. I think its a good approach, and your script is just only missing a simple function to prepare the markers style, if i'm not wrong here.
I changed slightly your data because all coordinates are pointing to the same location and the markers overlaps. It would be also useful if you explain if this is what you have to deal with.
This is a simple function to get the styles for the markers, it's just like a boring switch:
function getMarkerStyle(port) {
var styles = {'1020': {fill: '#cc6600', stroke: '#222222',r: 2},
'5050': {fill: '#aaa',stroke: '#bbb',r: 2}};
var unknown = {fill: '#F00',stroke: '#000',r: 2};
return styles[port] || unknown;
}
This shall be inside your getJSON callback function, instead of $.each i'm using here a classic for loop:
for (var i = 0, l = logFile.relays.length; i < l; i++) {
var port = logFile.relays[i].or_addresses[0].split(':')[1];
var id = logFile.relays[i].or_addresses[0].split(':')[0];
var coords = [logFile.relays[i].latitude, logFile.relays[i].longitude];
var name = id;
var style = getMarkerStyle(port);
mapObj.addMarker(id, {latLng: coords, name: name, style: style}, null);
}
You just only need to put the style inside the second parameter of the function addMarker.
Tested with jvectormap-2.0.2

JQVMap - How to show data values onregionclick

var setMap = function (name) {
var data = {
map: 'world_en',
backgroundColor: null,
borderColor: '#333333',
borderOpacity: 0.5,
borderWidth: 1,
color: '#c6c6c6',
enableZoom: true,
hoverColor: '#c9dfaf',
hoverOpacity: null,
values: sample_data,
normalizeFunction: 'linear',
scaleColors: ['#b6da93', '#909cae'],
selectedColor: '#c9dfaf',
selectedRegion: null,
showTooltip: true,
onLabelShow: function (event, label, code) {
},
onRegionOver: function (event, code) {
if (code == 'ca') {
event.preventDefault();
}
},
onRegionClick: function (element, code, region) {
var message = 'You clicked "' + region + '" which has the code: ' + code.toUpperCase();
alert(message);
}
};
data.map = name + '_en';
var map = jQuery('#vmap_' + name);
map.width(map.parent().parent().width());
map.show();
map.vectorMap(data);
map.hide();
}
Anyone knows how to use the values of the clicked region in the onRegionClick function?
I use this map to provide website statistics and want to alert on click something like "1000 Views in US (United States)"
As i said in my comment, i found out the solution right after i asked the question, but for those who have this little problem, too i just post my solution.
You just have to append the string you want to display to the label.
onLabelShow: function (event, label, code) {
if(sample_data[code] > 0)
label.append(': '+sample_data[code]+' Views');
}
hope it helps.

knockout bindings not being applied in rails 3 remote partial load

I have this view model in a js file that loads with my app:
var portfolioViewModel = function() {
var self = this;
this.selectedCompany = ko.observable('All Companies');
this.allComp = ko.observable(true);
this.chartSeries = ko.observableArray();
$(function(){
self.chart.addSeries(companyChart['All Companies']);
});
$.each(companyData, function(index, company) {
self[company] = ko.observable(false);
self.chartSeries.push(companyChart[company]);
});
this.chart = ko.observable();
this.showCompany = function(company){
self.hideCompanies();
self[company](true);
self.allComp(false);
self.selectedCompany(company);
while(self.chart.series.length > 0){
self.chart.series[0].remove(true);
}
self.chart.addSeries(companyChart[company]);
}
this.allCompanies = function(){
self.hideCompanies();
self.allComp(true);
self.selectedCompany('All Companies');
self.chart.addSeries(companyChart['All Companies']);
$.each(companyData, function(index, company) {
self.chart.addSeries(companyChart[company]);
});
}
this.hideCompanies = function(){
$.each(companyData, function(i, c){
self[c](false);
});
while(self.chart.series.length > 0){
self.chart.series[0].remove(true);
}
}
}
It controls adding series to a high charts chart, based on whichever company is selected.
In my partial, I have the some HTML, and then the following javascript code block:
<!--SCRIPTS-->
<script type="text/javascript">
<% companies = current_user.list_of_companies %>
<% funding_date = current_user.first_funding_date * 1000 %>
var companyData = <%= companies.map(&:name).to_json.html_safe %>;
var companyChart = {};
companyChart['All Companies'] = {
name: 'Total Portfolio',
pointInterval: <%= 1.day * 1000 %>,
pointStart: <%=funding_date %>,
data: <%= current_user.portfolio_values.group("portfolio_values.day").select("portfolio_values.day, SUM(portfolio_values.value) as totals").map(&:totals).collect{|x| x.to_i} %>
}
<% companies.each do |company|%>
companyChart['<%= company.name %>'] = {
name: '<%= company.name %>',
pointInterval: <%= 1.day * 1000 %>,
pointStart: <%= funding_date %>,
data: <%= current_user.portfolio_values.where(:company_id => company.id).map(&:value).collect{|x| x.to_i} %>
}
<% end %>
var vm = new portfolioViewModel();
ko.applyBindings(vm);
vm.chart = new Highcharts.StockChart({
chart: {
renderTo: 'chart1',
backgroundColor: 'transparent',
zoomType: 'xy',
type: 'areaspline',
style: {
color: '#ffffff'
}
},
labels : {
style: {
color: 'red'
}
},
colors: [
'#ea00ff',
'#229aff',
'#ff4e00',
'#ea00ff',
'#229aff',
'#ff4e00',
'#ea00ff',
'#229aff',
'#ff4e00',
'#ea00ff',
'#229aff',
'#ff4e00'
],
credits: {
enabled: false
},
rangeSelector: {
enabled: false,
buttons: [{
type: 'month',
count: 1,
text: '1m'
}, {
type: 'ytd',
text: 'YTD'
}, {
type: 'all',
text: 'All'
}],
buttonTheme: { // styles for the buttons
fill: 'none',
stroke: 'none',
style: {
color: '#fff',
fontWeight: 'bold'
},
states: {
hover: {
stroke: 'none',
fill: 'black'
},
select: {
stroke: 'none',
fill: 'black',
style: {
color: 'white'
}
}
}
},
inputStyle: {
color: '#fff',
fontWeight: 'bold',
borderColor:'transparent',
background: 'transparent'
},
labelStyle: {
color: 'silver',
fontWeight: 'bold'
}
},
navigator: {
enabled: false,
},
plotOptions : {
areaspline : {
lineWidth : 2,
fillOpacity : .2,
shadow:true,
marker : {
enabled : false,
symbol: 'circle'
}
}
},
yAxis: {
alternateGridColor: 'rgba(0,0,0,0.1)',
gridLineColor: 'rgba(0,0,0,0.3)',
lineColor: 'rgba(0,0,0,0.3)',
lineWidth: 1,
labels: {
style: {
color: 'rgba(255,255,255,0.6)',
fontWeight: 'bold'
}
}
},
xAxis: {
gridLineWidth: 1,
gridLineColor: 'rgba(0,0,0,0.3)',
type: 'datetime',
lineColor: 'rgba(0,0,0,0.3)',
labels: {
style: {
color: 'rgba(255,255,255,0.6)',
fontWeight: 'bold'
}
}
},
scrollbar : {
enabled : false
},
series: vm.chartSeries()
});
</script>
<!--SCRIPTS-->
Sometimes the bindings are applied and the scripts load with the partial, but many times they do not. When they do not load with the remote call to the partial (even though the HTML comes through) the script block will be completely missing it seems.
I'm not even sure how to start debugging this. Does anyone see any obvious mistakes? I'm very new to javascript.
Typically, if there's a javascript error of any kind that stops the execution of later javascript, that will prevent your ko model from loading, or cause it to load only part way. I recommend using Firebug with Firefox, or something similar, to check for the javascript error causing the problem.
Also, the 'gon' gem is a good way to get information from your rails model into your javascript. I also like using the rabl gem with .json.rabl templates for ajax requests to update the knockout model.

Categories

Resources