The `<script>` tag is used to define a client-side script (JavaScript). The "type" attribute is required in HTML 4, but optional in HTML5.
		
			
				
	
	
		
			209 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html>
 | 
						|
<html lang="en">
 | 
						|
    <head>
 | 
						|
        <meta charset="utf-8">
 | 
						|
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
						|
        <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
						|
        <title>Server-Sent Events. Room "{{.roomid}}"</title>
 | 
						|
        <!-- jQuery -->
 | 
						|
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
 | 
						|
        <script src="http://malsup.github.com/jquery.form.js"></script> 
 | 
						|
        <!-- EPOCH -->
 | 
						|
        <script src="http://d3js.org/d3.v3.min.js"></script>
 | 
						|
        <script src="/static/epoch.min.js"></script>
 | 
						|
        <link rel="stylesheet" href="/static/epoch.min.css">
 | 
						|
        <script src="/static/realtime.js"></script>
 | 
						|
        <!-- Latest compiled and minified CSS -->
 | 
						|
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
 | 
						|
        <!-- Optional theme -->
 | 
						|
        <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>
 | 
						|
            $(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">
 | 
						|
                <h1>Server-Sent Events in Go</h1>
 | 
						|
                <p>Server-sent events (SSE) is a technology where a browser receives automatic updates from a server via HTTP connection. It is not websockets. <a href="http://www.html5rocks.com/en/tutorials/eventsource/basics/">Learn more.</a></p>
 | 
						|
                <p>The chat and the charts data is provided in realtime using the SSE implementation 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">
 | 
						|
                    <div class="col-md-8">
 | 
						|
                        <div id="chat-scroll" style="overflow-y:scroll; overflow-x:scroll; height:290px">
 | 
						|
                            <table id="table-style" class="table" data-show-header="false">
 | 
						|
                                <thead>
 | 
						|
                                    <tr>
 | 
						|
                                        <th data-field="nick" class="col-md-2">Nick</th>
 | 
						|
                                        <th data-field="message" class="col-md-8">Message</th>
 | 
						|
                                    </tr>
 | 
						|
                                </thead>
 | 
						|
                                <tbody id="chat"></tbody>
 | 
						|
                            </table>
 | 
						|
                        </div>
 | 
						|
                        {{if .nick}}
 | 
						|
                        <form autocomplete="off" class="form-inline" id="chat-form" action="/room-post/{{.roomid}}?nick={{.nick}}" method="post">
 | 
						|
                            <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 type="text" name="message" id="chat-message" class="form-control" placeholder="a message" value="">
 | 
						|
                                </div>
 | 
						|
                            </div>
 | 
						|
                            <input type="submit" class="btn btn-primary" value="Send">
 | 
						|
                        </form>
 | 
						|
                        {{else}}
 | 
						|
                        <form action="" method="get" class="form-inline">
 | 
						|
                            <legend>Join the SSE real-time chat</legend>
 | 
						|
                            <div class="form-group">
 | 
						|
                                <input value='' name="nick" id="nick" placeholder="Your Name" type="text" class="form-control">
 | 
						|
                            </div>
 | 
						|
                            <div class="form-group text-center">
 | 
						|
                                <input type="submit" class="btn btn-success btn-login-submit" value="Join">
 | 
						|
                            </div>
 | 
						|
                        </form>
 | 
						|
                        {{end}}
 | 
						|
                    </div>
 | 
						|
                    <div class="col-md-4">
 | 
						|
                        <div id="messagesChart" class="epoch category10"></div>
 | 
						|
                        <p>
 | 
						|
                        <span style="font-size:20px; color:#1f77b4">◼︎</span> Users<br>
 | 
						|
                        <span style="font-size:20px; color:#ff7f0e">◼︎</span> Inbound messages / sec<br>
 | 
						|
                        <span style="font-size:20px; color:#2ca02c">◼︎</span> Outbound messages / sec<br>
 | 
						|
                        </p>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
        <div class="container">
 | 
						|
            <div class="row">
 | 
						|
                <h2>Realtime server Go stats</h2>
 | 
						|
                <div class="col-md-6">
 | 
						|
                    <h3>Memory usage</h3>
 | 
						|
                    <p>
 | 
						|
                    <div id="heapChart" class="epoch category20c"></div>
 | 
						|
                    </p>
 | 
						|
                    <p>
 | 
						|
                    <span style="font-size:20px; color:#1f77b4">◼︎</span> Heap bytes<br>
 | 
						|
                    <span style="font-size:20px; color:#aec7e8">◼︎</span> Stack bytes<br>
 | 
						|
                    </p>
 | 
						|
                </div>
 | 
						|
                <div class="col-md-6">
 | 
						|
                    <h3>Allocations per second</h3>
 | 
						|
                    <p>
 | 
						|
                    <div id="mallocsChart" class="epoch category20b"></div>
 | 
						|
                    </p>
 | 
						|
                    <p>
 | 
						|
                    <span style="font-size:20px; color:#393b79">◼︎</span> Mallocs / sec<br>
 | 
						|
                    <span style="font-size:20px; color:#5254a3">◼︎</span> Frees / sec<br>
 | 
						|
                    </p>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
            <div class="row">
 | 
						|
                <h2>MIT Open Sourced</h2>
 | 
						|
                <ul>
 | 
						|
                    <li><a href="https://github.com/gin-gonic/gin/tree/develop/examples/realtime-advanced">This demo website (JS and Go)</a></li>
 | 
						|
                    <li><a href="https://github.com/manucorporat/sse">The SSE implementation in Go</a></li>
 | 
						|
                    <li><a href="https://github.com/gin-gonic/gin">The Web Framework (Gin)</a></li>
 | 
						|
                </ul>
 | 
						|
                <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>
 | 
						|
            <div class="row">
 | 
						|
                <div class="col-md-12">
 | 
						|
                    <h3>SSE package</h3>
 | 
						|
                    <pre><code class="language-go">import "github.com/manucorporat/sse"
 | 
						|
 | 
						|
func httpHandler(w http.ResponseWriter, req *http.Request) {
 | 
						|
    // data can be a primitive like a string, an integer or a float
 | 
						|
    sse.Encode(w, sse.Event{
 | 
						|
        Event: "message",
 | 
						|
        Data:  "some data\nmore data",
 | 
						|
    })
 | 
						|
 | 
						|
    // also a complex type, like a map, a struct or a slice
 | 
						|
    sse.Encode(w, sse.Event{
 | 
						|
        Id:    "124",
 | 
						|
        Event: "message",
 | 
						|
        Data: map[string]interface{}{
 | 
						|
            "user":    "manu",
 | 
						|
            "date":    time.Now().Unix(),
 | 
						|
            "content": "hi!",
 | 
						|
        },
 | 
						|
    })
 | 
						|
}</code></pre>
 | 
						|
<pre>event: message
 | 
						|
data: some data\\nmore data
 | 
						|
 | 
						|
id: 124
 | 
						|
event: message
 | 
						|
data: {"content":"hi!","date":1431540810,"user":"manu"}</pre>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
            <hr>
 | 
						|
            <footer>
 | 
						|
                <p>Created with <span class="glyphicon glyphicon-heart"></span> by <a href="https://github.com/manucorporat">Manu Martinez-Almeida</a></p>
 | 
						|
            </footer>
 | 
						|
        </div>
 | 
						|
    </body>
 | 
						|
</html>
 |