maintenance-as-architecture
clone your own copy | download snapshot

Snapshots | iceberg

Inside this repository

tags.js
application/javascript

Download raw (6.5 KB)

(function () {
  'use strict';

  function forEach (list, callback) {
    if (list.forEach) {
      list.forEach(callback);
    } else {
      for (var i=0;i<list.length;i++) {
        callback(list[i], i);
      }
    }
  }

  function map (list, callback) {
    var buff = [];
  
    forEach(list, function (v, k) {
      buff.push(callback(v, k));
    });

    return buff;
  }

  function loadPosts (url) {
    fetch(url, { method: 'GET'})
      .then(function(response) {
        if (response.status == 200) {
            // success
            response.text().then(function (html) {
              var parser = new DOMParser(),
                  dom = parser.parseFromString(html, "text/html");

              forEach(dom.querySelectorAll('article.entry'), function (el) { postList.addPost(new Post(el)) });
              unifyStrokeWidths();
            });
        } else {
            // showError();
        }
    });
  }

  var TagManager = function (tags) {
    this.activeTags = (tags && Array.isArray(tags)) ? tags : [];
    this.setBodyClass();
  }

  TagManager.prototype.toggle = function (tag, tagUrl) {
    if (this.activeTags.includes(tag)) {
      this.disable(tag);
    } else {
      this.enable(tag, tagUrl);
    }
  }

  TagManager.prototype.setBodyClass = function () {
    document.body.classList.toggle('filter-active', this.activeTags.length > 0);
  }

  TagManager.prototype.enable = function (tag, url) {
    if (!this.activeTags.includes(tag)) {
      this.activeTags.push(tag);
      this.setBodyClass();

      if (this.activeTags.length == 1) {
        postList.filter(this.activeTags);
      }

      forEach(document.querySelectorAll('.tag[data-slug="' + tag + '"]'), function (el) { el.classList.toggle('active', true );});
      loadPosts(url);
      this.updateURL();
    }
  }

  TagManager.prototype.disable = function (tag) {
    if (this.activeTags.includes(tag)) {
      this.activeTags.splice(this.activeTags.indexOf(tag), 1);
      postList.filter(this.activeTags);
      forEach(document.querySelectorAll('.tag[data-slug="' + tag + '"]'), function (el) { el.classList.toggle('active', false );});
      this.updateURL();
      this.setBodyClass();
      if (this.activeTags.length == 0) {
        loadPosts('/index.html');
      }
    }
  }

  TagManager.prototype.updateURL = function () {
    var params = new URLSearchParams();
    params.set('t', this.activeTags.join(','));
    console.log(params.toString());
    // push 
  }

  TagManager.prototype.updatePostCount = function (count) {
    document.getElementById('taglist').dataset.postCount = count;
  }

  var Post = function (domEl) {
    this.el = domEl;
    this.slug = this.parseSlug();
    this.tags = this.parseTags();
    this.activeTags();
    this.activateToggle();
  }

  Post.prototype.parseSlug = function () { return this.el.dataset.slug; }

  Post.prototype.parseTags = function () {
    return map(this.el.querySelectorAll(".tags .tag"), function (el) { return el.dataset.slug });  
  }

  Post.prototype.remove = function () {
    // Perhaps more fancy later on?
    this.el.parentElement.removeChild(this.el);
  }

  Post.prototype.hasTag = function (tag) {
    return this.tags.includes(tag);
  }

  Post.prototype.hasSomeTags = function (tags) {
    return tags.some(this.hasTag, this);
  }

  Post.prototype.activeTags = function () {
    var tags = this.el.querySelectorAll(".tags .tag");
    
    forEach(tags, function (el) {
      el.classList.toggle('active', tagManager.activeTags.includes(el.dataset.slug));
      el.addEventListener('click', function (e) {
        e.preventDefault();
        tagManager.toggle(el.dataset.slug, el.getAttribute('href'));
      });
    });
  }

  Post.prototype.activateToggle = function () {
    var toggle = this.el.querySelector('.toggle'),
        el = this.el;
    el.dataset.expanded = false;
    if (toggle) {
      toggle.addEventListener('click', function (e) { 
        e.preventDefault();
        el.dataset.expanded = ('expanded' in el.dataset && el.dataset.expanded == 'true') ? 'false' : 'true';
      });
    }
  }

  var PostList = function (domEl) {
    this.el = domEl;
    var posts = this.el.querySelectorAll('.entry');
    this.posts = map(posts, function (el) { return new Post(el); });
    this.updatePostCount();
  };

  PostList.prototype.addPost = function (post) {
    if (!this.has(post.slug)) {
      this.posts.push(post);
      var domEl = this.el.appendChild(post.el);
      this.updatePostCount();
      return domEl;
    }
  }

  PostList.prototype.updatePostCount = function () {
    tagManager.updatePostCount(this.posts.length);
  }

  PostList.prototype.removePost = function (i) {
    this.posts.splice(i, 1).forEach(function (p) { p.remove(); });
    this.updatePostCount();
  }

  PostList.prototype.filter = function (tags) {
    var i = 0;
   
    while (i < this.posts.length) {
      if (this.posts[i].hasSomeTags(tags)) {
        i++;
      } else {
        this.removePost(i);
      }
    }
  }

  PostList.prototype.removeAllPosts = function () {
    while (this.postList.length > 0) {
      this.removePost(0);
    }
  }

  PostList.prototype.has = function (slug) {
    return this.posts.some(function (p) { return p.slug === slug });
  }

  PostList.prototype.find = function (slug) {
    return this.posts.find(function (p) { return p.slug === slug });
  }

  PostList.prototype.load = function () {

  }

  var TagList = function (list) {
    this.el = list;
    this.el.classList.toggle('show-all', false);

    forEach(list.querySelectorAll('.tag'), function (tag) {
      tag.addEventListener('click', function (e) {
        e.preventDefault();
        tagManager.toggle(tag.dataset.slug, tag.getAttribute('href'));
        // list.classList.toggle('show-all', false);
      });
    });
    list.querySelector('.show-all-toggle').addEventListener('click', function (e) {
      this.toggleShowAll();
    }.bind(this));
  }

  TagList.prototype.toggleShowAll = function() {
    this.el.classList.toggle('show-all');
    document.body.classList.toggle('filter-list--expanded');
  }
  
  window.Post = Post;
  window.PostList = PostList;
  window.TagManager = TagManager;
  window.TagList = TagList;


  window.tagManager = new TagManager(map(document.querySelectorAll('#taglist .tag.active'), function (tag) { return tag.dataset.slug }));
  window.postList = new PostList(document.querySelector('#postlist'));
  window.tagList = new TagList(document.querySelector('#taglist'));

  document.querySelector('#menu-item-tags').addEventListener('click', function (e) {
    e.preventDefault();
    tagList.toggleShowAll();
  });
})();