Ajax Loader
×
HTML
x
25
1
 
2
<script type="text/template" id="visual-template">
3
<div class="size{{visualSize}}" id="tweet{{tweetId}}">
4
  <div class="visual-container">
5
    <div class="visual">
6
      <div class="visual-inlay">
7
        <div class="visual-img" style="background-image:url({{avatarImage}})"></div>
8
        <div class="visual-overlay-container">
9
          <div class="visual-text">{{retweetCount}}</div>
10
          <div class="visual-overlay" style="background-image:url({{avatarImage}})"></div>
11
        </div>
12
      </div>
13
      <div class="visual-text-2">{{tweetTime}}</div>
14
    </div>
15
    <div class="handle">
16
      {{twitterHandle}}
17
    </div>
18
  </div>
19
</div>
20
</script>
21
<div id="twtcontainer"></div>
22
<script class="cssdeck" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
23
<script class="cssdeck" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.2.2/underscore-min.js"></script>
24
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.js"></script>
25
 
 
CSS
x
184
1
 
2
@import url("https://fonts.googleapis.com/css?family=Lato:100,400,700,700italic,900,400italic,300,300italic");
3
@import url("https://fonts.googleapis.com/css?family=Source+Code+Pro:300,300italic,400");
4
body {
5
  background: #f6f6f6;
6
  font-family: Lato, sans-serif; 
7
  overflow: hidden;
8
}
9
  
10
.first {opacity: 1!important}
11
 
12
* {
13
  box-sizing: border-box;
14
}
15
$margin: 20px;
16
 
17
.flip-side {
18
  .visual-text-2 {
19
    display: block;
20
    transform: rotateY(180deg);
21
    opacity: 1!important;
22
  }
23
  transform: rotateY(180deg);
24
  .handle, .visual-inlay {
25
    opacity: 0;
26
  }
27
}
28
.visual-inlay {
29
  position: absolute;
30
  width: 100%;
31
  height: 100%;
32
}
33
.visual-overlay-container {
34
  border-radius: 50%;
35
  width: 70%;
36
  height: 70%;
37
  margin-left: 15%;
38
  margin-top: 15%;
39
  overflow: hidden;
40
  position: absolute;
41
}
42
    
43
.visual-overlay-container:before {
44
  content: '';
45
  width: 100%;
46
  height: 100%;
47
  background: rgba(255, 255, 255, 0.2);
48
  display:block;
49
  position:absolute;
50
  z-index: 10;
51
}
52
      
53
.visual-img {
54
  border-radius: 50%;
55
  width: 100%;
56
  height: 100%;
57
  position: absolute;
58
  background: url(https://secure.gravatar.com/avatar/fdce3ad4c57f9ca651c168a8cf1f9416?s=180&d=identicon) center center no-repeat;
59
  background-size: 100%;
60
  box-shadow: 1px 1px 6px 0px rgba(255,255,255,1), inset 2px 2px 6px 0px rgba(0,0,0,0.3);
61
}
62
  
63
.visual {
64
  width: 100%;
65
  height: 100%;
66
  position: relative;
67
  border-radius: 50%;
68
  //-webkit-clip-path: polygon(0% 0%, 0% 100%, 45% 100%, 50% 91.3333333333%, 55% 100%, 100% 100%, 100% 0%);
69
}
70
 
71
 
72
.visual-overlay {
73
  width: 100%;
74
  height: 100%;
75
  background: rgba(0, 0, 0, 1) url(https://secure.gravatar.com/avatar/fdce3ad4c57f9ca651c168a8cf1f9416?s=180&d=identicon) center center no-repeat;
76
  background-size: 140%;
77
  //-webkit-filter: blur(2px); -moz-filter: blur(2px); -o-filter: blur(2px); -ms-filter: blur(2px); filter: blur(2px);
78
  border-radius: 50%;
79
  position:absolute;
80
}
81
  
82
        
83
.handle {
84
  height: 100%;
85
  width: 100%;
86
  position: relative;
87
  top: -100%;
88
  float: left;
89
}
90
.visual-container {
91
  border-radius: 50%;  
92
  background: white;
93
  box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.2);
94
  border: $margin white solid;
95
  -webkit-transition: 0.5s;
96
  transition: 0.5s;
97
  .visual-text-2 {
98
    opacity: 0;
99
  }
100
}
101
      
102
.handle, .visual-inlay, .visual-text-2 {
103
  -webkit-transition: 0.25s;
104
  transition: 0.25s;
105
}
106
    
107
.visual-text {font-weight: 400}
108
 
109
.visual-text, .visual-text-2 {
110
  width: 100%;
111
  height: 100%;
112
  color: white;
113
  text-align: center;
114
  vertical-align: middle;
115
  position: absolute;
116
  line-height: 1em;
117
  z-index: 11;
118
  font-weight: 400;
119
  text-shadow: 0px 0px 8px black;
120
}
121
.visual-text-2 {
122
  color: #888;
123
  text-shadow: none;
124
  line-height: 1.2em;
125
  font-weight: 300;
126
}
127
.handle span {
128
  height: 100%;
129
  
130
  position: absolute;
131
  top: 0;
132
  left: 0;
133
  width: 100%;
134
  transform-origin: center center;
135
  text-transform: uppercase;
136
  text-align: center;
137
  font-size: $margin / 2;
138
  line-height: 1.9em;
139
  font-weight: 100;
140
  font-family: 'Source Code Pro', typewriter;
141
}
142
 
143
@for $s from 0 through 4 {
144
  $size: 100px + 20 * $s;
145
  .size#{$s} {
146
    opacity: 0.5;
147
 
148
    transition: 0.5s;
149
    -webkit-transition: 0.5s;
150
    position: absolute;
151
    margin-left: -80px;
152
    margin-top: -80px;
153
    .visual-container {
154
      width: $size + $margin * 2;
155
      height: $size + $margin * 2;
156
    }
157
    .visual-text {
158
      font-size: $size / 3;
159
      margin-top: $size / 6;
160
    } 
161
    .visual-text-2 {
162
      font-size: $size / 6;
163
      margin-top: $size / 4;
164
    }
165
    .handle span {
166
      font-size: $margin / 2;
167
    }
168
  }
169
}
170
$rotation: 8;
171
@for $i from 1 through 16 {
172
  .char#{$i} {
173
    font-weight: 400;
174
    transform: rotate(180 - $i * $rotation + deg);
175
    span {
176
      transform-origin: top center;
177
      transform: rotate(180deg);
178
    }
179
  }
180
  .length#{$i} {
181
    transform: rotate($i * $rotation / 2 + deg);
182
  }
183
}
184
 
 
JavaScript
var hash = {};
1
var hash = {};
2
var r = [];
3
 
4
function fromUTCDate(date) {
5
  if (!(date instanceof Date)) {
6
    date = new Date(date);
7
  }
8
  return new Date(Date.UTC(
9
    date.getFullYear(),
10
    date.getMonth(),
11
    date.getDate(),
12
    date.getHours(),
13
    date.getMinutes(),
14
    date.getSeconds(),
15
    date.getMilliseconds()
16
  ));
17
};
18
 
19
function pt(x, y) {
20
  return {
21
    x: x, 
22
    y: y, 
23
    toString: function() { return [this.x, this.y].join(','); }
24
  };
25
}
26
 
27
function adj(a) {
28
  return [
29
    pt(a.x + 1, a.y),
30
    pt(a.x, a.y + 1),
31
    pt(a.x - 1, a.y),
32
    pt(a.x, a.y - 1)
33
  ]
34
}
35
 
36
function adjcreate(a, m) {
37
  m = Math.abs(a.x) + Math.abs(a.y);
38
  if (hash[a] || m > 10) return;
39
  (r[m] = r[m] || []).push(a);
40
  hash[a] = true;
41
  adj(a).map(adjcreate);
42
}
43
 
44
function flat(a) {
45
  var b = [];
46
  for (var i = 0; i < a.length; i++) {
47
    for (var j = 0; j < a[i].length; j++) {
48
      b.push(a[i][j]);
49
    }
50
  }
51
  return b;
52
}
53
 
54
adjcreate(pt(0, 0));
55
 
56
r = flat(r);
57
 
58
function rand(a, b) {
59
  return a + Math.floor(Math.random() * (b - a));
60
}
61
 
62
/*********************************************************************
63
*  #### Twitter Post Fetcher v12.0 ####
64
*  Coded by Jason Mayes 2013. A present to all the developers out there.
65
*  www.jasonmayes.com
66
*  Please keep this disclaimer with my code if you use it. Thanks. :-)
67
*  Got feedback or questions, ask here:
68
*  http://www.jasonmayes.com/projects/twitterApi/
69
*  Github: https://github.com/jasonmayes/Twitter-Post-Fetcher
70
*  Updates will be posted to this site.
71
*********************************************************************/
72
var twitterFetcher = function() {
73
  var domNode = '';
74
  var maxTweets = 20;
75
  var parseLinks = true;
76
  var queue = [];
77
  var inProgress = false;
78
  var printTime = true;
79
  var printUser = true;
80
  var formatterFunction = null;
81
  var supportsClassName = true;
82
  var showRts = true;
83
  var customCallbackFunction = null;
84
  var showInteractionLinks = true;
85
  var showImages = false;
86
  var lang = 'en';
87
 
88
  function strip(data) {
89
    return data.replace(/<b[^>]*>(.*?)<\/b>/gi, function(a,s){return s;})
90
        .replace(/class=".*?"|data-query-source=".*?"|dir=".*?"|rel=".*?"/gi,
91
        '');
92
  }
93
 
94
  function getElementsByClassName (node, classname) {
95
    var a = [];
96
    var regex = new RegExp('(^| )' + classname + '( |$)');
97
    var elems = node.getElementsByTagName('*');
98
    for (var i = 0, j = elems.length; i < j; i++) {
99
        if(regex.test(elems[i].className)){
100
          a.push(elems[i]);
101
        }
102
    }
103
    return a;
104
  }
105
 
106
  function extractImageUrl(image_data) {
107
    if (image_data !== undefined) {
108
      var data_src = image_data.innerHTML.match(/data-srcset="([A-z0-9%_\.-]+)/i)[0];
109
      return decodeURIComponent(data_src).split('"')[1];
110
    }
111
  }
112
  
113
  var div;
114
  var first = 0;
115
 
116
  return {
117
    fetch: function(config) {
118
      if (config.maxTweets === undefined) {
119
        config.maxTweets = 20;
120
      }
121
      if (config.enableLinks === undefined) {
122
        config.enableLinks = true;
123
      }
124
      if (config.showUser === undefined) {
125
        config.showUser = true;
126
      }
127
      if (config.showTime === undefined) {
128
        config.showTime = true;
129
      }
130
      if (config.dateFunction === undefined) {
131
        config.dateFunction = 'default';
132
      }
133
      if (config.showRetweet === undefined) {
134
        config.showRetweet = true;
135
      }
136
      if (config.customCallback === undefined) {
137
        config.customCallback = null;
138
      }
139
      if (config.showInteraction === undefined) {
140
        config.showInteraction = true;
141
      }
142
      if (config.showImages === undefined) {
143
        config.showImages = false;
144
      }
145
 
146
//      if (inProgress) {
147
        queue.push(config);
148
//      } else {
149
        inProgress = true;
150
 
151
        domNode = config.domId;
152
        parseLinks = config.enableLinks;
153
        printUser = config.showUser;
154
        printTime = config.showTime;
155
        showRts = config.showRetweet;
156
        formatterFunction = config.dateFunction;
157
        customCallbackFunction = config.customCallback;
158
        showInteractionLinks = config.showInteraction;
159
        showImages = config.showImages;
160
 
161
        var script = document.createElement('script');
162
        script.type = 'text/javascript';
163
        script.src = '//cdn.syndication.twimg.com/widgets/timelines/' +(config.sinceId ?'paged/':'')+
164
            config.id + '?&lang=' + (config.lang || lang) + '&callback=twitterFetcher.callback&' +
165
            (config.sinceId ? 'max_id=' + config.sinceId + '&' : '')
166
            'suppress_response_codes=true&rnd=' + Math.random();
167
        document.getElementsByTagName('head')[0].appendChild(script);
168
        this.config = config;
169
//      }
170
    },
171
    
172
 
173
    callback: function(data) {
174
      var self = this;
175
      function handleTweets(tweets){
176
        console.log(tweets);
177
        if (customCallbackFunction) {
178
          customCallbackFunction(tweets);
179
          if (first < 2) {
180
            self.fetch(config);
181
            first++;
182
          }
183
        }
184
      }
185
      
186
      var config = this.config;
187
      delete this.config;
188
      div = div || document.createElement('div');
189
      if (data.body.indexOf('<li') === 0) {
190
        console.log($(data.body));
191
        if ($(data.body).length > 1) {
192
          div.querySelector('.stream .h-feed').innerHTML += data.body;
193
        } else {
194
          return;
195
        }
196
      } else {
197
        div.innerHTML = data.body;
198
      }
199
 
200
      if (typeof(div.getElementsByClassName) === 'undefined') {
201
         supportsClassName = false;
202
      }
203
 
204
      var tweets = [];
205
      var authors = [];
206
      var times = [];
207
      var images = [];
208
      var rts = [];
209
      var tids = [];
210
      var retweetCount = [];
211
      var favCount = [];
212
      var x = 0;
213
      
214
      console.log(div);
215
 
216
      var tmp = div.getElementsByClassName('tweet');
217
      console.log([].slice.call(tmp), tmp.length);
218
      while (x < tmp.length) {
219
        if (tmp[x].getElementsByClassName('retweet-credit').length > 0) {
220
          rts.push(true);
221
        } else {
222
          rts.push(false);
223
        }
224
        if (!rts[x] || rts[x] && showRts) {
225
          tweets.push(tmp[x].getElementsByClassName('e-entry-title')[0]);
226
          tids.push(tmp[x].getAttribute('data-tweet-id'));
227
          var author = tmp[x].getElementsByClassName('p-author')[0];
228
          authors.push({
229
            avatar: author.querySelector('[data-scribe="element:avatar"').getAttribute('data-src-2x'),
230
            name: author.querySelector('[data-scribe="element:name"').textContent,
231
            screenName: author.querySelector('[data-scribe="element:screen_name"').textContent
232
          });
233
          times.push(tmp[x].getElementsByClassName('dt-updated')[0]);
234
          if (tmp[x].getElementsByClassName('inline-media')[0] !== undefined) {
235
            images.push(tmp[x].getElementsByClassName('inline-media')[0]);
236
          } else {
237
            images.push(undefined);
238
          }
239
          if (tmp[x].getElementsByClassName('stats-retweets')[0] !== undefined) {
240
            retweetCount.push(tmp[x].getElementsByClassName('stats-retweets')[0].getElementsByTagName('strong')[0].textContent);
241
          } else {
242
            retweetCount.push(0);
243
          }
244
          if (tmp[x].getElementsByClassName('stats-favorites')[0] !== undefined) {
245
            favCount.push(tmp[x].getElementsByClassName('stats-favorites')[0].getElementsByTagName('strong')[0].textContent);
246
          } else {
247
            favCount.push(0);
248
          }
249
        }
250
        x++;
251
      }
252
      
253
      var arrayTweets = [];
254
      var x = tweets.length;
255
      var n = 0;
256
      while(n < x) {
257
        if (typeof(formatterFunction) !== 'string') {
258
          var newDate = new Date(times[n].getAttribute('datetime')
259
              .replace(/-/g,'/').replace('T', ' ').split('+')[0]);
260
          var dateString = formatterFunction(newDate);
261
          times[n].setAttribute('aria-label', dateString);
262
 
263
          if (tweets[n].innerText) {
264
            // IE hack.
265
            if (supportsClassName) {
266
              times[n].innerText = dateString;
267
            } else {
268
              var h = document.createElement('p');
269
              var t = document.createTextNode(dateString);
270
              h.appendChild(t);
271
              h.setAttribute('aria-label', dateString);
272
              times[n] = h;
273
            }
274
          } else {
275
            times[n].textContent = dateString;
276
          }
277
        }
278
        var op = '';
279
        var retval = {};
280
        if (printUser) {
281
          retval.author = authors[n];
282
        }
283
        if (parseLinks) {
284
          retval.tweet = strip(tweets[n].innerHTML);
285
          if (printTime) {
286
            retval.time = times[n].getAttribute('aria-label');
287
          }
288
        } else {
289
          if (tweets[n].innerText) {
290
            retval.tweet = tweets[n].textContent;
291
            if (printTime) {
292
              retval.time = times[n].textContent;
293
            }
294
          }
295
        }
296
        retval.id = tids[n];
297
 
298
        if (showImages && images[n] !== undefined) {
299
          retval.image = extractImageUrl(images[n]);
300
        }
301
        retval.isRetweet = rts[n];
302
        
303
        retval.stats = {retweets: parseInt(retweetCount[n], 10), favorites: parseInt(favCount[n], 10)};
304
 
305
        arrayTweets.push(retval);
306
        n++;
307
      }
308
      handleTweets(arrayTweets);
309
      inProgress = false;
310
 
311
      if (queue.length > 0) {
312
        twitterFetcher.fetch(queue[0]);
313
        queue.splice(0,1);
314
      }
315
    }
316
  }
317
}();
318
 
319
_.templateSettings = {
320
  interpolate: /\{\{(.+?)\}\}/g
321
};
322
 
323
var visualTemplate;
324
 
325
$(function () {
326
  visualTemplate = $('#visual-template').text();
327
  visualTemplate = _.template(visualTemplate);
328
  
329
});
330
 
331
function createVisual(tweet) {
332
  var element = document.createElement('div');
333
  element.innerHTML = visualTemplate({
334
    twitterHandle: tweet.author.screenName,
335
    retweetCount: tweet.stats.retweets,
336
    visualSize: 1,
337
    tweetId: tweet.id,
338
    avatarImage: tweet.author.avatar,
339
    tweetTime: tweet.time
340
  });
341
  var handle = $('.handle', element).text().trim();
342
  var text = '';
343
  for (var i = 1; i < handle.length + 1; i++)
344
    text += '<span class="char' + i + '"><span>' + handle[i - 1] + '</span></span>';
345
  $('.handle', element).html(text).addClass('length' + handle.length);
346
  return element;
347
}
348
 
349
var config = {
350
  "id": '512112985221775360',
351
  "domId": '',
352
  "enableLinks": true,
353
  "showUser": true,
354
  "showRetweet": true,
355
  
356
  "showTime": true,
357
  "dateFunction": function (date) {
358
    
359
    return moment(fromUTCDate(date)).format('MMM D<br>h:mma');
360
  },
361
  "showInteraction": true,
362
  "customCallback": handleTweets
363
};
364
 
365
function handleTweets(tweets) {
366
  config.sinceId = tweets[tweets.length-1].id;  
367
  tweets = tweets.filter(function(t) {
368
    return !t.isRetweet;
369
  });
370
  tweets.sort(function(t1, t2){ 
371
    if (t1.stats.retweets < t2.stats.retweets) {
372
      return 1;
373
    } else return -1;
374
  });
375
  
376
  console.log(tweets);
377
  
378
  for (var i = 0; i < tweets.length; i++) {
379
    var visual = $('#tweet' + tweets[i].id);
380
    var directions = [
381
      {left: '-50%', top: '-50%'},
382
      {left: '50%', top: '-50%'},
383
      {left: '150%', top: '-50%'},
384
      {left: '-50%', top: '50%'},
385
      {left: '150%', top: '50%'},
386
      {left: '-50%', top: '150%'},
387
      {left: '50%', top: '150%'},
388
      {left: '150%', top: '150%'}
389
    ];
390
    var random = rand(0, directions.length - 1);
391
    if (visual.length) {
392
      updateVisual(tweets[i], !i);
393
    } else {
394
      visual = createVisual(tweets[i]);
395
      visual = $('#tweet' + tweets[i].id, visual);
396
      visual.css({
397
        position: 'absolute',
398
        marginLeft: '-80px',
399
        marginTop: '-80px'
400
      })//.css(directions[random]);
401
      if (!i) {
402
        visual.addClass('first');
403
      }
404
      visual.css({'transform': 'translate(' + [r[i].x * 180 + 'px', r[i].y * 180 + 'px'] + ')'}, 400);
405
 
406
      $('#twtcontainer').append(visual);  
407
    }
408
    visual.css({'transform': 'translate(' + [r[i].x * 180 + 'px', r[i].y * 180 + 'px'] + ')'}, 400);
409
 
410
    visual.css({
411
      top: '50%',
412
      left: '50%'
413
    });
414
  }
415
}
416
 
417
function updateVisual(tweet, first) {
418
  console.log('updating tweet', tweet.stats.retweets);
419
  var div = $('#tweet' + tweet.id);
420
  if (first) {
421
    $('.first').removeClass('first');
422
    div.addClass('first');
423
  }
424
  div.find('.visual-img, .visual-overlay').css('background-image', "url('" + tweet.author.avatar + "')")
425
  div.find('.visual-text').text(tweet.stats.retweets);
426
}
427
 
428
var truth = true;
429
 
430
setInterval(function () {
431
  delete config.sinceId;
432
  twitterFetcher.fetch(config);
433
  if (truth) {
434
    $('.visual-container').removeClass('flip-side');
435
  } else {
436
    $('.visual-container').addClass('flip-side');
437
  }
438
  truth = !truth;
439
  
440
}, 4000);
441
 
 

Untitled

CSSDeck G+