Modal base

C:\Users\Administrator\Desktop\git-blaze\zuck.js\zuck.css

/* base */
.stories {
  white-space: nowrap;
  overflow: auto;
}
.stories .story {
  display: inline-block;
  width: 20vw;
  margin: 0 12px;
  max-width: 90px;
}
.stories .story:first-child {
  margin-left: 0;
}
.stories .story:last-child {
  margin-right: 0;
}
.stories .story > a {
  display: block;
}
.stories .story > a > span > img {
  width: 100%;
}
.stories .story > .items {
  display: none;
}
/* modal */
#zuck-modal {
  position: fixed;
  background: rgba(0, 0, 0, 0.5);
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
}
#zuck-modal-content,
#zuck-modal-content .stories-slides,
#zuck-modal-content .stories-slides > * {
  background: #000;
  width: 100vw;
  height: 100vh;
  position: absolute;
}
#zuck-modal-content .slide-item > * {
  height: 100%;
  margin: auto;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}

C:\Users\Administrator\Desktop\git-blaze\zuck.js\skins\snapgram.css

.stories.snapgram .story > a,
.stories.snapgram .story > a:visited {
  text-decoration: none;
  text-align: center;
  color: #333;
}
.stories.snapgram .story > a > span {
  border-radius: 50%;
  display: block;
  box-sizing: border-box;
  padding: 2px;
  background: radial-gradient(ellipse at 70% 70%, #ee583f 8%, #d92d77 42%, #bd3381 58%);
  font-size: 0;
  max-height: 90px;
  height: 20vw;
  overflow: hidden;
}
.stories.snapgram .story.seem {
  opacity: 0.75;
}
.stories.snapgram .story.seem > a > span {
  background: #999;
  color: #999;
}
.stories.snapgram .story.seem > a {
  color: #999 !important;
}
.stories.snapgram .story > a > span > i {
  display: block;
  border-radius: 50%;
  border: 3px solid #fff;
  box-sizing: border-box;
  height: 100%;
  width: 100%;
  background-size: cover;
}
.stories.snapgram .story > a > strong {
  display: inline-block;
  margin-top: 0.5em;
  line-height: 1.2em;
  font-size: 14px;
}

C:\Users\Administrator\Desktop\git-blaze\zuck.js\index.html

<html>
<head>
  <title>x</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0" />
  <!-- styles just for demo -->
  <style>
    body {
      font-size: 14px;
      font-family: sans-serif;
      padding: 0;
      margin: 0;
    }
    #stories {
      padding: 12px;
    }
    h1 {
      font-family: monospace;
      padding: 12px;
      border-bottom: 1px solid #ddd;
      font-size: 24px;
      height: 56px;
      line-height: 56px;
      margin-bottom: 0;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
    }
  </style>
  <!-- script styles -->
  <link rel="stylesheet" href="zuck.css">
  <link rel="stylesheet" href="skins/snapgram.css">
</head>
<body>
  <h1>~/evan/app_boilerplate</h1>
  <div id="stories"></div>
  <script src="zuck.js"></script>
  <script>
    var itemsExample = [
      {
        id: "ramon-1",
        type: "photo",
        length: 5,
        src: "images/1.jpg",
        preview: "images/1.jpg",
        link: false,
        seem: false
      },
      {
        id: "ramon-2",
        type: "photo",
        length: 5,
        src: "images/2.jpg",
        preview: "images/2.jpg",
        link: "https://twitter.com/ramon82",
        seem: false
      },
      {
        id: "ramon-3",
        type: "photo",
        length: 41,
        src: "images/3.jpg",
        preview: "images/3.jpg",
        link: "https://twitter.com/ramon82",
        seem: false
      }
    ];
    var stories = new Zuck('stories', {
      stories: [
        {
          id: "gorillaz",
          photo: "images/1.jpg",
          name: "Gorillaz",
          link: "",
          lastUpdated: "2017-04-09 05:08:30",
          items: itemsExample
        },
        {
          id: "ladygaga",
          photo: "images/2.jpg",
          name: "Lady Gaga",
          link: "",
          lastUpdated: "2017-04-09 05:08:30",
          items: itemsExample
        },
        {
          id: "starboy",
          photo: "images/3.jpg",
          name: "Abel",
          link: "",
          lastUpdated: "2017-04-09 05:08:30",
          items: itemsExample
        },
        {
          id: "qotsa",
          photo: "images/4.jpg",
          name: "QOTSA",
          link: "",
          lastUpdated: "2017-04-09 05:08:30",
          items: itemsExample
        },
        {
          id: "ramon",
          photo: "images/5.jpg",
          name: "Ramon",
          link: "https://ramon.codes",
          lastUpdated: "2017-04-09 05:08:30",
          items: itemsExample
        }
      ]
    });
  </script>
</body>
</html>

C:\Users\Administrator\Desktop\git-blaze\zuck.js\zuck.js

window['ZuckitaDaGalera'] = window['Zuck'] = function (element, options) {
  var zuck = this;
  var d = document;
  var q = function (query) {
    return d.querySelectorAll(query)[0];
  };
  var g = function (array, what) {
    if (array) {
      return array[what] || '';
    } else {
      return '';
    }
  };
  var each = function (arr, func) {
    if (arr) {
      var total = arr.length;
      for (var i = 0; i < total; i++) {
        func(i, arr[i]);
      }
    }
  };
  var prepend = function (parent, child) {
    if (parent.firstChild) {
      parent.insertBefore(child, parent.firstChild);
    } else {
      parent.appendChild(child);
    }
  };
  zuck.data = {};
  options = options;
  optionsDefault = {
    skin: 'snapgram',
    avatars: true,
    saveRead: function (storyId, storyItemId, status) {
    },
    stories: [],
    expiresIn: 24
  };
  if (typeof element == 'string') {
    element = d.getElementById(element);
  }
  var id = element.id;
  var option = function (name, prop) {
    if (prop) {
      if (options[name]) {
        return options[name][prop] || optionsDefault[name][prop]
      } else {
        return optionsDefault[name][prop];
      }
    } else {
      return options[name] || optionsDefault[name]
    }
  };
  if (!window['ZuckModal']) {
    window['ZuckModal'] = function () {
      var modalContainer = g('#zuck-modal');
      if (!modalContainer) {
        modalContainer = d.createElement('div');
        modalContainer.id = 'zuck-modal';
        modalContainer.innerHTML = '<div id="zuck-modal-content"></div>';
        modalContainer.style.display = 'none';
        d.body.appendChild(modalContainer);
      }
      return {
        'show': function (storyId, page) {
          var modalContent = q('#zuck-modal-content');
          var html = '';
          each(zuck.data[storyId]['items'], function (i, item) {
            html += '<div class="slide-item">' +
              ((item['type'] == 'video') ? '<video src="' + item['src'] + '">' : '<img src="' + item['src'] + '">') +
              '</div>';
          });
          console.log('modalshow', modalContent, storyId, zuck.data[storyId]['items'], html);
          modalContent.innerHTML = '<div class="stories-slides">' + html + '</div>';
          modalContainer.style.display = 'block';
        }
      };
    };
  }
  var modal = new ZuckModal();
  var parseItems = function (story) {
    var storyId = story.getAttribute('data-id');
    var storyItems = d.querySelectorAll('#' + id + ' [data-id="' + storyId + '"] .items > li');
    var items = [];
    each(storyItems, function (i, el) {
      var a = el.firstElementChild;
      var img = a.firstElementChild;
      items.push({
        'src': a.getAttribute('href'),
        'link': a.getAttribute('data-link'),
        'preview': img.getAttribute('src')
      });
    });
    zuck.data[storyId]['items'] = items;
  };
  var parseStory = function (story) {
    var storyId = story.getAttribute('data-id');
    try {
      zuck.data[storyId] = {
        'id': storyId, //story id
        'photo': story.getAttribute('data-photo'), //story photo (or user photo)
        'name': story.firstElementChild.lastElementChild.text,
        'link': story.firstElementChild.getAttribute('href'),
        'lastUpdated': story.getAttribute('data-last-updated'),
        'items': []
      };
    } catch (e) {
      zuck.data[storyId] = {
        'items': []
      };
    }
    story.onclick = function (e) {
      e.preventDefault();
      //story.className += ' seem';
      modal.show(storyId);
    };
  };
  zuck.add = function (data) {
    var storyId = g(data, 'id');
    var story = q('#' + id + ' [data-id="' + storyId + '"]');
    var html = '';
    var items = g(data, 'items');
    zuck.data[storyId] = {};
    if (!story) {
      story = d.createElement('div');
      story.setAttribute('data-id', storyId);
      story.className = 'story';
      html = '<a href="' + g(data, 'link') + '">' +
        '<span><i class="img" style="background-image:url(' + g(data, 'photo') + ')"></i></span>' +
        '<strong>' + g(data, 'name') + '</strong>' +
        '</a>' +
        '<ul class="items"></ul>';
      story.innerHTML = html;
      parseStory(story);
      prepend(element, story);
      each(items, function (i, item) {
        zuck.addItem(storyId, item);
      });
    }
  };
  zuck.addItem = function (storyId, data) {
    var story = q('#' + id + ' > [data-id="' + storyId + '"]');
    var li = d.createElement('li');
    li.className = g(data, 'seem') ? 'seem' : '';
    li.setAttribute('data-id', g(data, 'id'));
    li.innerHTML = '<a href="' + g(data, 'src') + '" data-link="' + g(data, 'link') + '">' +
      '<img src="' + g(data, 'preview') + '">' +
      '</a>';
    prepend(story.querySelectorAll('.items')[0], li);
    parseItems(story);
  };
  zuck.removeItem = function (storyId, itemId) {
    var item = q('#' + id + ' > [data-id="' + storyId + '"] [data-id="' + itemId + '"]');
    element.parentNode.removeChild(item);
  };
  var init = function () {
    console.log('init', option('stories'));
    if (q('#' + id + ' .story')) {
      each(element.querySelectorAll('.story'), function (i, story) {
        parseStory(story, true);
      });
    }
    each(option('stories'), function (i, item) {
      zuck.add(item);
    });
    element.className = (option('skin')) ? 'stories ' + option('skin') : 'stories';
    return zuck;
  };
  return init();
};

Last updated