Using EON charts in a Ember Page - pubnub

We are trying to use (pubnub) EON charts in an Ember application.
While we see this which talks about using pubnub APIs in Ember, this doesn't talk about EON charts.
Is there a "Ember wrapped" EON chart variant? Either way some sample code will be helpful.

You can use EON with Ember just like any other library. Check out this example which combines the EON real time spline chart example and the ember starter kit.
Your HTML:
<script type="text/javascript" src="//pubnub.github.io/eon/v/eon/0.0.9/eon.js"></script>
<link type="text/css" rel="stylesheet" href="//pubnub.github.io/eon/v/eon/0.0.9/eon.css"/>
<div id="chart"></div>
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" id="index">
<ul>
{{#each item in model}}
<li>{{item}}</li>
{{/each}}
</ul>
</script>
And then in your JS:
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
}
});
var pubnub = PUBNUB.init({
publish_key: 'demo',
subscribe_key: 'demo'
});
var channel = "c3-spline" + Math.random();
eon.chart({
channel: channel,
history: true,
flow: true,
pubnub: pubnub,
generate: {
bindto: '#chart',
data: {
labels: false
}
}
});
var pubnub = PUBNUB.init({
publish_key: 'demo',
subscribe_key: 'demo'
});
setInterval(function(){
pubnub.publish({
channel: channel,
message: {
eon: {
'Austin': Math.floor(Math.random() * 99),
'New York': Math.floor(Math.random() * 99),
'San Francisco': Math.floor(Math.random() * 99),
'Portland': Math.floor(Math.random() * 99)
}
}
});
}, 1000);

Related

How to make a Graph on VueJS

Am trying to make a graph with data received from an API and put this on a graph (https://bl.ocks.org/mbostock/4062045) - Force-Directed Graph
However I am unsure on how this is done on VueJs or if there is a simpler tool to do this?
D3 Force-Directed Graph seems a bit complicated, maybe there is a library already that does this out of the box?
The mentioned vue-d3 package from the comment is just adding D3 to the Vue prototype so it is accessible with this.$d3.
I've tested that package but it wasn't working with my D3 version. Looks like a casing issue (D3 instead of d3). So I've added the prototype manually.
I don't know if there is an easier library for creating a force graph but please have a look at the demo below or this fiddle.
I've modified the example from your link to create a force directed graph. The demo is working but as you've mentioned it's pretty complicated.
Also binding from SVG to Vue.js model could be improved. But I couldn't find a better way to do it.
For example adding a new node on click is not working with just adding a new node to the array but this should be the goal for a Vue.js component. The SVG graph should automatically update once the data changes.
At the moment, nodes and links in Vue.js are not used in the component because I don't know how to add the updating of the graph.
If you figured out how to add the updating with the model data, please let me know. Refreshing the whole chart is pretty easy by deleting the SVG and re-create it. (see reload button)
// https://unpkg.com/vue-d3#0.1.0 --> only adds d3 to Vue.prototype but it wasn't working as expected (d3 is lower case)
Vue.prototype.$d3 = d3;
const URL = 'https://demo5147591.mockable.io/miserables'; // data copied from below link because of jsonp support
//'https://bl.ocks.org/mbostock/raw/4062045/5916d145c8c048a6e3086915a6be464467391c62/miserables.json';
//console.log(window.d3);
const d3ForceGraph = {
template: `
<div>
{{mousePosition}}
<button #click="reload">reload</button>
<svg width="600" height="600"
#mousemove="onMouseMove($event)"></svg>
</div>
`,
data() {
return {
nodes: [],
links: [],
simulation: undefined,
mousePosition: {
x: 0,
y: 0
}
}
},
mounted() {
this.loadData(); // initially load json
},
methods: {
// load data
loadData() {
this.$svg = $(this.$el).find('svg');
let svg = this.$d3.select(this.$svg.get(0)), //this.$d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
//console.log($(this.$el).find('svg').get(0));
this.simulation = this.$d3.forceSimulation()
.force("link", this.$d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", this.$d3.forceManyBody())
.force("center", this.$d3.forceCenter(width / 2, height / 2));
let color = this.$d3.scaleOrdinal(this.$d3.schemeCategory20);
$.getJSON(URL, (graph) => {
//d3.json("miserables.json", function(error, graph) { // already loaded
//if (error) throw error; // needs to be implemented differently
let nodes = graph.nodes;
let links = graph.links;
let link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(links) //graph.links)
.enter().append("line")
.attr("stroke-width", function(d) {
return Math.sqrt(d.value);
});
let node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(nodes) //graph.nodes)
.enter().append("circle")
.attr("r", 5)
.attr("fill", function(d) {
return color(d.group);
})
.call(this.$d3.drag()
.on("start", this.dragstarted)
.on("drag", this.dragged)
.on("end", this.dragended));
node.append("title")
.text(function(d) {
return d.id;
});
this.simulation
.nodes(graph.nodes)
.on("tick", ticked);
this.simulation.force("link")
.links(links); //graph.links);
function ticked() {
link
.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
}
})
},
reload() {
//console.log('reloading...');
this.$svg.empty(); // clear svg --> easiest way to re-create the force graph.
this.loadData();
},
// mouse events
onMouseMove(evt) {
//console.log(evt, this)
this.mousePosition = {
x: evt.clientX,
y: evt.clientY
}
},
// drag event handlers
dragstarted(d) {
if (!this.$d3.event.active) this.simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
},
dragged(d) {
d.fx = this.$d3.event.x;
d.fy = this.$d3.event.y;
},
dragended(d) {
if (!this.$d3.event.active) this.simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
}
};
new Vue({
el: '#app',
data() {
return {}
},
components: {
d3ForceGraph
}
});
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.8.0/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app">
<d3-force-graph></d3-force-graph>
</div>
I answered another question on vue + d3 by providing an example of a d3 force graph with vue.js.
d3.js is now split in small modules and specific computations are isolated in small components like d3-force. SVG can be drawn in a component template like any other HTML structure.
You can use vue-d3-network
npm install vue-d3-network
see this fiddle
html:
```
<head>
<script type="text/javascript" src="https://unpkg.com/vue">
</script>
<link rel="stylesheet" type="text/css" href="https://rawgit.com/emiliorizzo/vue-d3-network/master/dist/vue-d3-network.css">
<script type="text/javascript" src="https://rawgit.com/emiliorizzo/vue-d3-network/master/dist/vue-d3-network.umd.js"></script>
</head>
<body>
<div id="app">
<d3-network :net-nodes="nodes" :net-links="links" :options="options">
</d3-network>
</div>
</body>
```
javascript:
```
var D3Network = window['vue-d3-network']
new Vue({
el: '#app',
components: {
D3Network
},
data () {
return {
nodes: [
{ id: 1, name: 'my node 1' },
{ id: 2, name: 'my node 2' },
{ id: 3, _color:'orange' },
{ id: 4 },
{ id: 5 },
{ id: 6 },
{ id: 7 },
{ id: 8 },
{ id: 9 }
],
links: [
{ sid: 1, tid: 2, _color:'red' },
{ sid: 2, tid: 8, _color:'f0f' },
{ sid: 3, tid: 4,_color:'rebeccapurple' },
{ sid: 4, tid: 5 },
{ sid: 5, tid: 6 },
{ sid: 7, tid: 8 },
{ sid: 5, tid: 8 },
{ sid: 3, tid: 8 },
{ sid: 7, tid: 9 }
],
options:
{
force: 3000,
nodeSize: 20,
nodeLabels: true,
linkWidth:5
}
}
},
})
```

How to add img src attribute with VueJs

In my NodeJs route, I have the following:
router.get('/list/:id', function(req, res, next) {
request("http://localhost:3000/api/journal/" + req.params.id, function(error, response, body) {
var json = JSON.parse(body);
res.render('listdetail', { title: 'Journal', data: json });
});
});
The data is a json object containing all my screen fields. One of the fields is a base64 presentation of an image.
Then, in my List Detail html I have the following:
<div id="app">
<img class="materialboxed" src="{{data.base64Image}}" width="200">
</div>
This is surely not working... How can I add to the src attribute the base64 information that was sent by NodeJS?
I tried also the following:
<img class="materialboxed" :src=imagebase64Source width="200">
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
imagebase64Source: {{data.base64Image}}
}
})
</script>
But it obviously does not work
Thanks
EDIT:
Strange, it's working now!
Here's what I've done:
<img class="materialboxed" src="{{ data.base64Image }}" width="200">
The only difference I can see is the spacing between the mustache.
Thanks to all who helped.
You can do it simply like this:
<template>
<div>
<img :src="image"/>
</div>
</template>
<script>
module.exports = {
data: function() {
return {
image: //your b64 string there
};
}
};
</script>
Pay attention by the way, depending on what you have on your string, you may have to add a header to the raw string.
<template>
<div>
<img :src="imgWithHeader"/>
</div>
</template>
<script>
module.exports = {
data: function() {
return {
image: //your b64 string there
};
},
computed: {
imgWithHeader() {
return 'data:' + MIMETypeOfTheImage + ';base64,' + this.image;
}
}
};
</script>
Of course you should figure out what is the type of the image, in this case.
I think the method you tried should work if the syntax is corrected
So this:
<img class="materialboxed" :src=imagebase64Source width="200">
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
imagebase64Source: {{data.base64Image}}
}
})
</script>
should be changed to this:
<img class="materialboxed" :src="imagebase64Source" width="200">
<script type="text/javascript">
var app = new Vue({
el: '#app',
data () {
return {
imagebase64Source: data.base64Image,
}
}
})
</script>

Cannot Get Typeahead.js Working with MVC 5 Over Remote

I have no idea what I'm doing wrong, but I cannot get typeahead working in my MVC 5 application. I installed everything via NuGet and my view includes #Scripts.Render("~/bundles/typeahead"), which is rendering properly when viewing the source of the view. So the issue isn't that the dependencies are missing.
I am not seeing any drop down appear when I start typing, and using Fiddler I do not see any calls being made out to the remote that I setup that pulls the data.
Here's the line in my view that typeahead is being attached:
#Html.TextBoxFor(m => m.MainInfo.CompanyName,
new { #class = "form-control typeahead", id = "comp-name", autocomplete="off" })
Here's the portion of my script that configures typeahead and bloodhound:
$(document).ready(function() {
var clients = new Bloodhound({
datumTokenizer: function (datum) {
return Bloodhound.tokenizers.whitespace(datum.value);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "/info/client?like=%QUERY",
wildcard: '%QUERY',
filter: function (clients) {
return $.map(clients, function (client) {
return {
value: client.Name,
clientId: client.Identifier
};
});
}
}
});
clients.initialize();
$('#comp-name').typeahead(null,
{
display: 'value',
minLength: 1,
source: clients.ttAdapter(),
templates: {
empty: "Looks like a new client...",
suggestion: Handlebars.compile("<p><b>{{value}}</b> - {{clientId}}</p>")
}
});
});
Is there something that I've configured wrong in my javascript? I've used a few tutorials as well as their own documentation, but I cannot figure out what I'm doing wrong here. It almost feels like it's not properly initialized, but there are no errors being thrown.
NOTE: Just as an FYI I'm using Bootstrap 3 as well in case that changes anything.
EDIT: Here's my #section Scripts:
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/typeahead")
<script src="#Url.Content("~/Scripts/handlebars.min.js")"></script>
<script src="#Url.Content("~/Scripts/ProjectSetupFormScripts.js")"></script> <-- this is where typeahead is set up
This did the trick for me:
JS
#section Scripts {
<script type="text/javascript">
$(function () {
SetupTipeahead();
});
function SetupTipeahead() {
var engine = new Bloodhound({
remote: {
url: '/Employees/AllEmployees',
ajax: {
type: 'GET'
}
},
datumTokenizer: function (d) {
return Bloodhound.tokenizers.whitespace(d.FullName);
},
queryTokenizer: Bloodhound.tokenizers.whitespace
});
engine.initialize();
$('#FullName').typeahead(null, {
displayKey: 'FullName',
source: engine.ttAdapter(),
templates: {
empty: [
'<div class="empty-message">',
'No match',
'</div>'
].join('\n'),
suggestion: function (data) {
return '<p class="">' + data.FullName + '</p><p class="">' + data.ManNumber + '</p>';
}
}
});
}
</script>
EmployeesController has the following JsonResult
public JsonResult AllEmployees()
{
return Json(db.Employees.ToList(),JsonRequestBehavior.AllowGet);
}
Hello try to wrap your script in #section scripts {} this will place the script at the bottom just before the </body> tag and make sure you are not calling the function before your bundles load.
#section scripts {
<script>
$(document).ready(function() {
var clients = new Bloodhound({
datumTokenizer: function (datum) {
return Bloodhound.tokenizers.whitespace(datum.value);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "/info/client?like=%QUERY",
wildcard: '%QUERY',
filter: function (clients) {
return $.map(clients, function (client) {
return {
value: client.Name,
clientId: client.Identifier
};
});
}
}
});
clients.initialize();
$('#comp-name').typeahead(null,
{
display: 'value',
minLength: 1,
source: clients.ttAdapter(),
templates: {
empty: "Looks like a new client...",
suggestion: Handlebars.compile("<p><b>{{value}}</b> - {{clientId}}</p>")
}
});
});
</script>
}

React and Socket.io

I'm trying to create a simple app using ReactJS and Socket.io
In my component I want to be able to communicate with the server, but the problem is that I don't know how to do io.connect()
1.Do I need to explicitly specify the IP address like io.connect("http://myHost:7000") or is it enough to say : io.connect() ? As we can see in this piece of code :
https://github.com/DanialK/ReactJS-Realtime-Chat/blob/master/client/app.jsx
2.I do more or less the same as this code , but I receive error when I do npm start as io is undefined. I think , io is provided globally by including the socket.io script. How can I solve this problem ?
'use strict';
var React = require('react');
var socket = io.connect();
var chatWindow = React.createClass({
displayName: 'chatWindow',
propTypes: {},
getDefaultProps: function() {
return ({
messages: 0
});
},
componentDidMount: function() {
socket = this.props.io.connect();
socket.on('value', this._messageRecieve);
},
_messageRecieve: function(messages) {
this.setState({
messages: messages
});
},
getInitialState: function() {
return ({
messages: 0
});
},
_handleSend: function(){
var newValue = parseInt(this.refs.messageBox.value) + this.props.messages;
this.setState({
messages: newValue
});
socket.emit('clientMessage', { message: newValue});
},
render: function() {
var window =
<div>
<div>{this.props.messages}</div>
<input type="text" id="messageBox" refs="messageBox"></input>
<input type="button" onClick={this._handleSend} value="send" id="send"/>
</div>;
return (window);
}
});
module.exports = chatWindow;
This is the code :
https://github.com/arian-hosseinzadeh/simple-user-list
Answers:
1) No, you don't need to specify the IP, you can even use / and it will go through the default HTTP 80 port, anyway, you can find more examples on the socket.io site.
2) Require io too, remember to add socket.io-client to your package:
var React = require('react'),
io = require('socket.io-client');
Anyway, if you want to include the client script that socket.io server provides as a static file, then remember to add it into your HTML using a <script/> tag, that way you'll have io on the global scope avoiding the require part, but well, I prefer to require it.
NOW, WHAT ABOUT...
Trying my lib: https://www.npmjs.com/package/react-socket
It will handle the socket connection on mount and disconnection on unmount (the same goes for socket event listeners), give it a try and let me know.
Here you have an example:
http://coma.github.io/react-socket/
var App = React.createClass({
getInitialState: function() {
return {
tweets: []
};
},
onTweet: function(tweet) {
var tweets = this
.state
.tweets
.slice();
tweet.url = 'https://twitter.com/' + tweet.user + '/status/' + tweet.id;
tweet.at = new Date(tweet.at);
tweet.avatar = {
backgroundImage: 'url(' + tweet.img + ')'
};
tweets.unshift(tweet);
this.setState({
tweets: tweets
});
},
renderTweet: function (tweet) {
return (
<li key={tweet.id}>
<a href={tweet.url} target="_blank">
<div className="user">
<div className="avatar" style={ tweet.avatar }/>
<div className="name">{ tweet.user }</div>
</div>
<div className="text">{ tweet.text }</div>
</a>
</li>
);
},
render: function () {
return (
<div>
<ReactSocket.Socket url="http://tweets.socket.io"/>
<ReactSocket.Event name="tweet" callback={ this.onTweet }/>
<ul className="tweets">{ this.state.tweets.map(this.renderTweet) }</ul>
</div>
);
}
});
React.render(<App/>, document.body);

Vue.Js Beginner about Component

I have a little problem with my code and need some advice.
I try to simulate a diceroll with Vue.js. To be sure any diceroll is different, i want to create a component for that. I use that code for my app.js
Vue.component('diceroll', {
template: 'This is the result !' + diceroll,
data: function() {
return {
diceroll: 0
}
},
methods: function(){
diceroll: Math.floor(Math.random() * 6) + 1;
}
}
)
var demo = new Vue( {
el: ' #demo',
}
)
Obviously, it don't work and i don't understand how to do that. I read the doc and watch the laracast's series but...
Someone can help me on this ? ^^
"methods" in Vue are actually objects (key-value pair) where the value is a function. Also, inside the template you have to refer variables using mustache binding like this: {{ vName }}.
I made example: (here is a jsbin demo)
Vue.component('diceroll', {
template: 'This is the result: {{diceroll}}',
data: function() {
return {
diceroll: 0
};
},
methods: {
roll: function() {
this.diceroll = Math.floor(Math.random() * 6) + 1;
}
},
ready: function() {
this.roll();
}
});
var demo = new Vue({
el: '#demo'
});
<script src="http://vuejs.org/js/vue.js"></script>
<div id="demo">
<diceroll></diceroll>
</div>

Resources