diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100755 index 0000000..bfea61e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2012 Todd Matthews & Steve Purcell + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 6099ba1..f54e99b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ -tweetwidget -=========== +Sea of Clouds - Twitter Widget +======================= + +A twitter widget, based on the 'Sea of Clouds' script. The most often used +options can be configured in the `config.yml` file. If you wish to change either +the default CSS or the default javascript, you should copy the files from +`SeaOfCloudsWidget/assets` to another file in that same folder. That way, they +will not be overwritten when you update the extension. + +
+ ++ + + -Tweetwidget is a twitter widget, based on the 'Sea of Clouds' Tweet! script. \ No newline at end of file diff --git a/assets/index.css b/assets/index.css new file mode 100755 index 0000000..108b2f7 --- /dev/null +++ b/assets/index.css @@ -0,0 +1,69 @@ +body { + background-color: #008D99; + color: white; + font: 15px/1.3 arial, sans-serif; + margin: 0 auto; + width: 480px; + padding: 30px; + text-align: left; } + +h1 { + font-size: 240%; + margin-bottom: -.5em; } +h2, p, ul, code { + margin-bottom: 1em; } +h2 a { + color: #fff; } +h3 { + font-size: 140%; + margin-bottom: .4em; } +ul { + padding-left: 2em; } + ul li { + list-style-type: square; + margin-left: 0;} +a { + color: #8ADEE2; } +.demo a.num { + color: white; +} +code, .example { + padding: .5em; + display: block; + overflow-x: auto;} +code { + margin-left: 1em;} +code, .code, .example { + background-color: #0C717A; + color: #fff; + font-size: 85%; + font-family: courier, monospace; } + code a, .code a { + color: #fff; } +.show-code { + display: block; + font-size: 75%; + margin: 1em 0;} +.copyright { + font-family: verdana, sans-serif; + font-size: 75%; + margin-top: 8em; } + .copyright span { + color: #8ADEE2; } +.download h4 { + font-size: 120%; + margin-top: -.5em; + color: #8ADEE2; } +.twoot { + padding-top: 3em; } +.query { + margin-bottom: 2em; } +.notice { + background-color: #8adee2; + color: #444; + border: solid 2px #fff; + padding: 0 1em; +} +.notice a { + color: #444; +} \ No newline at end of file diff --git a/assets/index.html b/assets/index.html new file mode 100755 index 0000000..c131b30 --- /dev/null +++ b/assets/index.html @@ -0,0 +1,406 @@ + + + + +
Check out the script in action at seaofclouds.com, and see the following demos.
+ ++ Twitter's decision + to discontinue + their unauthenticated v1.0 API means that this widget will + stop working + at some + time in 2013 -- Twitter wants your only option for on-page + widgets to be their own Embedded Timelines. +
++ Please read the + corresponding support issue + for more information and possible current/future + workarounds. +
+#1 - Displaying three tweets from the seaofclouds twitter feed:
++ jQuery(function($){ + $(".tweet").tweet({ + join_text: "auto", + username: "seaofclouds", + avatar_size: 48, + count: 3, + auto_join_text_default: " we said, ", + auto_join_text_ed: " we ", + auto_join_text_ing: " we were ", + auto_join_text_reply: " we replied ", + auto_join_text_url: " we were checking out ", + loading_text: "loading tweets..." + }); + }); ++ +
#2 - Displaying up to four tweets with the query "tweet.seaofclouds.com":
+
+ (You can use any query supported by Twitter search)
+
+ jQuery(function($){ + $("#query").tweet({ + avatar_size: 32, + count: 4, + query: "tweet.seaofclouds.com", + loading_text: "searching twitter..." + }); + }); ++ +
#3 - Displaying up to three links with the search query "from:seaofclouds http":
++ jQuery(function($){ + $("#userandquery").tweet({ + count: 3, + query: "from:seaofclouds http", + loading_text: "searching twitter..." + }); + }); ++ +
#4 - Displaying four tweets from the two users "seaofclouds" and "laughingsquid", refreshing every 60 seconds:
+(Note that it's more reliable to display multiple users' tweets by using a list - see below)
++ jQuery(function($){ + $("#fromtwo").tweet({ + avatar_size: 32, + count: 4, + username: ["seaofclouds", "laughingsquid"], + loading_text: "searching twitter...", + refresh_interval: 60 + }); + }); ++ +
#5 - Displaying tweets from users on the 'team' list of 'twitter':
++ jQuery(function($){ + $("#list").tweet({ + avatar_size: 32, + count: 4, + username: "twitter", + list: "team", + loading_text: "loading list..." + }); + }); ++ +
#6 - Displaying the user sanityinc's favorite tweets, and using a handler + for tweet's "loaded" event to make links open in a new window:
++ jQuery(function($){ + $("#favorites").tweet({ + avatar_size: 32, + count: 3, + username: "sanityinc", + favorites: true, + loading_text: "loading list..." + }).bind("loaded",function(){$(this).find("a").attr("target","_blank");}); + }); ++ +
#7 - Fetch 20 tweets, but filter out @replies, and display only 3:
++ jQuery(function($){ + $("#filter").tweet({ + avatar_size: 32, + count: 3, + fetch: 20, + filter: function(t){ return ! /^@\w+/.test(t.tweet_raw_text); }, + username: "sanityinc" + }); + }); ++ +
#8 - Customize the layout to eliminate the date stamps and avatars, add an action (aka "web intent") link, + and make it open in a popup window:
++ jQuery(function($){ + $("#custom").tweet({ + avatar_size: 32, + count: 4, + username: "seaofclouds", + template: "{text} » {retweet_action}" + }); + }).bind("loaded", function(){ + $(this).find("a.tweet_action").click(function(ev) { + window.open(this.href, "Retweet", + 'menubar=0,resizable=0,width=550,height=420,top=200,left=400'); + ev.preventDefault(); + }); + }); ++ +
#9 - Adding a message when no tweets matching 'somerandomstring' are found:
++ jQuery(function($){ + $("#empty").tweet({ + avatar_size: 32, + count: 4, + query: rnd, + loading_text: "searching twitter..." + }).bind("empty", function() { $(this).append("No matching tweets found"); }); + }); ++ +
#10 - use button to page forwards and backwards (note the HTML structure required -- please view the source):
++ jQuery(function($){ + var options = { + username: "seaofclouds", + page: 1, + avatar_size: 32, + count: 4, + fetch: 5, // 1 + count + loading_text: "loading ..." + }; + + var widget = $("#paging .widget"), + next = $("#paging .next"), + prev = $("#paging .prev"); + + var enable = function(el, yes) { + yes ? $(el).removeAttr('disabled') : + $(el).attr('disabled', true); + }; + + var stepClick = function(incr) { + return function() { + options.page = options.page + incr; + enable(this, false); + widget.tweet(options); + }; + }; + + next.bind("checkstate", function() { + enable(this, widget.find("li").length == options.count) + }).click(stepClick(1)); + + prev.bind("checkstate", function() { + enable(this, options.page > 1) + }).click(stepClick(-1)); + + widget.tweet(options).bind("loaded", function() { next.add(prev).trigger("checkstate"); }); + }); ++
#11 - display one tweet at a time like a ticker:
++ jQuery(function($){ + $("#ticker").tweet({ + username: "seaofclouds", + page: 1, + avatar_size: 32, + count: 20, + loading_text: "loading ..." + }).bind("loaded", function() { + var ul = $(this).find(".tweet_list"); + var ticker = function() { + setTimeout(function() { + var top = ul.position().top; + var h = ul.height(); + var incr = (h / ul.children().length); + var newTop = top - incr; + if (h + newTop <= 0) newTop = 0; + ul.animate( {top: newTop}, 500 ); + ticker(); + }, 5000); + }; + ticker(); + }); + }); ++ + +
NOTE: Some users have reported that they do not show up in Twitter's search results.
+ + + +1. Get JQuery. In these examples, we use Google's AJAX Libraries API. +
2. include jQuery and jquery.tweet.js files in your template's <head>.
+
+ <script language="javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js" type="text/javascript"></script>
+ <script language="javascript" src="/tweet/jquery.tweet.js" type="text/javascript"></script>
+
+ 3. Also in <head>, Initialize tweet! on page load with your Username and other options
+
+ <script type='text/javascript'>
+ jQuery(function($){
+ $(".tweet").tweet({
+ username: "seaofclouds",
+ join_text: "auto",
+ avatar_size: 32,
+ count: 3,
+ auto_join_text_default: "we said,",
+ auto_join_text_ed: "we",
+ auto_join_text_ing: "we were",
+ auto_join_text_reply: "we replied to",
+ auto_join_text_url: "we were checking out",
+ loading_text: "loading tweets..."
+ });
+ });
+ </script>
+
+ 4. In <body>, include a placeholder for your tweets. They'll get loaded in via JSON. How fancy!
+
+ <div class="tweet"></div>
+
+ 5. Style with our stylesheet in <head>, or modify as you like!
+
+ <link href="jquery.tweet.css" media="all" rel="stylesheet" type="text/css"/>
+
+
+ Bring your code slinging skills to Github and help us develop new features for tweet!
+
+ git clone git://github.com/seaofclouds/tweet.git
+
+ + Report bugs and request features in Github Issues +
+
+ http://www.opensource.org/licenses/mit-license.php
+
+ something nifty from seaofclouds™ & sanityinc.com | contribute
+ + diff --git a/assets/jquery.tweet.css b/assets/jquery.tweet.css new file mode 100755 index 0000000..618039b --- /dev/null +++ b/assets/jquery.tweet.css @@ -0,0 +1,37 @@ +/* Note: do not change this file. If you wish to modify it, copy it, and set the correct name in this extension's config.yml */ +.tweet, .query { + /* font: 120% Georgia, serif; + color: #085258; */ +} + +.tweet_list { + list-style: none; + margin: 0; + padding: 0; + overflow-y: hidden; + /* background-color: #8ADEE2; */ +} + +.tweet_list li { + overflow-y: auto; + overflow-x: hidden; + padding: 0.5em; + list-style-type: none; + font-size: 90%; +} + +.tweet_list li a { + color: #0C717A; +} + +.tweet_list .tweet_even { + background-color: rgba(0, 0, 0, 0.1); +} + +.tweet_list .tweet_avatar { + padding-right: .5em; float: left; +} + +.tweet_list .tweet_avatar img { + vertical-align: middle; +} diff --git a/assets/jquery.tweet.js b/assets/jquery.tweet.js new file mode 100755 index 0000000..125c21b --- /dev/null +++ b/assets/jquery.tweet.js @@ -0,0 +1,264 @@ +// jquery.tweet.js - See http://tweet.seaofclouds.com/ or https://github.com/seaofclouds/tweet for more info +// Copyright (c) 2008-2012 Todd Matthews & Steve Purcell +(function (factory) { + if (typeof define === 'function' && define.amd) + define(['jquery'], factory); // AMD support for RequireJS etc. + else + factory(jQuery); +}(function ($) { + $.fn.tweet = function(o){ + var s = $.extend({ + username: null, // [string or array] required unless using the 'query' option; one or more twitter screen names (use 'list' option for multiple names, where possible) + list: null, // [string] optional name of list belonging to username + favorites: false, // [boolean] display the user's favorites instead of his tweets + query: null, // [string] optional search query (see also: http://search.twitter.com/operators) + avatar_size: null, // [integer] height and width of avatar if displayed (48px max) + count: 3, // [integer] how many tweets to display? + fetch: null, // [integer] how many tweets to fetch via the API (set this higher than 'count' if using the 'filter' option) + page: 1, // [integer] which page of results to fetch (if count != fetch, you'll get unexpected results) + retweets: true, // [boolean] whether to fetch (official) retweets (not supported in all display modes) + intro_text: null, // [string] do you want text BEFORE your your tweets? + outro_text: null, // [string] do you want text AFTER your tweets? + join_text: null, // [string] optional text in between date and tweet, try setting to "auto" + auto_join_text_default: " I said, ", // [string] auto text for non verb: "I said" bullocks + auto_join_text_ed: " I ", // [string] auto text for past tense: "I" surfed + auto_join_text_ing: " I am ", // [string] auto tense for present tense: "I was" surfing + auto_join_text_reply: " I replied to ", // [string] auto tense for replies: "I replied to" @someone "with" + auto_join_text_url: " I was looking at ", // [string] auto tense for urls: "I was looking at" http:... + loading_text: null, // [string] optional loading text, displayed while tweets load + refresh_interval: null, // [integer] optional number of seconds after which to reload tweets + twitter_url: "twitter.com", // [string] custom twitter url, if any (apigee, etc.) + twitter_api_url: "api.twitter.com", // [string] custom twitter api url, if any (apigee, etc.) + twitter_search_url: "search.twitter.com", // [string] custom twitter search url, if any (apigee, etc.) + template: "{avatar}{time}{join} {text}", // [string or function] template used to construct each tweet'+s.intro_text+'
'); + if (s.outro_text) list.after(''+s.outro_text+'
'); + + $(widget).trigger("loaded").trigger((tweets.length === 0 ? "empty" : "full")); + if (s.refresh_interval) { + window.setTimeout(function() { $(widget).trigger("tweet:load"); }, 1000 * s.refresh_interval); + } + } + + function load(widget) { + var loading = $(''+s.loading_text+'
'); + if (s.loading_text) $(widget).not(":has(.tweet_list)").empty().append(loading); + $.getJSON(build_api_url(), function(data){ + var tweets = $.map(data.results || data, extract_template_data); + tweets = $.grep(tweets, s.filter).sort(s.comparator).slice(0, s.count); + $(widget).trigger("tweet:retrieved", [tweets]); + }); + } + + return this.each(function(i, widget){ + if(s.username && typeof(s.username) === "string"){ + s.username = [s.username]; + } + + $(widget).unbind("tweet:render").unbind("tweet:retrieved").unbind("tweet:load"). + bind({ + "tweet:load": function() { load(widget); }, + "tweet:retrieved": function(ev, tweets) { + $(widget).trigger("tweet:render", [tweets]); + }, + "tweet:render": function(ev, tweets) { + render_tweets($(widget), tweets); + } + }).trigger("tweet:load"); + }); + }; +})); diff --git a/assets/tweetwidget.twig b/assets/tweetwidget.twig new file mode 100755 index 0000000..b6884e9 --- /dev/null +++ b/assets/tweetwidget.twig @@ -0,0 +1,24 @@ +{# Note: do not change this file. If you wish to modify it, copy it, and set the correct name in this extension's config.yml #} + + + + diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..a0571e3 --- /dev/null +++ b/config.yml @@ -0,0 +1,13 @@ +# Configuration file for Sea of Clouds - Twitter Widget + +username: boltcm +avatar_size: 40 +count: 3 +fetch: 20 +loading_text: 'Loading tweets…' + +# Change these, if you want to use your own templates (inside this extension's assets/ folder) +# Do _not_ change the default files themselves, because they will be overwritten with updates +# of this extension. +style_filename: jquery.tweet.css +template: tweetwidget.twig diff --git a/extension.php b/extension.php new file mode 100644 index 0000000..20722cf --- /dev/null +++ b/extension.php @@ -0,0 +1,77 @@ + "Tweet! - Twitter Widget", + 'description' => "Tweetwidget is a twitter widget, based on the 'Sea of Clouds' Tweet! script.", + 'keywords' => "twitter, widget, sidebar", + 'author' => "Bob den Otter", + 'link' => "http://bolt.cm", + 'version' => "0.1", + 'required_bolt_version' => "1.1.0", + 'highest_bolt_version' => "1.1.1", + 'type' => "Widget", + 'first_releasedate' => "2013-03-10", + 'latest_releasedate' => "2013-03-10", + 'dependencies' => "", + 'priority' => 10 + ); + + return $data; + + } + + /** + * Initialize Sea of Clouds - Twitter Widget. Called during bootstrap phase. + */ + function initialize() + { + + // Make sure jQuery is included + $this->addJquery(); + + // Add javascript file + $this->addJavascript("assets/jquery.tweet.js"); + + // Add CSS file + $this->addCSS("assets/" . $this->config['style_filename']); + + // Initialize the Twig function + $this->addTwigFunction('tweetwidget', 'tweetwidget'); + + } + + /** + * Twig function {{ tweetwidget() }} in Sea of Clouds - Twitter Widget extension. + */ + function tweetwidget() + { + + $this->app['twig.loader.filesystem']->addPath(__DIR__); + + $formhtml = $this->app['twig']->render("assets/" . $this->config['template'], array( + "config" => $this->config + )); + + return new \Twig_Markup($formhtml, 'UTF-8'); + + } + + + +} + +