--- /dev/null
+/**
+ * Javascript based Twitter client for Horde.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Horde
+ */
+var Horde_Twitter = Class.create({
+ inReplyTo: '',
+ page: 1,
+
+ /**
+ * Const'r
+ *
+ * opts.input The domid of the input form element.
+ * opts.spinner The domid of the spinner element.
+ * opts.content The main content area, where the tweets are placed.
+ * opts.endpoint The url endpoint for horde/servcies/twitter.php
+ * opts.inreplyto
+ * opts.strings.inreplyto
+ * opts.strings.defaultText
+ * opts.strings.justnow
+ */
+ initialize: function(opts) {
+ this.opts = opts;
+ $(this.opts.input).observe('focus', function() {this.clearInput()}.bind(this));
+ $(this.opts.input).observe('blur', function() {
+ if (!$(this.opts.input).value.length) {
+ $(this.opts.input).value = this.opts.strings.defaultText;
+ }
+ }.bind(this));
+
+ /* Get the first page */
+ this.updateStream(1);
+
+ },
+
+ /**
+ * Post a new tweet.
+ *
+ */
+ updateStatus: function(statusText) {
+ $(this.opts.input).stopObserving('blur');
+ $(this.opts.spinner).toggle();
+ params = {
+ actionID: 'updateStatus',
+ statusText: statusText,
+ params: { 'in_reply_to_status_id': this.inReplyTo }
+ };
+
+ new Ajax.Request(this.opts.endpoint, {
+ method: 'post',
+ parameters: params,
+ onComplete: function(response) {
+ this.updateCallback(response.responseJSON);
+ }.bind(this),
+ onFailure: function() {
+ $(this.opts.spinner).toggle();
+ this.inReplyTo = '';
+ }
+ });
+ },
+
+ /**
+ * Retweet the specifed tweet id.
+ *
+ */
+ retweet: function(id) {
+ $(this.opts.spinner).toggle();
+ params = {
+ actionID: 'retweet',
+ tweetId: id
+ };
+ new Ajax.Request(this.opts.endpoint, {
+ method: 'post',
+ parameters: params,
+ onComplete: function(response) {
+ this.updateCallback(response.responseJSON);
+ }.bind(this),
+ onFailure: function() {
+ $(this.opts.spinner).toggle();
+ this.inReplyTo = '';
+ }
+ });
+ },
+
+ /**
+ * Update the timeline stream.
+ *
+ * @param integer page The page number to retrieve.
+ */
+ updateStream: function(page) {
+ new Ajax.Request(this.opts.endpoint, {
+ method: 'post',
+ parameters: { actionID: 'getPage', 'page': page },
+ onComplete: function(response) {
+ var h = $(this.opts.content).scrollHeight
+ $(this.opts.content).insert(response.responseText);
+ // Don't scroll if it's the first request.
+ if (page != 1) {
+ $(this.opts.content).scrollTop = h;
+ } else {
+ $(this.opts.content).scrollTop = 0;
+ }
+ }.bind(this),
+ onFailure: function() {
+ $(this.opts.spinner).toggle();
+ }
+ });
+ },
+
+ /**
+ * Build the reply structure
+ */
+ buildReply: function(id, userid, usertext) {
+ this.inReplyTo = id;
+ $(this.opts.input).focus();
+ $(this.opts.input).value = '@' + userid + ' ';
+ $(this.opts.inreplyto).update(this.opts.strings.inreplyto + usertext);
+ },
+
+ /**
+ * Callback for after a new tweet is posted.
+ */
+ updateCallback: function(response) {
+ this.buildNewTweet(response);
+ $(this.opts.input).value = this.opts.strings.defaultText;
+ $(this.opts.spinner).toggle();
+ this.inReplyTo = '';
+ $(this.opts.inreplyto).update('');
+ },
+
+ /**
+ * Build adnd display the node for a new tweet.
+ */
+ buildNewTweet: function(response) {
+ var tweet = new Element('div', {'class':'fbstreamstory'});
+ var tPic = new Element('div', {'style':'float:left'}).update(
+ new Element('a', {'href': 'http://twitter.com/' + response.user.screen_name}).update(
+ new Element('img', {'src':response.user.profile_image_url})
+ )
+ );
+ var tBody = new Element('div', {'class':'fbstreambody'}).update(response.text);
+ tBody.appendChild(new Element('div', {'class':'fbstreaminfo'}).update(this.opts.strings.justnow));
+ tweet.appendChild(tPic);
+ tweet.appendChild(tBody);
+ $(this.opts.content).insert({top:tweet});
+ },
+
+ /**
+ * Clear the input field.
+ */
+ clearInput: function() {
+ $(this.opts.input).value = '';
+ }
+});
\ No newline at end of file
{
global $conf;
+ /* Get the twitter driver */
try {
$twitter = $this->_getTwitterObject();
} catch (Horde_Exception $e) {
}
}
+ /* Build values to pass to the javascript twitter client */
+ $defaultText = _("What are you working on now?");
+ $endpoint = Horde::url('services/twitter.php', true);
+ $spinner = $instance . '_loading';
+ $inputNode = $instance . '_newStatus';
+ $inReplyToNode = $instance . '_inReplyTo';
+ $inReplyToText = _("In reply to:");
+ $contentNode = 'twitter_body' . $instance;
+ $justNowText = _("Just now...");
+
+ /* Add the client javascript / initialize it */
+ Horde::addScriptFile('twitterclient.js');
+ $script = <<<EOT
+ var Horde = window.Horde || {};
+ Horde.twitter = new Horde_Twitter({
+ input: '{$instance}_newStatus',
+ spinner: '{$instance}_loading',
+ content: 'twitter_body{$instance}',
+ endpoint: '{$endpoint}',
+ inreplyto: '{$inReplyToNode}',
+ strings: { inreplyto: '{$inReplyToText}', defaultText: '{$defaultText}', justnow: '{$justNowText}' }
+ });
+EOT;
+ Horde::addInlineScript($script, 'dom');
+
+ /* Get the user's most recent tweet */
$latestStatus = htmlspecialchars($this->_profile->status->text, ENT_COMPAT, Horde_Nls::getCharset());
// Bring in the Facebook CSS
$csslink = $GLOBALS['registry']->get('themesuri', 'horde') . '/facebook.css';
- $defaultText = _("What are you working on now?");
+
+ /* Build the UI */
$html = '<link href="' . $csslink . '" rel="stylesheet" type="text/css" />';
$html .= '<div style="float:left;padding-left: 8px;padding-right:8px;">'
. '<input style="width:98%;margin-top:4px;margin-bottom:4px;" type="text" id="' . $instance . '_newStatus" name="' . $instance . '_newStatus" value="' . $defaultText . '" />'
$html .= '<div id="currentStatus" class="fbemptystatus" style="margin-left:10px;margin-top:10px;">' . sprintf(_("Latest: %s - %s"), $latestStatus, Horde_Date_Utils::relativeDateTime(strtotime($this->_profile->status->created_at), $GLOBALS['prefs']->getValue('date_format'), ($GLOBALS['prefs']->getValue('twentyFour') ? "%H:%M %P" : "%I %M %P"))) . '</div>';
$html .= '<div style="height:' . $this->_params['height'] . 'px;overflow-y:auto;" id="twitter_body' . $instance . '">';
$filter = Horde_Text_Filter::factory('Text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
-
$html .= '</div>';
$html .= '<div class="control fbgetmore"><a href="#" onclick="Horde.twitter.updateStream(++Horde.twitter.page);">' . _("Get More") . '</a></div>';
- $endpoint = Horde::url('services/twitter.php', true);
- $spinner = '$(\'' . $instance . '_loading\')';
- $inputNode = '$(\'' . $instance . '_newStatus\')';
- $inReplyToNode = '$(\'' . $instance . '_inReplyTo\')';
- $inReplyToText = _("In reply to:");
- $contentNode = 'twitter_body' . $instance;
- $justNowText = _("Just now...");
-
- $html .= <<<EOF
- <script type="text/javascript">
- var Horde = window.Horde || {};
- Horde.twitter = {
- inReplyTo: '',
- page: 1,
- updateStatus: function(statusText) {
- {$inputNode}.stopObserving('blur');
- {$spinner}.toggle();
- params = new Object();
- params.actionID = 'updateStatus';
- params.statusText = statusText;
- params.params = { 'in_reply_to_status_id': this.inReplyTo };
- new Ajax.Request('$endpoint', {
- method: 'post',
- parameters: params,
- onComplete: function(response) {
- this.updateCallback(response.responseJSON);
- }.bind(this),
- onFailure: function() {
- {$spinner}.toggle();
- this.inReplyTo = '';
- }
- });
- },
-
- retweet: function(id) {
- {$spinner}.toggle();
- params = {
- actionID: 'retweet',
- tweetId: id
- };
- new Ajax.Request('$endpoint', {
- method: 'post',
- parameters: params,
- onComplete: function(response) {
- this.updateCallback(response.responseJSON);
- }.bind(this),
- onFailure: function() {
- {$spinner}.toggle();
- this.inReplyTo = '';
- }
- });
- },
-
- updateStream: function(page) {
- new Ajax.Request('$endpoint', {
- method: 'post',
- parameters: { actionID: 'getPage', 'page': page },
- onComplete: function(response) {
- var content = new Element('div').update(response.responseText);
- var h = $('{$contentNode}').scrollHeight
- $('{$contentNode}').insert(content);
- // Don't scroll if it's the first request.
- if (page != 1) {
- $('{$contentNode}').scrollTop = h;
- } else {
- $('{$contentNode}').scrollTop = 0;
- }
- },
- onFailure: function() {
- {$spinner}.toggle();
- }
- });
- },
-
- buildReply: function(id, userid, usertext) {
- this.inReplyTo = id;
- {$inputNode}.focus();
- {$inputNode}.value = '@' + userid + ' ';
- {$inReplyToNode}.update(' {$inReplyToText} ' + usertext);
- },
-
- updateCallback: function(response) {
- this.buildNewTweet(response);
- {$inputNode}.value = '{$defaultText}';
- {$spinner}.toggle();
- this.inReplyTo = '';
- {$inReplyToNode}.update('');
- },
-
- buildNewTweet: function(response) {
- var tweet = new Element('div', {'class':'fbstreamstory'});
- var tPic = new Element('div', {'style':'float:left'}).update(
- new Element('a', {'href': 'http://twitter.com/' + response.user.screen_name}).update(
- new Element('img', {'src':response.user.profile_image_url})
- )
- );
- var tBody = new Element('div', {'class':'fbstreambody'}).update(response.text);
- tBody.appendChild(new Element('div', {'class':'fbstreaminfo'}).update('{$justNowText}'));
- tweet.appendChild(tPic);
- tweet.appendChild(tBody);
-
- $('{$contentNode}').insert({top:tweet});
- },
-
- buildTweet: function(response) {
- var tweet = new Element('div', {'class':'fbstreamstory'});
- var tPic = new Element('div', {'style':'float:left'}).update(
- new Element('a', {'href': 'http://twitter.com/' + response.user.screen_name}).update(
- new Element('img', {'src':response.user.profile_image_url})
- )
- );
- var tBody = new Element('div', {'class':'fbstreambody'}).update(response.text);
- tBody.appendChild(new Element('div', {'class':'fbstreaminfo'}).update('{$justNowText}'));
- tweet.appendChild(tPic);
- tweet.appendChild(tBody);
-
- $('{$contentNode}').insert(tweet);
- },
-
- clearInput: function() {
- {$inputNode}.value = '';
- }
- };
-
- document.observe('dom:loaded', function() {
- {$inputNode}.observe('focus', function() {Horde.twitter.clearInput()});
- {$inputNode}.observe('blur', function() {
- if (!{$inputNode}.value.length) {
- {$inputNode}.value = '{$defaultText}';
- }
- });
-
- /* Get the first page */
- Horde.twitter.updateStream(1);
- });
- </script>
-EOF;
$html .= '</div>';
+
return $html;
}