|
|
@@ -19,13 +19,41 @@
|
|
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
|
|
|
<!-- Latest compiled and minified JavaScript -->
|
|
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
|
|
+ <!-- Primjs -->
|
|
|
+ <link href="/static/prismjs.min.css" rel="stylesheet" />
|
|
|
+
|
|
|
<script type="text/javascript">
|
|
|
$(document).ready(function() {
|
|
|
StartRealtime({{.roomid}}, {{.timestamp}});
|
|
|
});
|
|
|
</script>
|
|
|
+ <style>
|
|
|
+ body { padding-top: 50px; }
|
|
|
+ </style>
|
|
|
</head>
|
|
|
<body>
|
|
|
+ <nav class="navbar navbar-fixed-top navbar-inverse">
|
|
|
+ <div class="container">
|
|
|
+ <div class="navbar-header">
|
|
|
+ <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
|
|
+ <span class="sr-only">Toggle navigation</span>
|
|
|
+ <span class="icon-bar"></span>
|
|
|
+ <span class="icon-bar"></span>
|
|
|
+ <span class="icon-bar"></span>
|
|
|
+ </button>
|
|
|
+ <a class="navbar-brand" href="#">Server-Sent Events</a>
|
|
|
+ </div>
|
|
|
+ <div id="navbar" class="collapse navbar-collapse">
|
|
|
+ <ul class="nav navbar-nav">
|
|
|
+ <li class="active"><a href="#">Demo</a></li>
|
|
|
+ <li><a href="http://www.w3.org/TR/2009/WD-eventsource-20091029/">W3 Standard</a></li>
|
|
|
+ <li><a href="http://caniuse.com/#feat=eventsource">Browser Support</a></li>
|
|
|
+ <li><a href="http://gin-gonic.github.io/gin/">Gin Framework</a></li>
|
|
|
+ <li><a href="https://github.com/gin-gonic/gin/tree/develop/examples/realtime-advanced">Github</a></li>
|
|
|
+ </ul>
|
|
|
+ </div><!-- /.nav-collapse -->
|
|
|
+ </div><!-- /.container -->
|
|
|
+ </nav><!-- /.navbar -->
|
|
|
<!-- Main jumbotron for a primary marketing message or call to action -->
|
|
|
<div class="jumbotron">
|
|
|
<div class="container">
|
|
|
@@ -33,10 +61,8 @@
|
|
|
<p><a href="http://www.html5rocks.com/en/tutorials/eventsource/basics/">Server-sent events (SSE)</a> is a technology where a browser receives automatic updates from a server via HTTP connection.</p>
|
|
|
<p>The chat and the charts data is provided in realtime using the SSE implemention of <a href="https://github.com/gin-gonic/gin/blob/15b0c49da556d58a3d934b86e3aa552ff224026d/examples/realtime-chat/main.go#L23-L32">Gin Framework</a>.</p>
|
|
|
<div class="row">
|
|
|
- {{if not .nick}}
|
|
|
<div class="col-md-8">
|
|
|
- {{end}}
|
|
|
- <div id="chat-scroll" style="overflow-y:scroll; overflow-x:scroll; height:200px">
|
|
|
+ <div id="chat-scroll" style="overflow-y:scroll; overflow-x:scroll; height:270px">
|
|
|
<table id="table-style" class="table">
|
|
|
<thead>
|
|
|
<tr>
|
|
|
@@ -49,17 +75,22 @@
|
|
|
</div>
|
|
|
{{if .nick}}
|
|
|
<form class="form-inline" id="chat-form" action="/room/{{.roomid}}?nick={{.nick}}" method="post">
|
|
|
- <div class="form-group col-md-6">
|
|
|
- <input name="message" id="chat-message" placeholder="a message" type="text" class="form-control" style="width:100%" />
|
|
|
- </div>
|
|
|
- <div class="form-group col-md-2">
|
|
|
- <input type="submit" class="btn btn-primary" value="Send" />
|
|
|
+ <div class="form-group">
|
|
|
+ <label class="sr-only" for="chat-message">Message</label>
|
|
|
+ <div class="input-group">
|
|
|
+ <div class="input-group-addon">{{.nick}}</div>
|
|
|
+ <input name="message" id="chat-message" placeholder="a message" type="text" class="form-control" />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ <input type="submit" class="btn btn-primary" value="Send" />
|
|
|
</form>
|
|
|
{{end}}
|
|
|
- {{if not .nick}}
|
|
|
</div>
|
|
|
<div class="col-md-4">
|
|
|
+ {{if .nick}}
|
|
|
+ <h3>Inbound/Outbound</h3>
|
|
|
+ <div id="messagesChart" class="epoch category20c"></div>
|
|
|
+ {{else}}
|
|
|
<form action="" method="get">
|
|
|
<legend>Join the SSE real-time chat</legend>
|
|
|
<div class="form-group">
|
|
|
@@ -70,13 +101,14 @@
|
|
|
<input type="submit" class="btn btn-success btn-login-submit" value="Join" />
|
|
|
</div>
|
|
|
</form>
|
|
|
+ {{end}}
|
|
|
</div>
|
|
|
- {{end}}
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="container">
|
|
|
<div class="row">
|
|
|
+ <h2>Realtime server Go stats</h2>
|
|
|
<div class="col-md-4">
|
|
|
<h3>Number of Goroutines</h3>
|
|
|
<p>
|
|
|
@@ -96,9 +128,41 @@
|
|
|
</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <div class="row">
|
|
|
+ <h2>Source code</h2>
|
|
|
+ <div class="col-md-6">
|
|
|
+ <script src="/static/prismjs.min.js"></script>
|
|
|
+ <h3>Server-side (Go)</h3>
|
|
|
+ <pre><code class="language-go">func streamRoom(c *gin.Context) {
|
|
|
+ roomid := c.ParamValue("roomid")
|
|
|
+ listener := openListener(roomid)
|
|
|
+ statsTicker := time.NewTicker(1 * time.Second)
|
|
|
+ defer closeListener(roomid, listener)
|
|
|
+ defer statsTicker.Stop()
|
|
|
+
|
|
|
+ c.Stream(func(w io.Writer) bool {
|
|
|
+ select {
|
|
|
+ case msg := <-listener:
|
|
|
+ c.SSEvent("message", msg)
|
|
|
+ case <-statsTicker.C:
|
|
|
+ c.SSEvent("stats", Stats())
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ })
|
|
|
+}</code></pre>
|
|
|
+ </div>
|
|
|
+ <div class="col-md-6">
|
|
|
+ <h3>Client-side (JS)</h3>
|
|
|
+ <pre><code class="language-javascript">function StartSSE(roomid) {
|
|
|
+ var source = new EventSource('/stream/'+roomid);
|
|
|
+ source.addEventListener('message', newChatMessage, false);
|
|
|
+ source.addEventListener('stats', stats, false);
|
|
|
+}</code></pre>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
<hr>
|
|
|
<footer>
|
|
|
- <p>© Company 2014</p>
|
|
|
+ <p>Created with <span class="glyphicon glyphicon-heart"></span> by <a href="https://github.com/manucorporat">Manu Martinez-Almeida</a></p>
|
|
|
</footer>
|
|
|
</div>
|
|
|
</body>
|