Membuat Custom Widget Post Blogger dengan Tabs Dinamis Berdasarkan Label Seperti Animestream

Rasgane
Get Started > Details
  • Details
  • Code

Deskripsi.

Widget ini berfungsi untuk menampilkan postingan terbaru dari Blogger berdasarkan label yang dipilih, ditampilkan dalam format tab dinamis. Setiap tab mewakili satu label, dan pengguna dapat dengan mudah berpindah antar tab untuk melihat artikel berdasarkan kategori. untuk desain mengambil dari AnimeStream.

  • Salin kode HTML dibawah

    Untuk kode ini kalian bebas untuk di letakan dimana saja.

    <div class="cp_tabs_animestream">
      <div class="tabs" id="tabs-container"></div>
      <div id="tab-contents-container"></div>
    </div>
  • Salin kode CSS dibawah

    Dan untuk css bisa diletakan antara <b:skin><![CDATA[...]]></b:skin> atau <style>...</style>. pilih salah satu saja.

    :root {
      --w-1: 100%;
      --w-2: 50%;
      --w-3: 33.3333333%;
      --w-4: 25%;
      --w-5: 20%;
      --w-6: 16.66666%;
    }
    .cp_tabs_animestream .tabs{display: flex;margin: 0;list-style: none;padding: 5px;overflow: hidden;background: #f7f7f7;border-radius: 3px;font-size: 13px}
    .cp_tabs_animestream .tabs .tab{flex: 1;cursor: pointer;text-align: center;padding: 5px;text-overflow: ellipsis;overflow: hidden;white-space: nowrap}
    .cp_tabs_animestream .tabs .tab.active{background: #0c70de;border-radius: 3px;color: #fff}
    .cp_tabs_animestream .tab-content{display: none;padding: 10px 0;overflow: hidden}
    .cp_tabs_animestream .tab-content.active{display: block}
    .cp_tabs_animestream .tab-content>p{text-align: center}
    .cp_tabs_animestream .tab-content article{float: left;width: var(--w-5)}
    .cp_tabs_animestream .tab-content article>a{color: #333;display: block;overflow: hidden;margin: 7px;margin-bottom: 15px;transition: all .2s;-webkit-transition: all .2s;position: relative}
    .cp_tabs_animestream .tab-content article>a .images{position: relative}
    .cp_tabs_animestream .tab-content article>a figure{position: relative;margin: 0;padding-top: 142%;border-radius: 3px;overflow: hidden}
    .cp_tabs_animestream .tab-content article>a figure{position: relative;margin: 0;padding-top: 142%;border-radius: 3px;overflow: hidden;background: #dfdfdf}
    .cp_tabs_animestream .tab-content article>a figure .status.Completed{position: absolute;display: block;top: 7%;left: -34%;line-height: normal;color: #fff;text-transform: uppercase;z-index: 1;padding: 2px 0;font-size: 9px;width: 100%;text-align: center;background: #d33;-ms-transform: rotate(-45deg);-webkit-transform: rotate(-45deg);transform: rotate(-45deg)}
    .cp_tabs_animestream .tab-content article>a figure .typez{position: absolute;top: 5px;right: 5px;font-size: 12px;padding: 2px 5px;line-height: normal;border-radius: 3px;z-index: 1;color: #fff;background: #333}
    .cp_tabs_animestream .tab-content article>a figure .typez.TV{background: #0c70de}
    .cp_tabs_animestream .tab-content article>a figure .typez.Movie{background: #9c27b0}
    .cp_tabs_animestream .tab-content article>a figure .typez.Live{background: #ff5722}
    .cp_tabs_animestream .tab-content article>a figure .typez.OVA{background: #2196f3}
    .cp_tabs_animestream .tab-content article>a figure .typez.Special{background: #d3392d}
    .cp_tabs_animestream .tab-content article>a figure .ply{display: none;position: absolute;width: 100%;z-index: 1;height: 100%;top: 0;background: rgba(34,58,101,.7)}
    .cp_tabs_animestream .tab-content article:hover>a figure .ply{display: block}
    .cp_tabs_animestream .tab-content article>a figure .ply i{border-radius: var(--w-5);-webkit-border-radius: var(--w-5);-moz-border-radius: var(--w-5);font-size: 45px;position: absolute;top: 50%;left: 50%;display: inline-block;text-align: center;line-height: 38px;margin-top: -20px;margin-left: -25px;speak: none;text-transform: none;line-height: 1;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;color: #fff;line-height: 38px;transition: all .3s ease 0;-webkit-transition: all .3s ease 0;-moz-transition: all .3s ease 0}
    .cp_tabs_animestream .tab-content article>a figure .bt{position: absolute;bottom: 0;z-index: 1;width: 100%;color: #fff;font-size: 12.5px;overflow: hidden;background: linear-gradient(180deg,rgba(0,0,0,0) 0%,rgba(0,0,0,.6) 30%,rgba(0,0,0,.8) 60%,rgba(0,0,0,.7) 100%);padding-bottom: 5px;padding-top: 12px}
    .cp_tabs_animestream .tab-content article>a figure .bt .epx{display: block;float: left;margin-left: 10px}
    .cp_tabs_animestream .tab-content article>a figure .bt .sb{display: block;float: right;padding: 2px 5px;font-size: 12px;color: #111;margin-right: 5px;line-height: normal;border-radius: 3px;background: #ffa000}
    .cp_tabs_animestream .tab-content article>a figure .bt .Dub{background: #e32214;color: #fff}
    .cp_tabs_animestream .tab-content article>a figure .bt .Raw{background: rgba(14,175,193,.8);color: #fff}
    .cp_tabs_animestream .tab-content article>a .tt{height: 33px;overflow: hidden;font-size: .95em;margin: 8px 0;margin-bottom: 0;line-height: 1.25em;text-align: center}
    .cp_tabs_animestream .tab-content article>a figure img{position: absolute;left: 0;right: 0;bottom: 0;top: 0;width: 100%;height: 100%;transition: all .15s ease-out}
    .cp_tabs_animestream .tab-content article:hover>a figure img{transform: scale(1.1);transition: all .15s ease-out}
    @media only screen and (max-width: 768px){.cp_tabs_animestream .tabs .tab:nth-child(n+5){display: none}.cp_tabs_animestream .tab-content article{width: var(--w-4)}}
    @media only screen and (max-width: 540px){.cp_tabs_animestream .tabs .tab:nth-child(n+4){display: none}.cp_tabs_animestream .tab-content article{width: var(--w-3)}}
    @media only screen and (max-width: 425px){.cp_tabs_animestream .tabs .tab:nth-child(n+3){display: none}.cp_tabs_animestream .tab-content article{width: var(--w-2)}}

    Jika ingin mengganti tampilan tab dan konten, Anda bisa mengedit bagian CSS sesuai selera Anda.

  • Salin kode Javascript dibawah

    Untuk javascript bisa diletakkan diatas </body> dengan dibungkus

    <script>//<![CDATA[
      kode di sini
    //]]></script>
    !function() {
      let s = {
        url_blog: "",
        label: ["Action", "Adventure", "Avant Garde", "Award Winning", "Boys Love", "Comedy", "Drama", "Fantasy", "Girls Love", "Gourmet", "Horror", "Mystery", "Romance", "Sci-Fi", "Slice of Life", "Sports", "Supernatural", "Suspense"],
        max_artikel: 5,
        max_tabs: 5,
        no_thumbnail: "https://1.bp.blogspot.com/-XSp30PahyTM/YK37Rq_-M7I/AAAAAAAABCc/01K0sUhw-2YI7vr48wqMIAVoMLDEUdK2gCLcBGAsYHQ/s2048/No%2BImage%2BBerkas%2BKita.jpg",
        thumbnail_size: 720,
        filter_status: "Completed",
        status: ["Completed", "Delay", "Ongoing"],
        type: ["TV", "ONA", "OVA", "Bluray", "BD", "Special"],
        sub: ["Sub", "Dub", "Raw"]
      };
      (a => {
        for (let t = a.length - 1; 0 < t; t--) {
          var e = Math.floor(Math.random() * (t + 1));
          [a[t], a[e]] = [a[e], a[t]]
        }
      })(s.label);
      const r = s.label.slice(0, s.max_tabs),
        c = {
          getByLabel: async (t, a, e = s.max_artikel) => {
            try {
              var i = (await (await fetch(`${t}/feeds/posts/default/-/${encodeURIComponent(a)}?alt=json&max-results=` + e)).json()).feed;
              if (!i.entry) return [];
              return i.entry.map(t => {
                var a = t.content?.$t || t.summary?.$t || "",
                  e = t.media$thumbnail ? t.media$thumbnail.url.replace("/s72-c/", `/s${s.thumbnail_size}/`) : (t => {
                    t = t.match(/<img.*?src=["'](.*?)["'].*?>/i);
                    return t ? t[1] : s.no_thumbnail
                  })(a),
                  i = t.category ? t.category.map(t => t.term) : [];
                return {
                  title: t.title.$t,
                  link: t.link.find(t => "alternate" === t.rel).href,
                  content: a,
                  published: t.published.$t,
                  updated: t.updated.$t,
                  id: t.id.$t,
                  author: {
                    name: t.author[0]?.name.$t || "Unknown",
                    uri: t.author[0]?.uri.$t || "",
                    image: t.author[0]?.gd$image?.src || "https://via.placeholder.com/50"
                  },
                  thumbnail: e,
                  labels: i
                }
              })
            } catch (t) {
              return console.error(`Error fetching label '${a}':`, t), []
            }
          }
        };
      (() => {
        var t = document.getElementById("tabs-container"),
          a = document.getElementById("tab-contents-container");
        let e = "",
          i = "";
        r.forEach((t, a) => {
          e += `<div class="tab ${0===a?"active":""}" data-tab="${a+1}">${t}</div>`, i += `<div class="tab-content ${0===a?"active":""}" id="tab-${a+1}" data-label="${t}"><p>Loading...</p></div>`
        }), t.innerHTML = e, a.innerHTML = i;
        const l = document.querySelectorAll(".tab"),
          n = document.querySelectorAll(".tab-content");
        l.forEach(t => {
          t.addEventListener("click", function() {
            var t = this.getAttribute("data-tab");
            l.forEach(t => t.classList.remove("active")), n.forEach(t => t.classList.remove("active")), this.classList.add("active"), document.getElementById("tab-" + t).classList.add("active")
          })
        }), async function(e, i = s.max_artikel) {
          document.querySelectorAll(".tab-content").forEach(async t => {
            var a = t.dataset.label,
              a = await c.getByLabel(e, a, i);
            let l = "";
            a.length ? (a.forEach(t => {
              var a = t.labels.find(t => s.status.includes(t)),
                e = t.labels.find(t => s.type.includes(t)),
                i = t.labels.find(t => s.sub.includes(t));
              l += `<article>
                  <a href="${t.title}" title="${t.title}">
                    <div class="images">
                      <figure>
                        ${a===s.filter_status?`<div class="status ${a}">${a}</div>`:""}
                        ${e?`<div class="typez ${e}">${e}</div>`:""}
                        <div class="ply"><i class="far fa-play-circle" aria-hidden="true"></i></div>
                        <div class="bt">
                          ${a?`<span class="epx">${a}</span>`:""}
                          ${i?`<span class="sb ${i}">${i}</span>`:""}
                        </div>
                        <img src="${t.thumbnail}" alt="${t.title}">
                      </figure>
                    </div>
                    <div class="tt"><span class="ntitle">${t.title}</span></div>
                  </a>
                </article>`
            }), t.innerHTML = l) : t.innerHTML = "<p>Tidak ada postingan dengan label ini.</p>"
          })
        }(s.url_blog)
      })()
    }();
    Name Deskripsi
    url_blog Sebagai sumber data feed Blogger berdasarkan label.
    label Digunakan untuk membuat tab sesuai dengan label yang ditentukan.
    max_artikel Isi dengan jumlah postingan maksimal yang ingin ditampilkan di setiap tab. Misalnya, 5 berarti akan menampilkan 5 postingan terbaru untuk tiap label.
    max_tabs Jumlah tab maksimal yang ditampilkan. Jika label berisi 10 kategori, tetapi max_tabs diset ke 5, maka hanya 5 label yang akan ditampilkan secara acak.
    no_thumbnail URL gambar default jika postingan tidak memiliki thumbnail.
    thumbnail_size Ukuran resolusi gambar thumbnail yang ditampilkan.
    filter_status Untuk menampikan status Completed disebelah kiri atas.
    status Sebagai filter Completed, Delay, Ongoing.
    type Sebagai filter TV, ONA, OVA, Bluray, BD, Special.
    sub Sebagai filter Sub, Dub, Raw.

Comments