Break out the javascript for the twitter client.
authorMichael J. Rubinsky <mrubinsk@horde.org>
Thu, 1 Jul 2010 21:14:57 +0000 (17:14 -0400)
committerMichael J. Rubinsky <mrubinsk@horde.org>
Thu, 1 Jul 2010 21:14:57 +0000 (17:14 -0400)
horde/js/twitterclient.js [new file with mode: 0644]
horde/lib/Block/twitter_timeline.php

diff --git a/horde/js/twitterclient.js b/horde/js/twitterclient.js
new file mode 100644 (file)
index 0000000..9096ad5
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+ * 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
index 1ac2485..4b22c6d 100644 (file)
@@ -104,6 +104,7 @@ class Horde_Block_Horde_twitter_timeline extends Horde_Block
     {
         global $conf;
 
+        /* Get the twitter driver */
         try {
             $twitter = $this->_getTwitterObject();
         }  catch (Horde_Exception $e) {
@@ -127,11 +128,38 @@ class Horde_Block_Horde_twitter_timeline extends Horde_Block
             }
         }
 
+        /* 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 . '" />'
@@ -140,147 +168,10 @@ class Horde_Block_Horde_twitter_timeline extends Horde_Block
         $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;
     }