Labels

[Blogger] Nâng cấp Blogger Layout, Default Widget và Skin lên phiên bản mới


Vừa qua Google có tung ra gói theme blogger mới khá đẹp mắt với chức năng tùy chỉnh cao hơn. Tuy nhiên với hầu hết các template blogger cũ bạn phải tiến hành cập nhật thủ công. Bài viết này sẽ hướng dẫn các bạn cách nâng cấp Blogger Layout, Default Widget và Skin lên phiên bản mới để được hỗ trợ CSS Script và Webkit mới nhất

Giao diện cũ

Giao diện mới
Với giao diện widget mới này bạn có thể dễ dàng ẩn đi 1 widget nào đó bằng 1 cú click chuột, điều đó khá phức tạp khi muốn ẩn/xóa widget với giao diện cũ

Một số lợi ích khi nâng cấp
  • Bố cục ổn định hơn và thêm chức năng mới
  • Tất cả widget mới nhất sẽ tương thích với cập nhật
  • Bạn có thể dễ dàng tuỳ chỉnh chủ đề blogger mà không bị bỡ ngỡ với giao diện mới
  • Cách bố trí blogger mới và thiết kế widget mặc định trông bắt mắt hơn.
Trước tiên bạn hãy backup lại template để tránh lỗi đáng tiếc xảy ra nhè. Để nâng cấp bạn tiến hành làm như sau

1. Nâng cấp bố cục lên Version 3

Như thường lệ bạn đăng nhập trang quản trị vào phần chỉnh sửa HTML

Thêm thuộc tính b:layoutsVersion='3' vào trong thẻ mở<html Sau khi thêm sẽ được kết quả gần giống như sau

<html b:version='2' class='v2' b:layoutsVersion='3' expr:dir='data:blog.languageDirection' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>

2. Nâng cấp widget lên Version 2

Tương tự như phần 1, bạn tiếp tục thêm thuộc tính b:defaultwidgetversion='2' vào trong thẻ mở<html Sau khi thêm sẽ được kết quả như sau

<html b:version='2' class='v2' b:layoutsVersion='3' b:defaultwidgetversion='2' expr:dir='data:blog.languageDirection' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>

Bạn không cần quá quan tâm đến vị trí đặt thuộc tính, chỉ cần lưu mẫu lại và f5 trang thì blogger sẽ tự đặt nó đúng vị trí nó thuộc về.

Tiếp theo bạn dán toàn bộ đoạn code sau vào sau thẻ đóng ]]></b:skin> hoặc
</b:template-skin>

<b:defaultmarkups>
      <b:defaultmarkup type='Common'>
        <b:includable id='responsiveImage' var='settings'>
          <b:comment>Add in the high-res thumb for youtube images.</b:comment>
          <b:if cond='not data:settings.image.isYoutube'>
            <b:include data='settings' name='super.responsiveImage'/>
          <b:else/>
            <b:with value='resizeImage(data:post.featuredImage.youtubeMaxResDefaultUrl, 1152, &quot;4:3&quot;)' var='highRes'>
              <b:include data='{                                  image: data:settings.image,                                  imageSizes: [320,490],                                  sourceSizes: &quot;(max-width: 640px) 100vw, (max-width: 1024px) 576px, 490px&quot;,                                  enhancedSourceset: data:highRes                                }' name='super.responsiveImage'/>
            </b:with>
          </b:if>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='BlogSearch'>
        <b:includable id='searchSubmit'>
          <b:if cond='data:widget.sectionId == &quot;search_top&quot;'>
            <label>
              <input type='submit'/>
              <b:include data='{ iconClass: &quot;touch-icon search-icon&quot; }' name='searchIcon'/>
            </label>
          <b:else/>
            <b:include name='super.searchSubmit'/>
          </b:if>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='AdSense,Blog'>
        <b:includable id='defaultAdUnit'>
          <!-- Clear out style (need non-empty string) -->
          <b:with value='&quot;/* Done in css. */&quot;' var='style'>
            <b:include name='super.defaultAdUnit'/>
          </b:with>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='Blog,FeaturedPost,PopularPosts'>
        <b:includable id='sharingButtonContent'>
          <b:message name='messages.share'/>
        </b:includable>
        <b:includable id='postLabels'>
          <b:include cond='data:view.isSingleItem and data:widget.type == &quot;Blog&quot;' name='super.postLabels'/>
        </b:includable>
        <b:includable id='headerByline'>
          <b:if cond='data:view.isSingleItem and data:widget.type == &quot;Blog&quot;'>
            <b:include name='super.headerByline'/>
          <b:else/>
            <b:include data='{ items: [&quot;author&quot;, &quot;timestamp&quot;] }' name='headerBylineOverride'/>
          </b:if>
        </b:includable>
        <b:includable id='footerBylines'>
          <b:if cond='data:view.isSingleItem and data:widget.type == &quot;Blog&quot;'>
            <b:include name='super.footerBylines'/>
          <b:else/>
            <b:include data='{ items: [[&quot;share&quot;, &quot;comments&quot;]] }' name='footerBylinesOverride'/>
          </b:if>
        </b:includable>
        <b:includable id='emailPostIcon'>
          <!-- Replace icon with text -->
          <span class='byline'>
            <a class='flat-button' expr:href='data:post.emailPostUrl'><data:messages.emailPost/></a>
          </span>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='Blog'>
        <b:includable id='main'>
          <b:if cond='not data:posts.any'>
            <div class='no-posts'>
              <b:eval expr='data:view.isSearch ? data:messages.noResultsFound : data:messages.theresNothingHere'/>
            </div>
          </b:if>

          <!-- Display title on homepage -->
          <b:if cond='data:posts.any and data:view.isHomepage'>
            <h3 class='title'><data:messages.latestPosts/></h3>
          </b:if>
          <!-- Filter out the featured post, but only on the homepage. -->
          <b:with value='(data:widgets.FeaturedPost filter w =&gt; w.sectionId == &quot;page_body&quot;) map (w =&gt; w.postId)' var='featuredPostIds'>
            <b:with value='data:view.isHomepage ? data:posts filter (post =&gt; post.id not in data:featuredPostIds) : data:posts' var='posts'>
              <b:include name='super.main'/>
            </b:with>
          </b:with>
        </b:includable>
        <b:includable id='commentFormIframeSrc' var='post'>
          <b:with value='data:template.isAlternateRendering ? (&quot;&amp;skinvariant=&quot; + data:template.variant) : &quot;&quot;' var='variantParam'>
            <a expr:href='data:post.commentFormIframeSrc + &quot;&amp;skin=soho&quot; + data:variantParam' id='comment-editor-src'/>
          </b:with>
        </b:includable>
        <b:includable id='commentForm' var='post'>
          <b:with value='&quot;90px&quot;' var='cmtIframeInitialHeight'>
            <b:include data='post' name='super.commentForm'/>
          </b:with>
        </b:includable>
        <b:includable id='threadedCommentForm' var='post'>
          <b:with value='&quot;90px&quot;' var='cmtIframeInitialHeight'>
            <b:include data='post' name='super.threadedCommentForm'/>
          </b:with>
        </b:includable>
        <b:includable id='postCommentsAndAd' var='post'>
          <!-- Always render inline ad inside container -->
          <div class='post-outer-container'>
            <div class='post-outer'>
              <b:include data='post' name='post'/>
            </div>
            <b:include cond='data:view.isSingleItem' data='post' name='commentPicker'/>
            <b:include cond='data:post.includeAd and data:post.adNumber lt (data:view.isHomepage ? 2 : 3)' data='post' name='inlineAd'/>
          </div>
        </b:includable>
        <b:includable id='post' var='post'>
          <b:if cond='data:view.isSingleItem'>
            <div class='post-sidebar'>
              <b:if cond='data:widgets.Blog.first.allBylineItems.share and data:post.shareUrl'>
                <div class='post-sidebar-item post-share-buttons'>
                  <b:with value='data:widget.instanceId + &quot;-&quot; + (data:regionName ?: &quot;byline&quot;) + &quot;-&quot; + data:post.id' var='sharingId'>
                    <b:include data='{                                                              sharingId: data:sharingId,                                                              originalUrl: data:post.url,                                                              shareUrl: data:post.shareUrl,                                                              platforms: data:blog.sharing.platforms,                                                            }' name='sharingButtons'/>
                  </b:with>
                </div>
              </b:if>
              <b:if cond='data:widgets.Blog.first.allBylineItems.labels and data:post.labels'>
                <div class='post-sidebar-item post-sidebar-labels'>
                  <div><data:messages.labels/></div>
                  <ul>
                    <b:loop index='i' values='data:post.labels' var='label'>
                      <li><a expr:href='data:label.url' rel='tag'><data:label.name/></a></li>
                    </b:loop>
                  </ul>
                </div>
              </b:if>
            </div>
          </b:if>
          <div class='post'>
            <b:class cond='data:view.isMultipleItems and data:post.featuredImage' name='has-featured-image'/>
            <b:class cond='data:view.isMultipleItems and not data:post.featuredImage' name='no-featured-image'/>
            <b:include data='post' name='postMeta'/>
            <b:if cond='data:view.isSingleItem'>
              <b:include name='headerByline'/>
              <b:include data='post' name='postTitle'/>
              <div class='post-body-container'>
                <b:include data='post' name='postBody'/>
              </div>
            <b:else/>
              <b:if cond='data:post.featuredImage'>
                <div class='snippet-thumbnail'>
                  <a b:whitespace='remove' expr:href='data:post.url'>
                    <b:comment>Max width is 576, so max size @ 2x is 1152.</b:comment>
                    <b:include data='{                                        image: data:post.featuredImage,                                        imageSizes: [320,490,576,1152],                                        sourceSizes: &quot;(max-width: 576px) 100vw, (max-width: 1024px) 576px, 490px&quot;                                      }' name='responsiveImage'/>
                  </a>
                  <b:include name='headerByline'/>
                </div>
              <b:else/>
                <b:include name='headerByline'/>
              </b:if>
              <b:include data='post' name='postTitle'/>
            </b:if>
            <b:include data='post' name='postFooter'/>
          </div>
        </b:includable>
        <b:includable id='feedLinks'>
          <!-- Don't render -->
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='BlogArchive'>
        <b:includable id='main' var='this'>
          <details class='collapsible extendable'>
            <b:attr cond='data:view.isArchive' name='open' value='open'/>
            <b:with value='true' var='renderAsDetails'>
            <b:with value='data:messages.archive' var='defaultTitle'>
              <b:include name='super.main'/>
            </b:with>
            </b:with>
          </details>
        </b:includable>
        <b:includable id='flat'>
          <b:include data='{                               buttonClass: &quot;flat-button&quot;,                               items: data:this.data,                               itemSet: &quot;data&quot;,                               itemsMarkup: &quot;super.flat&quot;                             }' name='extendableItems'/>
        </b:includable>
        <b:includable id='hierarchy'>
          <b:include data='{                               buttonClass: &quot;flat-button&quot;,                               limit: 1,                               items: data:this.data,                               itemSet: &quot;data&quot;,                               itemsMarkup: &quot;super.hierarchy&quot;                             }' name='extendableItems'/>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='FeaturedPost'>
        <b:includable id='main'>
          <b:with value='data:messages.featured' var='defaultTitle'>
            <b:include name='super.main'/>
          </b:with>
        </b:includable>
        <b:includable id='snippetedPostContent'>
          <b:with value='data:postDisplay.showFeaturedImage and data:post.featuredImage' var='hasImage'>
            <div class='post-content'>
              <b:class cond='data:hasImage' name='has-featured-image'/>
              <b:class cond='not data:hasImage' name='no-featured-image'/>

              <!-- Change the order and add a snippet container -->
              <b:include cond='data:hasImage' data='post' name='snippetedPostThumbnail'/>
              <div class='post-text-container'>
                <b:include name='headerByline'/>
                <b:include cond='data:this.postDisplay.showTitle' name='snippetedPostTitle'/>
                <b:with value='&quot;featured-post&quot;' var='snippetPrefix'>
                  <b:include cond='data:this.postDisplay.showSnippet' data='post' name='postSnippet'/>
                </b:with>
                <div class='post-footer'>
                  <b:include name='footerBylines'/>
                  <!-- TODO(sarnesjo): Use the postJumpLink call (in case it's been customized). -->
                  <a class='jump-link flat-button' expr:href='data:post.url'><data:messages.readMore/></a>
                </div>
              </div>
            </div>
          </b:with>
        </b:includable>
        <b:includable id='snippetedPostByline' var='post'>
          <b:include name='headerByline'/>
        </b:includable>
        <b:includable id='snippetedPostThumbnail'>
          <b:include data='{image: data:featuredImage, maxSize: 954, selector: &quot;.hero-thumb&quot;}' name='responsiveImageStyle'/>
          <a class='thumb-link' expr:href='data:post.url'><div class='thumb hero-thumb'/></a>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='Header'>
        <b:includable id='image'>
          <b:include name='super.image'/>
          <!-- If we are replacing the title, force it to render anyway, and it'll be hidden in CSS. -->
          <b:include cond='data:this.imagePlacement == &quot;REPLACE&quot;' name='title'/>
        </b:includable>
        <b:includable id='title'>
          <div>
            <b:class cond='data:this.imagePlacement == &quot;REPLACE&quot;' name='replaced'/>
            <b:include name='super.title'/>
          </div>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='Label'>
        <b:includable id='main' var='this'>
          <details class='collapsible extendable'>
            <b:attr cond='data:view.isLabelSearch' name='open' value='open'/>
            <b:with value='true' var='renderAsDetails'>
            <b:with value='data:messages.labels' var='defaultTitle'>
              <b:include name='super.main'/>
            </b:with>
            </b:with>
          </details>
        </b:includable>
        <b:includable id='list'>
          <b:include data='{                               buttonClass: &quot;flat-button&quot;,                               items: data:this.labels,                               itemSet: &quot;labels&quot;,                               itemsMarkup: &quot;super.list&quot;                             }' name='extendableItems'/>
        </b:includable>
        <b:includable id='cloud'>
          <b:include data='{                               buttonClass: &quot;flat-button&quot;,                               items: data:this.labels,                               itemSet: &quot;labels&quot;,                               itemsMarkup: &quot;super.cloud&quot;                             }' name='extendableItems'/>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='PageList'>
        <b:includable id='content'>
          <div class='widget-content'>
            <b:if cond='data:widget.sectionId == &quot;page_list_top&quot;'>
              <b:include name='overflowablePageList'/>
            <b:else/>
              <b:include name='pageList'/>
            </b:if>
          </div>
        </b:includable>
        <b:includable id='overflowButton'>
          <a><data:messages.moreEllipsis/></a>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='PopularPosts'>
        <b:includable id='main'>
          <!-- Default the title to 'Popular posts'. -->
          <b:with value='data:messages.popularPosts' var='defaultTitle'>
            <b:include name='super.main'/>
          </b:with>
        </b:includable>
        <b:includable id='snippetedPostContent'>
          <div class='post'>
            <b:class cond='data:post.featuredImage' name='has-featured-image'/>
            <b:class cond='not data:post.featuredImage' name='no-featured-image'/>
            <b:if cond='data:post.featuredImage'>
              <div class='snippet-thumbnail'>
                <a b:whitespace='remove' expr:href='data:post.url'>
                  <b:include data='{                                      image: data:post.featuredImage,                                      imageSizes: [330,660,1320],                                      sourceSizes: &quot;(max-width: 660px) 100vw, 660px&quot;                                    }' name='responsiveImage'/>
                </a>
                <b:include name='headerByline'/>
              </div>
            <b:else/>
              <b:include name='headerByline'/>
            </b:if>
            <b:include cond='data:this.postDisplay.showTitle' name='snippetedPostTitle'/>
            <div class='post-footer'>
              <b:include name='footerBylines'/>
            </div>
          </div>
        </b:includable>
      </b:defaultmarkup>
      <b:defaultmarkup type='Profile'>
        <b:includable id='main' var='this'>
          <!-- Remove widget title -->
          <b:include name='content'/>
        </b:includable>
        <b:includable id='teamProfileLink'>
          <!-- Remove background image, add "Visit profile" message -->
          <a class='profile-link g-profile' expr:href='data:userUrl'>
            <b:include name='profileImage'/>
            <div class='profile-name-wrapper'>
              <div class='profile-name'><data:display-name/></div>
              <div class='visit-profile'><data:messages.visitProfile/></div>
            </div>
          </a>
        </b:includable>
        <b:includable id='userProfileLink'>
          <!-- Remove background image -->
          <a class='profile-link g-profile' expr:href='data:userUrl' rel='author'>
            <data:displayname/>
          </a>
        </b:includable>
        <b:includable id='viewProfileLink'>
          <!-- Change message to "Visit profile" -->
          <a class='profile-link' expr:href='data:userUrl' rel='author'>
            <data:messages.visitProfile/>
          </a>
        </b:includable>
        <b:includable id='defaultProfileImage'>
          <div class='default-avatar-wrapper'>
            <b:include data='{ iconClass: &quot;avatar-icon&quot; }' name='defaultAvatarIcon'/>
          </div>
        </b:includable>
      </b:defaultmarkup>
    </b:defaultmarkups>

3. Nâng cấp b:skin

Thay thế <b:skin><![CDATA[/* thành <b:skin version='1.3.0'><![CDATA[/*

Cuối cùng lưu mẫu lại để xem thay đổi

4. Fix lỗi

Bạn không nên nâng cấp giao diện của Popular Posts vì cấu trúc khác nhau có thể làm vỡ bố cục của trang web, khi đã nâng cấp thành công bạn hãy thay thế đoạn code Popular Posts mới bằng code Popular Posts cũ đã backup từ trước

Khi thêm 1 widget mới có thể bị lỗi tiêu đề thẻ h2. Bạn hãy tìm đến đoạn code của widget đó và thay thế <b:includable id='main'>...</b:includable> thành

<b:includable id='main'>
    <!-- only display title if it's non-empty -->
    <b:if cond='data:title != &quot;&quot;'>
        <h2 class='title'><data:title/></h2>
    </b:if>
    <div class='widget-content'>
        <data:content/>
    </div>
    <b:include name='quickedit' />
</b:includable>

Thì widget sẽ được áp dụng đúng css

Good Luck