Building a Twitter widget, part 5: publishing data to your account through authentication
We’ve been through a lot of things since we started this series of articles, but the part we are entering now is what will make a difference in your widget. Many widget are able to display public data, and others can display private data just fine, but being able to also publish data directly from one’s Netvibes page (and on different account for each instance of the widget, even) is what will drive users to your widget.

Of course, being able to publish data (or, in HTTP lingo, to POST data) requires the adequate API method. Twitter provides it, and it’s simply named update. This way, we can display our friend’s statuses using one method (friends_timeline, as seen in the previous part), and publish our statuses using another one. For publishing, we will use the JSON data format, so the URL to retrieve a JSON feed from that API method will be http://twitter.com/statuses/update.json.
To follow along, grab the code from the previous version.
Expanding the HTML code
This new feature of our widget will require us to have two different parts in our HTML display: one that will feature a form, which will send our text to Twitter, and another part where we will display the data feed we are getting from our account. We will create static HTML tags that we will access and update using their CSS classes and the widget.getElementsByClassName method. We will also have to rework a bit of our JavaScript code to make these new HTML elements fit in.
Previously, our HTML code only featured a single p element. Now it will look like this:
</head>
<body>
<form method="post"
action="http://twitter.com/statuses/update.json">
<textarea rows="2" name="status"></textarea>
<input type="submit" class="submit" value="Update" />
</form>
<div class="messages"><p>Twitter is loading ...</p></div>
<div class="paging"></div>
</body>
</html>
Note that the form is directly pointing its action attribute to the API method’s URL.
Because those elements are hand-created, they don’t have access to UWA’s DOM method, like addContent or hide. Only dynamically-created elements, using widget.createElement() for instance, are UWA-extended. Luckily, UWA provides a method to extend our elements, and apply DOM methods to them: UWA.$element.
Because we will need to access those elements using DOM method throughout our code, we will gather their references in an object: widget.elements[]. Extension has to be done at loading time, so this is how our new Twitter.onLoad method looks like:
Twitter.onLoad = function() {
widget.setValue('offset', 0);
widget.setTitle('Twitter');
widget.elements['form'] = UWA.$element(
widget.body.getElementsByTagName('form')[0] );
widget.elements['messages'] = UWA.$element(
widget.body.getElementsByClassName('messages')[0] );
widget.elements['paging'] = UWA.$element(
widget.body.getElementsByClassName('paging')[0] );
widget.elements['textarea'] = UWA.$element(
widget.elements['form'].getElementsByTagName('textarea')[0]);
widget.elements['textarea'].value = ";
if ( widget.getValue('username') ) {
widget.elements['form'].show();
widget.elements['form'].onsubmit = Twitter.submit;
Twitter.loadTimeline();
} else {
widget.elements['form'].hide();
widget.elements['messages']
.setHTML('Please authenticate.');
widget.callback("onEdit");
}
widget.callback('onUpdateBody');
}
Incidentally, we have updated our if..else block to reflect these changes. Note that we are already “hijacking” the form onsubmit event in order to handle it ourselves. The rest should be pretty self explanatory.
Likewise, Twitter.loadTimeline() will get a little update to use our new HTML elements:
Twitter.loadTimeline = function() {
widget.elements['form'].show();
UWA.Data.request(
'http://twitter.com/statuses/friends_timeline.json',
{ method: 'get', type: 'json', cache: 600,
onComplete: Twitter.display,
authentication: Twitter.getAuthentication() }
);
widget.elements['messages'].setHTML(
'<div class="loading">Fetching messages from Twitter<br />
(be patient, Twitter can be slow !)</div>');
widget.callback('onUpdateBody');
}
The Twitter.display method also gets the widget.elements[] treatment in a few places:
- widget.setBody(''); is replaced with widget.elements['messages'].empty();
- widget.body.appendChild(p); becomes widget.elements['messages'].appendChild(p);
- widget.body.addContent('<div class="paging"></div>'); is removed, since the div is now static in the HTML code
- var pagerContainer = UWA.$element( widget.body.getElementsByClassName('paging')[0] ); is also removed, since pagerContainer can be replaced by widget.elements['paging']
- pagerContainer.setContent( pager.getContent() ); thus becomes widget.elements['paging'].setContent( pager.getContent() );
That’s it for our rewriting of our HTML around our new HTML code, and the related JavaScript code.
Submitting data: the methods around the form
Thanks to our if..else block in the onLoad method, our form is only displayed when the user is logged-in. Once he is, we have to handle it, and its Submit button, in the most elegant way possible - that is, not by opening a new browser page where the answer data will be displayed, but by passing the data to our Ajax method. That method is called Twitter.submit, as defined in our if..else block, using this line of code: widget.elements['form'].onsubmit = Twitter.submit;. Here’s how we’ll write it:
Twitter.submit = function() {
var status = widget.elements['textarea'].value;
UWA.Data.request(
this.action,
{
method: this.method, proxy: 'ajax',
onComplete: Twitter.onSubmitOk,
parameters: 'status=' + status,
authentication: Twitter.getAuthentication()
}
);
widget.elements['textarea'].setAttribute('disabled', 'disabled');
return false;
}
Notice how the URL of our Ajax request is directly taken from the form action attribute, using this.action. Also, we disable the form’s text area, to prevent more text from being entered while the request is being sent. Finally, return false; prevents the form itself from being submitted: the whole submission is done through Ajax.
Twitter’s update method requires a parameter, status, which contains the status’ text. We provide it using the parameters setting of the Ajax request.
We already have the Twitter.getAuthentication method in place (it’s the same as in the previous parts of the widget), but we need the define Twitter.onSubmitOk(), which will decide what is to be done if the request is successful. Here, we will simply erase the message we submitted, and re-enable the textarea for further Twitting.
Twitter.onSubmitOk = function() {
widget.elements['textarea'].value = '';
widget.elements['textarea'].removeAttribute('disabled');
Twitter.loadTimeline();
}
And this is it for data submission through authentication!
Styling the form

As it is, the form isn’t really pretty: the textarea and the input button are next to each other, which prevents the textarea from being larger. A bit of CSS will make it more appealing:
<style type="text/css">
(..)
textarea {
width:98%;
display:block;
padding:2px 1%;
margin:auto;
font-size:1em;
}
input.submit {
margin:auto;
display:block;
font-weight:bold;
}
</style>
Our Twitter widget is now fully functional for handling private data, in and out of the API.
Check out the code for that new version of our Twitter widget!
Tags: ajax, authentication, dom, http post, javascript, request, twitter, uwa