Skip to content

Instantly share code, notes, and snippets.

@jlrodriguezdev
Created April 11, 2019 06:55
Show Gist options
  • Save jlrodriguezdev/cec92f6af55288aca226b43f6c9e667f to your computer and use it in GitHub Desktop.
Save jlrodriguezdev/cec92f6af55288aca226b43f6c9e667f to your computer and use it in GitHub Desktop.
Instafeed.js - User feed example with load more and modal gallery using jQuery and GSAP
<div class="instafeed-gallery">
<div class="header">
<ul class="meta">
<li>
<span class="count post-count"></span>
<span class="title">posts</span>
</li>
<li>
<span class="count follower-count"></span>
<span class="title">followers</span>
</li>
<li>
<span class="count following-count"></span>
<span class="title">following</span>
</li>
</ul>
</div>
<div id="instafeed-gallery-feed" class="row no-gutter">
<!-- instagram feed loads here -->
</div>
</div>
<button id="btn-instafeed-load" class="btn">Load more</button>
<div class="post-modal-container">
<!-- <div class="arrow-left">left</div>
<div class="arrow-right">right</div> -->
</div>
<div class="post-modal-backdrop"></div>
// ----- Notes -----
// A maximum of 20 posts can be loaded due to the app being in sandbox mode on instagram
// How to get an access token:
// http://jelled.com/instagram/access-token
// API Endpoints:
// https://www.instagram.com/developer/endpoints/
// Model guide example:
// https://www.instagram.com/selcukcura/media/
// {{model.user.username}}, {{likes}} likes
// user data example using userId and accessToken:
// https://api.instagram.com/v1/users/4622774/?access_token=4622774.7cbaeb5.ec8c5041b92b44ada03e4a4a9153bc54
$( window ).on('load', function() {
var feedHTML =
// header
'<div class="header-container">'+
'<img src="{{model.user.profile_picture}}" class="avatar">'+
'<div class="user-container">'+
'<p class="name">{{model.user.full_name}}</p>'+
'<p class="username"><a href="http://instagram.com/{{model.user.username}}" target="_blank">@{{model.user.username}}</a></p>'+
'</div>'+
'</div>'+
// posts
'<div class="img-featured-container col-xs-4">'+
'<div class="img-backdrop"></div>'+
'<div class="description-container">'+
'<span class="likes"><i class="icon ion-heart"></i> {{likes}}</span>'+
'<span class="comments"><i class="icon ion-chatbubble"></i> {{comments}}</span>'+
'</div>'+
'<img src="{{image}}" class="img-responsive">'+
'</div>'+
// modal
'<div class="post-modal">'+
'<div class="btn-close">'+
'<div class="close-icon">&times;</div>'+
'</div>'+
'<img src="{{image}}">'+
// video
// '<video controls autoplay>' +
// '<source src="{{model.videos.standard_resolution.url}}" type="video/mp4">' +
// 'Your browser does not support the video tag.' +
// '</video>' +
'<div class="post-modal-body">'+
'<div class="post-modal-meta-container">'+
'<p class="likes"><i class="icon ion-heart"></i> {{likes}}</p>'+
'<p class="comments"><i class="icon ion-chatbubble"></i> {{comments}}</p>'+
'</div>'+
'<div class="post-modal-caption-container">'+
'<p class="caption">{{caption}}</p>'+
'</div>'+
'</div>'+
'</div>'
var galleryFeed = new Instafeed({
target: "instafeed-gallery-feed",
get: "user",
userId: 4622774,
accessToken: "4622774.7cbaeb5.ec8c5041b92b44ada03e4a4a9153bc54",
resolution: "standard_resolution",
useHttp: "true",
limit: 6,
template: feedHTML,
before: function(){
// get user data
var url = 'https://api.instagram.com/v1/users/' + this.options.userId + '/?access_token=' + this.options.accessToken;
$.ajax({
method: 'GET',
url: url,
dataType: 'jsonp',
jsonp: 'callback',
success: function (response) {
// currently being replaced on each 'load more' button click
$('.post-count').html(response.data.counts.media);
$('.follower-count').html(response.data.counts.follows);
$('.following-count').html(response.data.counts.followed_by);
}
});
},
after: function() {
console.log('after');
var $headerContainer = $('.header-container'),
$imagePost = $('.img-featured-container'),
totalImages = $imagePost.length,
$postModalContainer = $('.post-modal-container'),
$postModal = $('.post-modal'),
$postModalBackdrop = $('.post-modal-backdrop'),
counter = 0;
console.log('totalImages', totalImages)
// remove all $headerContainer except one from template function and move to header
for (i=1; i < totalImages; i++) {
console.log('remove', i)
$headerContainer.eq(i).remove();
$('.header').prepend($headerContainer.eq(0));
$postModalContainer.prepend($postModal);
}
$imagePost.on('click', function() {
var postIndex = $(this).index();
console.log('clicked post', postIndex);
$postModal.eq(postIndex).addClass('show');
$postModalBackdrop.addClass('show');
});
$('.btn-close').on('click', function() {
var postIndex = $(this).index();
console.log('modal closed', postIndex)
$(this).parent().removeClass('show');
$postModalBackdrop.removeClass('show');
});
$postModalBackdrop.on('click', function() {
$postModal.removeClass('show');
$postModalBackdrop.removeClass('show');
});
$(document.documentElement).keydown(function(event) {
if (event.keyCode == 37) { // left arrow key
prevModal();
}
if (event.keyCode == 39) { // right arrow key
nextModal();
}
if (event.keyCode == 27) { // escape key
if ($postModal.hasClass('show')) {
$postModal.removeClass('show');
$postModalBackdrop.removeClass('show');
}
}
});
TweenMax.staggerTo($imagePost, 0.5, {autoAlpha:1}, 0.02);
// disable button if no more results to load
if (!this.hasNext()) {
console.log('no more posts to load')
TweenMax.to($btnInstafeedLoad, 0.5, {opacity:0.5, onComplete: function(){
$btnInstafeedLoad.attr('disabled', 'disabled');
}}, 0)
}
}
});
galleryFeed.run(firstLoad());
var $btnInstafeedLoad = $("#btn-instafeed-load");
$btnInstafeedLoad.on('click', function() {
console.log('btn clicked - load posts')
galleryFeed.next();
});
function firstLoad() {
console.log('first load');
var tl = new TimelineMax();
tl.to('body', 0.3, {autoAlpha:1}, 1);
tl.to('.instafeed-gallery', 0.3, {autoAlpha:1}, 0.2);
tl.staggerFrom('span', 0.5, {autoAlpha:0, y:10}, 0.05);
tl.from('.btn', 0.5, {autoAlpha:0, y:20, ease:Power2.easeOut}, 1.5);
}
// modal
function prevModal() {
console.log('prev modal')
}
function nextModal() {
var postIndex = $('post-modal.show').index();
counter = postIndex;
counter++
console.log('next modal: current index', counter)
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/instafeed.js/1.4.1/instafeed.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js"></script>
// vars
$postPadding: 0px;
$minWidth: 280px;
$maxWidth: 420px;
// general
@import url('https://fonts.googleapis.com/css?family=Lato:100,100i,300,300i,400,400i,700,700i,900,900i');
body {
background: #f9f9f9;
font-family: 'Lato', "Helvetica", Arial, sans-serif;
line-height: 1.2;
opacity: 0;
}
// helper
.hide {
display: none !important;
opacity: 0 !important;
}
.show {
display: block !important;
opacity: 1 !important;
}
/* remove bootstrap gutter*/
.row.no-gutter {
margin-left: 0;
margin-right: 0;
}
.row.no-gutter [class*='col-']:not(:first-child),
.row.no-gutter [class*='col-']:not(:last-child) {
padding-right: 0;
padding-left: 0;
}
// the good stuff
.instafeed-gallery {
background: #fff;
min-width: $minWidth;
max-width: $maxWidth;
width: 100%;
margin: 0 auto;
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.15);
border-radius: 2px;
transition: all 0.2 ease;
opacity: 0;
}
.header {
p {
margin: 0;
}
a {
color: inherit;
&:hover {
color: #aaa;
text-decoration: none;
}
}
.header-container {
text-align: center;
padding: 30px 30px 0;
.avatar {
width: 100%;
max-width: 120px;
border-radius: 100%;
margin: 0 auto;
display: block;
}
.user-container {
margin-top: 20px;
}
.name {
font-size: 20px;
font-weight: 600;
}
.username {
color: #bbb;
font-size: 16px;
}
}
.meta {
width: 100%;
margin: 0;
padding: 30px;
display: table;
li {
text-align: center;
width: 33%;
display: table-cell;
}
span {
display: block;
}
.count {
font-size: 20px;
font-weight: 600;
}
.title {
color: #bbb;
font-size: 16px;
}
}
}
.post-modal-container {
.post-modal {
background: #fff;
min-width: $minWidth;
max-width: $maxWidth;
margin: auto;
top: 0;
right: 0;
left: 0;
z-index: 9999;
position: fixed;
display: none;
opacity: 0;
}
.btn-close {
color: #fff;
background: rgba(0, 0, 0, 0.5);
width: 40px;
height: 40px;
top: 0;
right: 0;
position: absolute;
cursor: pointer;
&:hover {
background: rgba(0, 0, 0, 0.7);
}
}
.close-icon {
font-size: 22px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: absolute;
}
img {
width: 100%;
}
.post-modal-body {
padding: 15px;
}
.post-modal-meta-container {
margin-bottom: 10px;
p {
color: #bbb;
display: inline-block;
margin-right: 10px;
}
.icon {
margin-right: 2px;
}
}
.post-modal-caption-container {
}
}
.post-modal-backdrop {
background: rgba(0,0,0,0.7);
top: 0;
right: 0;
bottom: 0;
left: 0;
position: fixed;
z-index: 999;
display: none;
cursor: pointer;
}
// post
.img-featured-container {
overflow: hidden;
position: relative;
padding: $postPadding;
opacity: 0;
cursor: pointer;
}
.img-featured-container img {
width: 100%;
}
.img-featured-container .img-backdrop {
background: linear-gradient(135deg, rgba(38, 163, 255, 0.85), rgba(83, 201, 179, 0.85));
margin: 0;
padding: $postPadding;
width: 100%;
height: 100%;
position: absolute;
z-index: 1;
opacity: 0;
transition: all 0.3s ease;
}
.img-featured-container:hover > .img-backdrop {
opacity: 1;
}
// center text horizontally and vertically on image hover
.img-featured-container .description-container {
color: #fff;
font-size: 16px;
line-height: 1.2;
text-align: center;
line-height: 20px;
width: 100%;
padding: 10px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: absolute;
transform-style: preserve-3d;
transition: all .2s ease;
z-index: 2;
opacity: 0;
}
.img-featured-container .description-container .fa-instagram {
font-size: 40px;
}
.img-featured-container .description-container p {
font-weight: 300;
margin-bottom: 0;
}
.img-featured-container:hover .description-container {
opacity: 1;
}
.img-featured-container .description-container .likes,
.img-featured-container .description-container .comments {
margin: 0 5px;
}
// load more button
#btn-instafeed-load {
color: #fff;
background: #26a3ff;
font-size: 16px;
margin: 20px auto;
padding: 8px 40px;
display: block;
border: none;
}
// media queries
@media screen and (min-width:$maxWidth) {
.post-modal-container {
.post-modal {
margin: 20px auto;
}
}
}
@media screen and (min-width:768px) {
.instafeed-gallery {
margin: 50px auto 30px;
}
}
<link href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment