Hướng dẫn thiết kế blogspot căn bản - Tạo nút lưu bài viết

Hướng dẫn chèn nút lưu bài viết vào các bài đăng hiển thị tại nhóm trang chỉ mục để lưu nhanh bài viết blogspot

Xin chào các bạn, rất vui vì gặp lại các bạn trong một bài viết về chủ đề hướng dẫn thiết kế blogspot căn bản, bài viết hôm nay mình lại tiếp tục chia sẻ về cách tạo nút, vâng nút là button hành động nha các bạn, và button ở đây sử dụng lưu bài viết.

Qua hai bài hướng dẫn tạo nút chia sẻ và nút đăng nhận xét, trong bài này bạn có thể tạo thêm nút lưu bài viết đặt nó cùng với hai nút kia tại các post thuộc nhóm trang chỉ mục ví dụ tại trang chủ blog chẳng hạn.

Khi bạn chèn nút lưu bài viết có tác dụng tạo hành động click dạng toggle nhấp chọn và bỏ chọn ví dụ click lưu bài viết, click tiếp bỏ lưu bài viết. Ngoài ra bạn cũng cần tạo một element ẩn lưu trữ storage những bài đã được lưu.

Hướng dẫn thiết kế blogspot căn bản - Tạo nút lưu bài viết
Hiển thị nút lưu nhanh bài viết tại mỗi post có tác dụng click lưu bài viết đó

Trước khi tiếp tục mình giới thiệu sơ qua một chút về trang label, nếu một bài đăng đã được xuất bản có chứa label (nhãn), bạn sẽ có một trang label riêng về nhãn đó. Ví dụ URL trang label https://www.thietkeblogspot.com/search/label/blogger-tips sẽ lưu các bài đăng có nhãn "blogger-tips".

Đọc thêm: Tầm quan trọng của jumb break và số bài đăng tối đa hiển thị tại trang chỉ mục

Một điểm đặc biệt nếu URL trang label mà không lưu các bài đăng nào có nhãn liên quan thì trang sẽ trở thành một trang trống chứ lại không báo báo lỗi 404 nha các bạn. Cụ thể, nếu bạn truy cập trang từ URL https://www.thietkeblogspot.com/search/label/archive nếu không có các bài đăng nào có nhãn "archive" thì vùng hiển thị các bài đăng có nhãn (trong tiện ích Bài đăng trên Blog) sẽ bị trống tức không có bài đăng nào.

Tận dụng trang trống từ liên kết URL https://www.thietkeblogspot.com/search/label/archive, bạn có thể tạo ra một được một nhãn "archive" nhưng nó không nằm trong bất kỳ bài đăng nào, trang này bạn sử dụng để lưu các bài đã lưu.

Lại tiếp tục bàn về vòng lặp của các bài đăng hiển thị tại trang này, vì trong vòng lặp của post nên chúng được sắp xếp các phần tử element giống nhau, ví dụ có dạng

<div class="widget Blog" id="Blog1">
  <div class="blog-posts">
    <article class="post">
    ...
    </article>
    <article class="post">
    ...
    </article>
  </div>
</div>

Trong đó mỗi element "article" là một post với class chính là "post", và để lưu mỗi post chính đó bạn chỉ cần đặt nút lưu bài viết trong đó để lưu toàn bộ nội dung bên trong post này, chẳng hạn sẽ đặt nút bài viết trong class post-meta

<article class="post">
  <div class="post-thumb"></div>
  <div class="post-title"></div>
  <div class="post-meta">
    <span aria-label="Lưu để đọc sau" aria-pressed="false" class="save-this-article" role="button" tabindex="0" title="Lưu để đọc sau"></span>
  </div>
  <div class="post-snippets"></div>
</article>

Hướng dẫn tạo nút lưu bài viết

Bước 1: chèn nút lưu vào vị trí hiển thị

<b:if cond='data:widgets.Blog.first.allBylineItems.icons'>
  <span aria-label='Lưu để đọc sau' aria-pressed='false' class='archive-icon has-svg-icon save-this-article flex-center' expr:data-article-id='data:post.id' role='button' tabindex='0' title='Lưu để đọc sau'></span>
</b:if>

Bước 2: Tìm các class chính của post ví dụ như trên thêm class "data-article"

<article class="post data-article">
  <div class="post-thumb"></div>
  <div class="post-title"></div>
  <div class="post-meta">
    <b:if cond='data:widgets.Blog.first.allBylineItems.icons'>
      <span aria-label='Lưu để đọc sau' aria-pressed='false' class='archive-icon has-svg-icon save-this-article flex-center' expr:data-article-id='data:post.id' role='button' tabindex='0' title='Lưu để đọc sau'>  </span>
    </b:if>
  </div>
  <div class="post-snippets"></div>
</article>

Bước 3: Chèn element ẩn để lưu storage đặt nó trước thẻ đóng </body>

<b:tag class='save-all-posts' cond='data:widgets.Blog.first.allBylineItems.icons' data-items-added='0' name='div'/>

Bước 4: Chèn code script trước thẻ đóng </body>

<b:if cond='data:widgets.Blog.first.allBylineItems.icons'>
  <script>
    var pageName="data:blog.pageName"
    //<![CDATA[
    var pageUrl='/search/label/archive',pageItems=20
    function save_this_article(e){
      e.preventDefault()
      var saved=$('.save-all-posts'),$this=$(this).parents('.data-article'),id=$(this).attr('data-article-id'),
      added=Number($(saved).attr('data-items-added')),
      str='<article class="post data-article">'+$this.html()+'</article>'
      if(added>=pageItems){
        var confirm='<div class="modal--confirm alert--dialog"><div class="modal--dialog"><div class="_3em"></div><div class="modal--content"><div class="modal--header"><div class="_mht">Vượt quá giới hạn số bài đã lưu</div><div class="_mhc modal--icon has-svg-icon modal--close" role="button" tabindex="0"></div></div><div class="modal--body"><div><p>Bạn chỉ lưu được tối đa <strong style="color:#b20000">'+pageItems+'</strong> bài viết. Bạn cần bỏ lưu bài cũ để tiếp tục lưu bài này. Bạn muốn đi đến trang tin bài đã lưu?</p></div></div><div class="modal--footer"><button class="modal--close" type="button">Đóng</button><button class="primary" type="button">Đồng ý</button></div></div><div class="_3em"></div></div></div>'
        $(confirm).appendTo('body')
        $('.modal--confirm.alert--dialog').fadeIn('slow',function(){$(this).addClass('show')})
        $('.modal--close').click(function(){
          $('.modal--confirm.alert--dialog').removeClass('show')
          setTimeout(function(){$('.modal--confirm.alert--dialog').remove()},200)
        })         
        $('.modal--footer button.primary').click(function(){location.href=pageUrl})
      }else{
        $(this).toggleClass('saved')
        if($(this).hasClass('saved')){
          $(saved).attr('data-items-added',added+1)
          $(str).appendTo(saved)
          $(this).attr({'aria-label':'Xóa khỏi phần tin bài đã lưu','aria-pressed':'true','title':'Xóa khỏi phần tin bài đã lưu'})
          $(saved).find('article[data-article-id='+id+'] .save-this-article').attr({'aria-label':'Xóa khỏi phần tin bài đã lưu','aria-pressed':'true','title':'Xóa khỏi phần tin bài đã lưu'}).addClass('saved')
        }else{
          $(saved).attr('data-items-added',added-1)
          $(saved).find('article[data-article-id='+id+']').remove()
          $(this).attr({'aria-label':'Lưu để đọc sau','aria-pressed':'false','title':'Lưu để đọc sau'})
        }
      }
      var item_added=$(saved).html()
      localStorage.setItem('saved_data',item_added)
    }
    function save_all_posts(){
      var saved_data='',saved=$('.save-all-posts'),arr=[]
      if(saved_data=localStorage.getItem('saved_data')){
        $(saved).html(saved_data)
        var item=$('.save-all-posts>article')
        for(var i=0;i<item.length;i++)arr.push($(item[i]).attr('data-article-id'))
        $(saved).attr('data-items-added',arr.length)
        $('.save-this-article').each(function(index,value){
          var id=$(value).parents('.data-article').attr('data-article-id')
          if(arr.includes(id))$(value).addClass('saved').attr({'aria-label':'Xóa khỏi phần tin bài đã lưu','aria-pressed':'true','title':'Xóa khỏi phần tin bài đã lưu'})
        })
        if(pageName=='archive')$('.blog-posts').append(saved_data)
      }else{
        if(pageName=='archive')$('.blog-posts').append('<p>Chưa có tin nào được lưu</p>')
      }
    }
    window.addEventListener('load',function(){
      save_all_posts()
      $(document).off('click','.save-this-article',save_this_article).on('click','.save-this-article',save_this_article)
    })
  //]]></script>
</b:if>

Cài đặt pageItems bằng giới hạn tổng số bài đăng được phép lưu.

Tham khảo thêm: Cách thêm thuộc tính async hoặc defer vào thẻ script jquery.js

Bước 5: Chèn code css trước thẻ đóng </head>

<b:if cond='data:widgets.Blog.first.allBylineItems.icons'>
<b:tag name='style'>/* <![CDATA[ */
*{box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;text-rendering:geometricPrecision}
.save-all-posts{display:none}
.flex-center{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center;justify-content:center}
.archive-icon{width:30px;height:30px;border-radius:50%}
.archive-icon:hover,.archive-icon:focus,.archive-icon:active{background:rgba(60,64,67,0.08)}
.archive-icon:focus,.archive-icon:active{box-shadow:rgba(0, 132, 255, 0.5) 0px 0px 0px 2px}
.archive-icon:focus{outline:none!important}
.has-svg-icon:before{background-size:100%;content:"";display:inline-block;vertical-align:middle}
.archive-icon:before{width:15px;height:15px}
.archive-icon:not(.saved):before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24'%3E%3Cpath fill='%23757575' d='M17,18L12,15.82L7,18V5H17M17,3H7A2,2 0 0,0 5,5V21L12,18L19,21V5C19,3.89 18.1,3 17,3Z' /%3E%3C/svg%3E")}
.archive-icon.saved:before{background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24'%3E%3Cpath fill='%23007bc7' d='M17,3H7A2,2 0 0,0 5,5V21L12,18L19,21V5C19,3.89 18.1,3 17,3Z' /%3E%3C/svg%3E")}
.modals-dialog{box-shadow:0 1px 3px 0 rgba(60,64,67,0.302),0 4px 8px 3px rgba(60,64,67,0.149);-webkit-font-smoothing:antialiased;letter-spacing:.2px;-webkit-align-items:center;align-items:center;background-color:#202124;border:none;-webkit-border-radius:4px;border-radius:4px;bottom:0;-webkit-box-sizing:border-box;box-sizing:border-box;display:-webkit-box;display:-moz-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;left:0;margin:20px;max-width:640px;min-height:50px;padding:8px 15px;position:fixed;right:auto;text-align:left;top:auto;white-space:normal;z-index:10000}
.modals-dialog-content{display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;font-size:1rem;font-weight:400;color:#fff}
.modals-dialog-buttons{vertical-align:middle;margin-left:15px}
.modal--confirm{background-color:rgba(0, 0, 0, 0.5);position:fixed;right:0;top:0;bottom:0;left:0;z-index:5000;opacity:0;transition:opacity .15s cubic-bezier(0.4,0.0,0.2,1) .15s}
.modal--target{display:none}
.modal--confirm.show{transition:opacity .05s cubic-bezier(0.4,0.0,0.2,1);opacity:1}
.modal--dialog{-webkit-box-align:center;box-align:center;align-items:center;display:flex;-webkit-box-orient:vertical;box-orient:vertical;flex-direction:column;bottom:0;left:0;padding:0 5%;position:absolute;right:0;top:0;-webkit-transform:scale(0,0);-moz-transform:scale(0,0);-ms-transform:scale(0,0);-o-transform:scale(0,0);transform:scale(0,0);transform-origin:center center;-webkit-transition:all .3s;-moz-transition:all .3s;-ms-transition:all .3s;-o-transition:all .3s;transition:all .3s}
.modal--confirm.show .modal--dialog{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1)}
.modal--confirm form{margin:0}
.modal--content{background-color:#fff;-webkit-box-align:stretch;align-items:stretch;display:flex;-webkit-box-orient:vertical;flex-direction:column;transition:transform .225s cubic-bezier(0.0,0.0,0.2,1);position:relative;border-radius:3px;box-shadow:0 2px 26px rgba(0, 0, 0, .3), 0 0 0 1px rgba(0, 0, 0, .1);max-width:600px;overflow:hidden;flex-shrink:1;max-height:100%;font-family:Roboto,Arial,sans-serif;font-size:inherit;color:currentColor}
@media(min-width:551px){.modal--content{min-width:510px}}
@media(max-width:550px){.modal--content{width:100%}}
._3em{display:block;height:3em;flex-grow:1}
._cs{padding:10px 0 0 22px}
.modal--header{background-color:#f5f6f7;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;position:relative;padding:10px 12px;border-bottom:1px solid #e5e5e5;border-radius:3px 3px 0 0;color:currentColor;font-weight:bolder;line-height:normal}
.modal--header ._mht{margin-right:auto}
.modal--header ._mhc{margin-left:auto}
.modal--icon{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:4px;border:1px solid;border-color:transparent}
.modal--icon:hover,.modal--icon:focus{border-color:#2d2d2d}
.modal--icon:focus{outline:none!important}
.modal--icon:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='21px' tabindex='0' viewBox='0 0 24 24' width='21px'%3E%3Cpath fill='%23707070' d='M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z'%3E%3C/path%3E%3C/svg%3E");width:21px;height:21px}
.modal--content p:not(:last-child){margin-bottom:.5rem}
.modal--body{background:#fff;padding:12px;overflow:hidden;overflow-y:auto}
.modal--body>div{line-height:1.6rem}
.modal--body>div:not(:last-child)>p{margin-bottom:1rem}
.modal--body input[type="radio"]{margin:0 5px 0 0}
.modal--footer{background:#fff;margin:0 12px;padding:12px 0;border-top:1px solid #dddfe2;text-align:right}
.modal--footer button{position:relative;display:inline-block;min-width:50px;padding:0 8px;border:1px solid;white-space:nowrap;height:26px;line-height:26px;border-radius:2px;-webkit-font-smoothing:antialiased;font:600 14px Roboto,Arial,sans-serif;justify-content:center;text-align:center;text-shadow:none;vertical-align:middle;transition: 200ms cubic-bezier(.08,.52,.52,1) background-color, 200ms cubic-bezier(.08,.52,.52,1) box-shadow, 200ms cubic-bezier(.08,.52,.52,1) transform}
.modal--footer button:not(.primary){background-color:#f5f6f7;border-color:#ccd0d5;color:currentColor}
.modal--footer button[type="submit"],.modal--footer button.primary{background-color:#4267b2;border-color:#4267b2;color:#fff}
.modal--footer button+button{margin-left:5px}
.modal--footer button:hover,.modal--footer button:focus{outline:none}
@media(min-width:1025px){.archive-icon:hover,.modal--icon:hover,.modal--footer button:hover{cursor:pointer}}
/* ]]> */</b:tag>
</b:if>

Bước 6: Cài đặt hiển thị nút lưu bài viết.

Trong bố cục tiện ích Bài đăng trên Blog chọn chỉnh sửa tiện ích định cấu hình bài đăng trên Blog tích chọn mục Hiển thị Liên kết Bài qua Email rồi bấm Lưu tiện ích

Xem thêm các bài viết hướng dẫn thiết kế blogspot căn bản khác:

Back to Top