Building WeTweetApp, part 1
Simulfy allows you to add real-time collaboration to your website or app, using our new JavaScript platform released earlier this month. In the early days of Simulfy, about a year ago, we built WeTweetApp allowing you to prepare and write a Tweet together and post it to Twitter. But while rewriting Simulfy over the past year, WeTweetApp wasnât updated and it got broken⌠Since the new Simulfy Client API (the client) is released, we decided to bring WeTweetApp back to life.
In the next couple of weeks, I will post a series of blogposts about how I created WeTweetApp.
In this first blogpost I will describe the base app structure, starting a Simulfy session using the client, creating the files and how to create the collaborative Tweet editor.
First off, the app is written in CoffeeScript, a language that compiles into JavaScript, and built on node.js.
I plan to annotate the source of WeTweetApp in the next couple of weeks, but the CoffeeScript source is already available at http://docs.simulfy.com/sources/wetweetapp/app.html.
Secondly, to post the collaborated text to Twitter, Iâve used Twitterâs Web Intents. Using web intents, itâs easy to hook Twitterâs API into WeTweetApp.
To create the WeTweetApp, Iâve created an HTML page containing the layout of the app and a CSS stylesheet. Then I added the client, Simulfy widgets library and the wetweetapp JavaScript via the script tag in the head. I then initiate the app by requiring the WetWeetApp JavaScript code. The require method is provided by the client.
<script src="http://simulfy.github.io/simulfy-libs/client/current/simulfy.min.js"></script> <script src="http://simulfy.github.io/simulfy-libs/client/current/simulfy-widgets.min.js"></script> <script src="/javascripts/wetweetapp.js"></script> <script> WeTweetApp = require('./app/js/app'); $(function() { window.app = new WeTweetApp(); }); </script>
WeTweetApp is a Coffeescript class containing all the app logic. With the client I can easily initiate a Simulfy session, by calling the startSimulfy method in the class constructor. The onConnect callback does all the specific app magic.
#app.coffee #require provided by nodejs extensionMap = require â./extensionmapâ simWidgets = require âsimulfy-widgetsâ class App #allows you to call ânew App()â constructor: () -> @start() start: () => startSimulfy onConnect: @onConnect extensionMap: extensionMap onConnect: () => #do WeTweetApp stuff
As you can see in the screenshot above, at the left thereâs the Tweet text, at the right is a comment thread. For Simulfy this translates to two files. For the Tweet I created the file index.tweet, for the comments the file index.comments. Both files are public by default, allowing everyone who has access to the web url, can be added to the files. So, in the onConnect method I open these two files.
#app.coffee onConnect: () => #simletId is provided by the client, bound to window and grabbed from the hash in the browser url... @tweetFile = simulfy.openFile(simletId, 'index.tweet') @commentsFile = simulfy.openFile(simletId, 'index.comments')
Because the files are public, I can add the current user to the files without permission. In a next blogpost Iâll describe how I obtained the current user.
#app.coffee, onConnect #@address = '[email protected]' @tweetFile.participants.add(@address)
The tweetFile is just a piece of text, so I can create a tweet scope on the file content in the extensionMap, create it with an empty string and pass it to the Simulfy textarea widget.
#extensionMap.coffee class TweetFile extends SimOp autoCreate: true structure: (key) -> switch key when 'tweet' then Tweet else SimOp default: -> tweet: '' initialize: -> @tweet = @scope 'tweet'
#app.coffee, onConnect tweet = @tweetFile.content.tweet #jquery ($) provided by the client... @tweetArea = $('#tweet-area') simWidgets.textarea.bind @tweetArea, tweet
As Twitter allows 140 characters per Tweet, Iâve added a simple characters left counter. Using the live method on the tweet scope, I can simply calculate the characters left.
#app.coffee, onConnect tweet.live (str) => @tweetCounter = $('#tweet-counter') @tweetCounter.html 140 - str.length
If there are no characters left, I bounce the change by not sending it to the server, using the simOpâs isAllowed method in the extensionmap.
#extensionMap.coffee class Tweet extends SimOp #override simulfy isAllowed api method, use for content validation not permission checking isAllowed: (method, val, cb) -> if val.length <= 140 cb(true) else cb(false)
Finally, I use Twitterâs Web Intents to post the composed Tweet text to Twitter. Off course the Twitter API is in the HTML.
@tweetButton = $('#tweet-button') @tweetButton.on 'click', (event) => text = @tweetArea.val() #change the text string of the Twitter iFrame, the click propagates and triggers the Twitter popup to be opened... @tweetButton.attr('href',"https://twitter.com/intent/tweet?text=#{encodeURIComponent(text)}")
So, thatâs it for this first blogpost. Next up is how I obtain the username, how to invite users and authentication.
Off course, donât forget to check out WeTweetApp now!
Richard














