TOP

2020年9月14日 星期一

[Blogger] 文章內容折疊功能

問題:

 Blogger 文章加入可收合 (折疊某段內容的按鈕,參考網上範例(Blogger 展開及收合文章)可簡單達到,但對於多個折疊內容,需多份相似的程式碼並修改對應的變數名稱,折疊內容愈多修改量愈大,每篇使用折疊功能的文章都要類似的修改。重覆代表程式碼有改善空間,站在軟體工程師的角度希望能簡化使用的流程。因此,我在這兒設計一個使用 <div> 包圍後即能指定折疊內容的方法:

 <div class="FoldBlk"> 區塊包圍折疊內容,於區塊前動態產生按鈕,由按鈕執行 toggle 動作。折疊內容只要透過指定 <div> 即可,不需再執行額外的動作。


範例:

按線色按鈕可收合/展開下面的圖片:




此處修改 CSS 樣式來改變預設的 button 樣式:

<style>

.FoldBtn

{

 background:#507840;

}

.FoldBlk

{

    background:#000000;

}

</style>

 

為每張圖加上 <div class="FoldBlk"> </div>

<div class="FoldBlk" data-desc="萬里 - 野柳">

</div>

 

<div class="FoldBlk" data-desc="綠島 - 朝日溫泉" style="display: none;">

</div>

 

<div class="FoldBlk" data-desc="綠島 - 海中步道">

</div>

 

 

流程:

[1]  </head> 前加入 initFoldBlk 的實作:

initFoldBlk 動作為:

<1> 列舉類別為 FoldBlk  <div>,並在每個 <div> 前建立類別為 FoldBtn  <button>

<2> 註冊 FoldBtn  click 函數,其動作為:找此按鈕對應的 <div>,對它進行 toggle

<3> 此處下方的 <style> 指定了 FoldBlk FoldBtn 預設的 style

<!-- Ankas(收合按鈕#1): begin -->

   <script src='https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js'/>

    <script type='text/javascript'>

     //<![CDATA[

    function initFoldBlk () {

        var strInfo;

        var $btn;

  

        function getDesc (d, nextState = false) {

            var expandTag = "[]";

            var shrinkTag = "[]";

            var separator = " ";

            var strTag = "";            


            strInfo = d.data ("desc");        // get description from 'data-desc' attr

            if (!strInfo) {

                strInfo = "";        // No description

            }

 

            var style = d.css('display');

            if (nextState) {

                strTag = (style == 'none') ? shrinkTag : expandTag;

            } else {

                strTag = (style == 'none') ? expandTag : shrinkTag;

            }

 strInfo = strInfo + separator + strTag;

 

            return strInfo;

        }

 

 

        $div = $(".FoldBlk");

        $div.each (function () {

            var d = $(this);

            strInfo = getDesc (d);

            $btn = $("<button class='FoldBtn'>" + strInfo + "</button>");

            //$btn = $("<input type='button' class='FoldBtn' value=" + strInfo + ">");

            $btn.insertBefore(d);

        });

 

        $(".FoldBtn").click(function() {

            var $clicked = $(this); 

            var $div = $clicked.next();

 

            strInfo = getDesc ($div, true);

            $(this).text (strInfo);

 

            $div.slideToggle();

        }); 

    }

 

    //]]>

    </script>   

    

    <style>

    .FoldBtn

    {

       width: 100%;

       margin:0px;

       padding:2px;

       text-align:right;

       background:#E8D0A0;

       border:solid 1px #000000;

       outline:none;        // Remove focus around button

    }

    .FoldBlk

    {

        margin:0px;

        padding:3px;

        background:#333333;

        border:solid 1px #000000;

        height:auto;

    }

    </style>

<!-- Ankas(收合按鈕#1): end -->

 

 

[2] 在載入文章後後呼叫 initFoldBlk()

在範本 HTML 中搜尋 <b:include cond='data:top.showPlusOne' name='googlePlusBootstrap'/> initFoldBlk 置於其上方

<!-- Ankas(收合按鈕#2): begin -->     

      <script type='text/javascript'>

        initFoldBlk();

      </script>

<!-- Ankas(收合按鈕#2): end -->

 PS: 上面的呼叫也可在每一篇使用 .FoldBlk 的文章開頭程式嗎如下:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script>

$(document).ready(function(){

initFoldBlk();

});

</script>

但這麼做的缺點是每個使用到的文章都要加上面程式碼不夠簡潔因此放在範本的 HTML 中呼叫是較好的做法。

 

 

[3] 指定要折疊的內容

對要加入收合按鈕的內容加入下面程式碼:

<div class="FoldBlk" data-desc="hello2" style="display: none;">

要收合的內容

</div>

o   data-desc 指定顯示於收合按鈕的文字

o   style="display: none;" 指定預設隱藏該段內容(視是否預設疊合來加入)

 

 

[4] 效果:

右邊文字:

+:代表可展開

-:代表可收合

   

結語/心得:

 

[1] Online resource:

jQuery API reference

http://jsfiddle.net/: 線上編寫 JS/jQuery 程式進行快速測試

 

[2] jQuery APIs here:

data ("desc")

get attribute: data-desc="xxx"

css('display')

get attribute: style="display: none;"

$btn = $("<button class='FoldBtn'>"test"</button>");

create new element

$btn.insertBefore($div)

insert element $btn before $div

$div = $clicked.next();

get next element from $clicked

$(this).text (strInfo);

write text to $(this)

$div.slideToggle();

toggle $div

$div.show(300)/hide(300)

show/hide $div

 

 

沒有留言:

張貼留言