Skip to content

Instantly share code, notes, and snippets.

@maccman
Forked from lifo/Gemfile
Created February 11, 2010 14:14

Revisions

  1. @lifo lifo revised this gist Jan 11, 2010. 2 changed files with 5 additions and 1 deletion.
    3 changes: 3 additions & 0 deletions Gemfile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    gem 'cramp'
    gem 'erubis', '2.6.5'
    gem 'usher', "0.6.0"
    3 changes: 2 additions & 1 deletion chat_ramp.rb
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    require 'rubygems'
    require 'vendor/gems/environment'

    require 'cramp/controller'
    require 'erubis'
    require 'usher'
  2. @lifo lifo revised this gist Jan 11, 2010. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions chat_ramp.rb
    Original file line number Diff line number Diff line change
    @@ -23,13 +23,11 @@ class SocketAction < Cramp::Controller::Websocket
    on_data :message_received

    def user_connected
    @time = Time.now
    @@users << self
    end

    def user_left
    @@users.delete self
    puts "USER LEFT IN #{Time.now - @time} seconds"
    end

    def message_received(data)
  3. @lifo lifo revised this gist Jan 10, 2010. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions chat_ramp.rb
    Original file line number Diff line number Diff line change
    @@ -23,11 +23,13 @@ class SocketAction < Cramp::Controller::Websocket
    on_data :message_received

    def user_connected
    @time = Time.now
    @@users << self
    end

    def user_left
    @@users.delete self
    puts "USER LEFT IN #{Time.now - @time} seconds"
    end

    def message_received(data)
  4. @lifo lifo revised this gist Jan 10, 2010. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion chat_ramp.rb
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@

    module ChatRamp
    class HomeAction < Cramp::Controller::Action
    @@template = Erubis::Eruby.new(File.read('views/index.erb'))
    @@template = Erubis::Eruby.new(File.read('index.erb'))

    def start
    render @@template.result(binding)
  5. @lifo lifo created this gist Jan 10, 2010.
    44 changes: 44 additions & 0 deletions chat_ramp.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    require 'rubygems'
    require 'cramp/controller'
    require 'erubis'
    require 'usher'

    Cramp::Controller::Websocket.backend = :thin

    module ChatRamp
    class HomeAction < Cramp::Controller::Action
    @@template = Erubis::Eruby.new(File.read('views/index.erb'))

    def start
    render @@template.result(binding)
    finish
    end
    end

    class SocketAction < Cramp::Controller::Websocket
    @@users = Set.new

    on_start :user_connected
    on_finish :user_left
    on_data :message_received

    def user_connected
    @@users << self
    end

    def user_left
    @@users.delete self
    end

    def message_received(data)
    @@users.each {|u| u.render data }
    end
    end
    end

    routes = Usher::Interface.for(:rack) do
    add('/').to(ChatRamp::HomeAction)
    add('/socket').to(ChatRamp::SocketAction)
    end

    Rack::Handler::Thin.run routes, :Port => 8080
    109 changes: 109 additions & 0 deletions index.erb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,109 @@
    <!-- Taken from http://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk/test-jetty-webapp/src/main/webapp/ws/index.html -->

    <html><head>
    <title>WebSocket Chat</title>
    <script type='text/javascript'>

    if (!window.WebSocket)
    alert("WebSocket not supported by this browser");

    function $() { return document.getElementById(arguments[0]); }
    function $F() { return document.getElementById(arguments[0]).value; }

    function getKeyCode(ev) { if (window.event) return window.event.keyCode; return ev.keyCode; }

    var room = {
    join: function(name) {
    this._username=name;
    var location = 'ws://<%= request.host_with_port %>/socket'
    // document.location.toString().replace('http:','ws:');
    this._ws=new WebSocket(location);
    this._ws.onopen=this._onopen;
    this._ws.onmessage=this._onmessage;
    this._ws.onclose=this._onclose;
    },

    _onopen: function(){
    $('join').className='hidden';
    $('joined').className='';
    $('phrase').focus();
    room._send(room._username,'has joined!');
    },

    _send: function(user,message){
    user=user.replace(':','_');
    if (this._ws)
    this._ws.send(user+':'+message);
    },

    chat: function(text) {
    if (text != null && text.length>0 )
    room._send(room._username,text);
    },

    _onmessage: function(m) {
    if (m.data){
    var c=m.data.indexOf(':');
    var from=m.data.substring(0,c).replace('<','&lt;').replace('>','&gt;');
    var text=m.data.substring(c+1).replace('<','&lt;').replace('>','&gt;');

    var chat=$('chat');
    var spanFrom = document.createElement('span');
    spanFrom.className='from';
    spanFrom.innerHTML=from+':&nbsp;';
    var spanText = document.createElement('span');
    spanText.className='text';
    spanText.innerHTML=text;
    var lineBreak = document.createElement('br');
    chat.appendChild(spanFrom);
    chat.appendChild(spanText);
    chat.appendChild(lineBreak);
    chat.scrollTop = chat.scrollHeight - chat.clientHeight;
    }
    },

    _onclose: function(m) {
    this._ws=null;
    $('join').className='';
    $('joined').className='hidden';
    $('username').focus();
    $('chat').innerHTML='';
    }

    };

    </script>
    <style type='text/css'>
    div { border: 0px solid black; }
    div#chat { clear: both; width: 40em; height: 20ex; overflow: auto; background-color: #f0f0f0; padding: 4px; border: 1px solid black; }
    div#input { clear: both; width: 40em; padding: 4px; background-color: #e0e0e0; border: 1px solid black; border-top: 0px }
    input#phrase { width:30em; background-color: #e0f0f0; }
    input#username { width:14em; background-color: #e0f0f0; }
    div.hidden { display: none; }
    span.from { font-weight: bold; }
    span.alert { font-style: italic; }
    </style>
    </head><body>
    <div id='chat'></div>
    <div id='input'>
    <div id='join' >
    Username:&nbsp;<input id='username' type='text'/><input id='joinB' class='button' type='submit' name='join' value='Join'/>
    </div>
    <div id='joined' class='hidden'>
    Chat:&nbsp;<input id='phrase' type='text'/>
    <input id='sendB' class='button' type='submit' name='join' value='Send'/>
    </div>
    </div>
    <script type='text/javascript'>
    $('username').setAttribute('autocomplete','OFF');
    $('username').onkeyup = function(ev) { var keyc=getKeyCode(ev); if (keyc==13 || keyc==10) { room.join($F('username')); return false; } return true; } ;
    $('joinB').onclick = function(event) { room.join($F('username')); return false; };
    $('phrase').setAttribute('autocomplete','OFF');
    $('phrase').onkeyup = function(ev) { var keyc=getKeyCode(ev); if (keyc==13 || keyc==10) { room.chat($F('phrase')); $('phrase').value=''; return false; } return true; };
    $('sendB').onclick = function(event) { room.chat($F('phrase')); $('phrase').value=''; return false; };
    </script>

    <p>
    This is a demonstration of the <a href="http://m.onkey.org/2010/1/7/introducing-cramp">Cramp Framework</a>'s websocket capabiltiy using HTML from <a href="http://jetty.mortbay.org/">Jetty websocket server</a>.
    </p>
    </body></html>