Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ja-k-e/7c29c67485c6b936a490 to your computer and use it in GitHub Desktop.

Select an option

Save ja-k-e/7c29c67485c6b936a490 to your computer and use it in GitHub Desktop.
Twitter Widget Stream using `ng-tweets` (no auth req’d)
<div ng-app='app'>
<div ng-controller='twitterController'>
<header>
<h1>Twitter Widget Stream</h1>
<p>Twitter’s API is notoriously locked down—and for good reasons. The one public-facing access point is via Twitter’s widgets. This pen is made possible by <a href="https://github.com/forwardadvance)" target=blank>Nicholas Johnson</a>’s <a href="https://github.com/forwardadvance/ng-tweets" target=blank>ng-tweets Angular module</a>. It grabs the widget data and reverse engineers JSON from the widget data. The result is an array of stream data without needing server-side authentication.</p>
<p>This stream is searching for “jakealbaugh”. Click “New Tweets” to make the notification go away. It will come back when feed contains new tweets.</p>
</header>
<span class=loading
ng-cloak
ng-hide='feed'>Loading tweets...</span>
<span class=alert
ng-click=seeNewData()
ng-cloak
ng-if="new_data">New Tweets!</span>
<ul ng-class='{enter: enter}' ng-cloak>
<li ng-repeat='tweet in feed.tweets'
ng-class="{rt: tweet.retweet}">
<span>
<a ng-href='{{tweet.author.url}}' target=blank>
<img ng-src='{{tweet.author.avatar}}' />
</a>
</span>
<span>
{{tweet.text}}<br>
{{tweet.updated}}
<span ng-if="tweet.retweet">RETWEET</span>
<a ng-href='{{tweet.permalink}}' target=blank>View Tweet&rarr;</a>
</span>
</li>
</ul>
<!--<pre>{{feed | json}}</pre>-->
</div>
</div>
var update_tick = 30, // in seconds
widget_id = '611635380677423107'; // id of twitter widget
//
// ng tweets: https://github.com/forwardadvance/ng-tweets
// essentially strips twitter widget and returns json
//
angular.module('app', ['ngTweets']).controller('twitterController', function($scope, tweets, $timeout) {
$scope.prev_data = null;
$scope.new_data = false;
// the function we are going to be looping
function updateData() {
tweets.get({
widgetId: widget_id
}).success( function(data) {
// enable enter animation class
$scope.enter = true;
// detecting if data is updated
if ($scope.prev_data != data.tweets[0].id) {
$scope.new_data = true;
$scope.prev_data = data.tweets[0].id;
}
console.log("First: "+data.tweets[0].id, "Prev: "+$scope.prev_data);
// mark new data alert as read
$scope.seeNewData = function() {
$scope.new_data = false;
}
// set feed to data
$scope.feed = data;
// toggle enter animation class
$timeout(function() {
$scope.enter = false;
}, Math.min(3000, update_tick * 1000));
// call wrapping function again in tick seconds
$timeout(function() {
updateData();
}, update_tick * 1000);
});
}
// start it off
updateData();
});
jakealbaughSignature();
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.10/angular.min.js"></script>
<script src="https://rawgit.com/forwardadvance/ng-tweets/master/build/js/ng-tweets.js"></script>
@import url(http://fonts.googleapis.com/css?family=Oxygen:700,300);
body {
background: linear-gradient(135deg, #01777D 0%, darken(#01777D,15%) 100%);
min-height: 100vh;
font-family: Oxygen, sans-serif;
line-height: 1.7;
font-size: 12px;
color: #FFF;
font-weight: 300;
}
h1 {
font-size: 3em;
font-weight: 300;
}
header {
text-align: center;
width: 90%;
max-width: 768px;
margin: 0 auto;
h1 { margin-bottom: 0; }
a { font-weight: 700; color: white; text-decoration: none; }
}
ul {
list-style: none;
display: flex;
width: 95%;
flex-direction: column;
margin: 4em auto 6em; padding: 0;
flex-wrap: wrap;
li {
flex: none;
display: flex;
box-sizing: border-box;
transition: opacity 200ms ease-in, transform 200ms ease-in;
@for $i from 1 through 40 { // may be getting more than i thought
&:nth-child(#{$i}) {
animation-delay: $i * 40ms;
}
}
// retweet style. dont like it right now
//&.rt, &.rt a { color: rgba(255,255,255,0.5); }
//&.rt img { opacity: 0.5; }
}
a {
color: rgba(0,0,0,0.7);
text-decoration: none;
font-weight: 700;
}
li > span {
padding: 1em 0.5em;
align-self: center;
&:nth-child(1) { flex: 1; }
&:nth-child(2) { flex: 6; }
&:nth-child(1) { text-align: center; }
img {
width: 40px;
height: auto;
vertical-align: top;
border-radius: 50%;
filter: grayscale(100%);
box-shadow:
0px 0px 0px 2px rgba(255,255,255,0),
0px 0px 0px 2px rgba(255,255,255,0.9);
transition: filter 200ms ease-in, box-shadow 300ms ease-out;
&:hover {
filter: grayscale(0%);
box-shadow:
0px 0px 0px 2px rgba(255,255,255,0.9),
0px 0px 0px 30px rgba(255,255,255,0);
}
}
}
}
.enter li {
transform: translateY(100%);
opacity: 0;
animation: tweet-in 400ms cubic-bezier(0.59, 2, 0.74, 0.8) forwards;
}
.loading, .alert {
position: fixed;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
z-index: 1;
animation: pulsate 1000ms infinite;
}
.alert {
padding: 2em;
background: rgba(0,0,0,0.8);
border-radius: 50%;
$di: 140px;
line-height: $di;
height: $di; width: $di;
text-align: center;
font-size: 1.4em;
cursor: pointer;
position: fixed;
}
@media (min-width: 768px ) {
ul { flex-direction: row; }
ul > li { width: 50%; }
}
@media (min-width: 1400px ) {
ul > li { width: 25%; }
}
@keyframes pulsate {
0%, 100% { transform: translate(-50%, -50%) scale(1); }
50% { transform: translate(-50%, -50%) scale(0.9); }
}
@keyframes tweet-in {
to { transform: translateY(0); opacity: 1; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment