title: RealTime Collaborative Text-Editor in Nodejs & Socket.io
body: <p>I am developing a <strong>real-time</strong> text editor with paragraph locking property similar to  <a href="https://quip.com/" rel="nofollow">https://quip.com/</a>.  in <strong>socket.io</strong> and <strong>nodejs</strong>.</p>
  
  <p>It means when you write onto a given paragraph, other <strong>collaborators</strong> cant edit it. </p>
  
  <p>Moment you hit enter or move cursor to a new line that paragraph becomes <strong>Editable</strong> for other <strong>Collaborators</strong>.</p>
  
  <p>I am quite stuck after this. I am thinking a nice <strong>approach</strong> to move further. Suggestions please.</p>
  
  <p>Below is my <strong>code</strong> which works perfectly. Till now i can get list of all collaborators and broadcast the content of editor to other collaborators.</p>
  
  <p><strong>index.html</strong></p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
      &lt;title&gt;Connected Clients&lt;/title&gt;
      &lt;!--&lt;meta charset="UTF-8"&gt; --&gt;
      &lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"&gt;&lt;/script&gt; 
      &lt;!--&lt;script type="text/javascript" src="jquery.js"&gt;&lt;/script&gt;  --&gt;
      &lt;script src="/socket.io/socket.io.js"&gt;&lt;/script&gt;
  &lt;/head&gt;
  
  &lt;body&gt;
      &lt;textarea id="editor" style="height:200px;width:300px"&gt;
          Thinknest Pragraph locking Test sample !
      &lt;/textarea&gt;
  
      &lt;script&gt;
      function msgReceived(msg){
          //clientCounter.html(msg.clients);
          document.getElementById('people').innerHTML=msg.uid;
          //console.log(msg.id);  
      }
  
      var clientCounter;  
  
      $(document).ready(function () {
          clientCounter = $("#client_count");
          var socket = io.connect(
                           'http://localhost:5000', 
                           {'sync disconnect on unload':true}
                       ); 
          var uId=prompt("enter your userId",'');
          socket.emit('collabrator',uId);
  
          socket.on('message', function(msg){
              msgReceived(msg);
          });
  
          socket.on('online_collabs',function(data){  
              $('#online_ppl').html(data);
              clientCounter.html(data.length);
          });
  
          socket.on('remained_collabs',function(data){
              $('#online_ppl').html(data);
              clientCounter.html(data.length);
          });
  
          socket.on('note_collabs',function(data){
              $('#note_colabs').html(data);
          });
  
          socket.on('updated_para',function(data){
              //$('#editor').append(data);
              document.getElementById('editor').innerHTML=data;
          });
  
          $('#editor').on('keydown',function(){
              //var para=$('#editor').value;
              var para= $('#editor').val();
              //var para=document.querySelector('[contenteditable]');
              // var text=para.textContent;
              socket.emit('para',{paragraph:para});
          });
      });  
      &lt;/script&gt;
  
      &lt;p&gt;&lt;span id="client_count"&gt;0&lt;/span&gt; connected clients&lt;/p&gt;&lt;br/&gt;
      &lt;ul id="people"&gt;&lt;/ul&gt;
      &lt;h3&gt;Online Collaborators&lt;/h3&gt;
      &lt;span id="online_ppl"&gt;&lt;/span&gt; &lt;br&gt;
      &lt;h3&gt;Note Collaborators&lt;/h3&gt;
      &lt;span id="note_colabs"&gt;&lt;/span&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p><strong>server.js</strong></p>
  
  <pre><code>var app = require('express')()
    , server = require('http').createServer(app)
    , io = require('socket.io').listen(server);
  
  server.listen(5000);
  
  app.get('/',function(req,res){
      res.sendfile("./index.html");
  });
  
  var activeClients = 0;
  var Collaborators=['Colab1','Colab2','Colab3'];
  var people=[];
  
  io.sockets.on('connection', function(socket){
      clientConnect(socket);
  
      socket.on('disconnect', function(){
          clientDisconnect(socket);
      });
  
      socket.on('para',function(data){
          //io.sockets.emit('updated_para',data.paragraph);
          socket.broadcast.emit('updated_para',data.paragraph);
      });
  });
  
  function clientConnect(socket){
      //activeClients +=1;
      var userSocketId=socket.id;
      check_Collaborator(socket);
  
      io.sockets.emit('message', {uid:userSocketId});
  }
  
  var online_collabs=[];
  
  function check_Collaborator(socket){
      socket.on('collabrator',function(data){
          if(Collaborators.indexOf(data)!=-1){
              socket.data=data;
  
              if(online_collabs.indexOf(data)==-1) {
                  online_collabs.push(data);
              }
  
              io.sockets.emit('online_collabs',online_collabs);
              io.sockets.emit('note_collabs',Collaborators);
          } else {
              console.log("collabrator not found");
          }
      });
  }
  
  function clientDisconnect(socket){
      var index=online_collabs.indexOf(socket.data)
  
      if(index&gt;-1)
          online_collabs.splice(index,1);
  
      //activeClients -=1;
      //io.sockets.emit('message', {clients:activeClients});
      io.sockets.emit('remained_collabs',online_collabs);
  }
  </code></pre>