close

資訊科技越來越進步的現代,日常使用的系統與網頁只增不減。

大家應該都聽過食物掉地上的三秒原則,在資訊的UI界也有三秒原則 --- 網頁跑超過三秒通常使用者就會開始哀。

網頁沒反應的因素很多,除了本身的設計外,從電腦(硬體)到網路都有可能。

最害怕的是因為系統沒動作,使用者就拼命點按鈕。

動作 ( 網絡中稱為Request ) 沒送出都是小事,被大量送出而伺服器重複處理那才是大事!!!

(但對電商來說,使用者大量下訂單是一點問題都沒有 www 大誤)

所以這次來玩玩怎麼預防使用者手癢的 jQuery BlockUI~

 

中場就要先拉幕 - 介紹 jQuery BlockUI


  BlockUI 是一款基於 jQuery 的插件 ( Plugin )。如前面所述,主要目的是在傳輸或處理資料的過程中,避免使用者進行其他的動作。

  當觸發 BlockUI 事件時,會在指定的區域上建立一層遮罩,而不需要逐個欄位或元素去設定唯讀、禁用,並可自行設定遮罩外觀。

  以下逐步說明,如何替自己的頁面套用 BlockUI

 

建立 jQuery BlockUI


  載入 jQuery 及 BlockUI

  第一步先設定頁面載入 jQuery 及 BlockUI 資源,這裡要注意順序。

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!--以下兩行載入 jQuery 及 BlockUI-->
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="http://malsup.github.io/jquery.blockUI.js"></script>
    <style>
        .input_area
        {
            text-aligncenter;
        }
    </style>
</head>

  如果沒有載入 jQuery、或是 jQuery 未在 BlockUI 前載入,會在 DevTools 中收到錯誤 : jQuery is not defined 、 $ is not defined

  測試畫面建立

  上面步驟的兩個套件都設定完成後,建立測試的畫面如下 : 

<body>
    <div class="row info">
        <input type="text" name="userName" id="userName" placeholder="請輸入姓名">
        <select name="gender" id="gender">
            <option value="female"></option>
            <option value="male"></option>
        </select>
        <input type="button" value="測試" id="test">
    </div>
    <div class="row other">
        <textarea name="other" id="other" cols="30" rows="10" placeholder="請於此處輸入備註"></textarea>
    </div>
    <script>
        $(document).ready(function(){
            $('#test').on('click',function(){
                //寫產生遮罩的指令,後續的程式碼如未特別註明,則都是寫在此段
            });
        });
    </script>
</body>

  這裡設置一個簡單的模擬畫面,包含文字框、下拉選項及一個按鈕。另有一個在不同區塊 ( div ) 的備註欄位。

  可參考如下圖

  image

  後面的程式碼如未特別註明,則都是寫在按鈕的click事件中 ( 即綠色備註的位置 )

  預設的提示訊息

  BlockUI 官網中的說明其實挺詳細的,如果只是要建立一個預設簡單的遮罩,僅需要一行指令。

                $.blockUI();

  之後在畫面中輸入姓名、性別,再點擊按鈕。

  image

  是不是超簡單的!? 預設的文字跟樣式稱不上極美,但也算是簡潔大方。

  另外要注意,因為在 JavaScript 中大小寫相異時是會被視為不同的,所以如果大小寫錯了,就不會觸發遮罩囉!

  那因為這裡是要示範訊息顯示,並沒有設定 form 及 action。( 忘記了的人,請往 : 這裡 )

  所以在重整之前,遮罩會一直在頁面上,不會消失。

  可以不要是英文嗎?(自訂遮罩訊息)

  可是可是,我們使用者說他英文不好,能不能不要寫英文啊?

  很簡單,那就自訂顯示訊息吧!

                $.blockUI({
                    message:'網頁讀取中,請稍後...'
                });

  只需要在剛剛的 blockUI 函式中傳入一個物件,

  物件內含屬性 message ( 請注意大小寫 ),設定為欲顯示的文字即可~

  image

  訊息框可以花俏一點嗎~(自訂遮罩訊息樣式)

  雖然可以改文字,但看起來還是有點無聊~

  能不能弄個黑色背景、白色文字,最好還有個圓弧角配上半透明,這不是 帥 呆 了 嗎?

  ( 工程師跟美編只能一起以頭搶地 )

  難道不能用 BlockUI 了嗎? 當然能 !  

$.blockUI({
                    message: '自訂遮罩訊息樣式',
                    css: {
                        border: 'none',
                        padding: '20px',
                        opacity: .5,
                        '-webkit-border-radius': '40px',
                        backgroundColor: '#000',
                        color: '#fff'
                    }
                });

  前面我們在物件中設定了一個屬性 message 來調整文字內容,

  現在只需要再設定一個 css ( css設定這裡就不細說了 )

  image

  能不能不要黑黑的(自訂遮罩樣式)

  雖然中間遮罩訊息的部分改了,可是老闆說他今年的幸運色是橘色,遮罩的部分能不能不要黑黑的?

  那麼剛剛加了 css 屬性,現在再來加個 overlayCSS

                $.blockUI({
                    message: '自訂遮罩樣式',
                    overlayCSS: {
                        backgroundColor: '#fa8',
                        opacity: 0.4,
                        cursor: "default"
                    }
                });

  一樣指定 overlayCSS 所需的 CSS屬性物件

  image

  顏色及透明度,都可以在 overlayCSS 中自行調整

  增加標題及強調訊息內容(自訂遮罩訊息排版)

  老闆說,使用者每次都在問系統要跑多久,要把"請稍後"紅字放大給使用者看。

  而且有人想看標題重點,有人希望訊息能描述的詳細一些。

  只有一行文字不夠用,該怎麼辦~~~是不是又有什麼神奇的屬性可以設定?

  答案是 ... 沒有 ! 但我們可以直接設定在 message !

                $.blockUI({
                    message:'<div><h1 style="color:brown;">這是標題</h1>系統讀取中,<span style="color:red;font-size:20px;font-weight: 800;">請稍後</span></div>',
                    css:{
                        backgroundColor: 'lemonchiffon'
                    }
                });

  message 不光是可以撰寫文字,也可以寫 HTML 排版。

  (我的美感已經沒救了...大家看看就好,還是自行設計吧XD)

  image

  增加標題及強調訊息內容(自訂遮罩訊息排版)之2

  嗚嗚,結果美編發現可以自己設計後樂不可支,做了一個長達50行美美的遮罩設計...

  這就苦了工程師了...想改個屬性看個排版,都得眼睛脫窗,難道非得這樣互相傷害嗎?

  為了解決這個狀況,需要先做些小小的更動

  image

  將設計好的遮罩藏在畫面中某處,要記得設定 display : none ; 以免影響到原本的畫面

  接著將 blockUI 更改如下 : 

                $.blockUI({
                    message: $('#msg'), // 以 css 選擇器 找到妳要顯示的元素區塊
                    css:{
                        backgroundColor: 'lemonchiffon'
                    }
                });

  image

  這樣是不是簡單愉快多了 ? 後續要修改也很便利~

  太靜態了看起來像當掉!(遮罩訊息轉圈圈)

  出現了等待訊息,但畫面一直不動,讓使用者一度懷疑是不是當機了~

  要不像網頁的讀取效果 ?! 加一個滾動的圈圈如何~

  首先可以到 ajaxload.info 自行挑選顏色的樣式,產生自己想要的讀取效果

  將產生的 gif 下載至自己的專案資料夾中

  image

  在自己設計的遮罩訊息排版中,使用 img Tag 加入該圖示

$.blockUI({
                    message: '<div><img src="Pics/ajax-loader-red.gif" /> 處理中,請稍候...</div>'
                });

  image

  很簡單的就可以旋轉給使用者看了~

  猶抱琵琶半遮面,能不能只遮一半啊?(遮罩範圍控制)

  以上的 BlockUI ,在送出的時候都是一次遮蔽整個網頁畫面。

  只是有時因為系統流程的考量,或許會希望只有部分欄位(區塊)被遮蔽,

  這個時候就可以使用 BlockUI 的 block Method

  使用方法跟前面的 blockUI Method 幾無差別 ( 要注意這裡是 block )

  image

  所以再看看前面的頁面及HTML,基本上設計時就區分成兩個同層級的 div 區塊

  image

  如果今天希望點擊按鈕後,保留備註欄位是可以編輯的,等於只會遮蔽 info 的部分

  使用預設的設定

                $('.info').block();

  因為遮蔽的區塊比較小,所以看起來會怪怪的

  image

  跟 blockUI 一樣,其顏色、訊息、排版等,都可以自行設定  

                $('.info').block({ 
                    message: null,
                    overlayCSS: {
                        backgroundColor: '#fa8',
                        opacity: 0.2,
                        cursor: "default"
                    }
                 });

 image

  是不是很方便呀~

  

開了之後怎麼關 - jQuery BlockUI取消遮蔽


  開了那麼多個遮蔽之後,在心滿意足的同時

  下一個問題馬上就出現了 : 完美的遮蔽了瀏覽器的畫面,現在資料載完了,要怎麼打開呀~~~

  只需要一個取消魔法的咒語

  遮罩的關閉跟遮罩的開啟一樣簡單,只需要一個指令

                $.unblockUI();

  如果今天是使用 block 做部分遮蔽,解除也是一樣很簡單

  只需要呼叫 CSS選擇器.unblock() 即可

                $('.info').unblock();  

  兩者弄錯可是會出現錯誤的哦~

  可以定時解除嗎?

  一般來說會設定在資料讀取完畢、動作執行完成後關閉遮罩。

  但如果想要直接定時關閉,當然也沒問題~

  第一種是應用 setTimeout , 在時間到時執行 unblockUI 或 unblock

                $.blockUI({
                    message: '等待遮罩自動關閉'
                });
                setTimeout($.unblockUI2000);

  第二種則是直接在 blockUI 或 block 中設定參數 : timeout

                $.blockUI({
                    message: '等待遮罩自動關閉',
                    timeout: 3000
                });

  以上兩種寫法,達成的效果都是一樣的~

  讓使用者自己關遮罩

  有時基於某些考量,或許我們希望只要使用者明白了,就可以解除遮罩

  作法其實很簡單,先自訂一個遮罩訊息排版,其中包含關閉遮罩的按鈕

  image

  設定遮罩為開啟此訊息排版 ( 參考 自訂遮罩訊息排版之2 )

  另外增加按鈕事件,觸發後關閉遮罩

    <script>
        $(document).ready(function () {
            $('#test').on('click'function () {
                $.blockUI({
                    message: $('#check_area')
                });
            });
 
            // 關閉遮罩按鈕
            $('.close').on('click'function () {
                $.unblockUI();
            });
        });
    </script>

  image

其他


  每個單位的使用需求都不同,以下再列出幾個稍微進階的使用

  遮罩訊息更新

  模擬遮罩由 1 數至 3,先跟大家分享一個比較蠢的寫法

         $.blockUI({
                    message: 1
                });
 
                setTimeout(function(){
                    $.blockUI({
                        message: 2
                    });
                },1000);
 
                setTimeout(function(){
                    $.blockUI({
                        message: 3
                    });
                },2000);
 
                setTimeout(function(){
                    $.unblockUI();
                },3000);

  等於每過一秒,便執行一次 blockUI 事件來刷新 message,並在3秒時關閉遮罩

  這不用說也看得出缺點,一來是當時間為一分鐘時,會寫到死

  二來在刷新遮罩的過程中,一閃一閃的讓眼睛很吃不消

  所以來使用 setInterval 改寫如下

                // 遮罩由1開始顯示
                var count = 1;
                $.blockUI({ message: count });
                
                interval = setInterval(function () 
                            {
                                if (count >= 3) {
                                    $.unblockUI();
                                    clearInterval(interval);
                                } else {
                                    count++;
                                    $.blockUI({ message: countfadeIn: 0 });
                                }
                            }, 1000);

  每秒執行 blockUI , 當計數到3時,即關閉遮罩與計時動作。

  需要特別注意,這裡的關鍵其實在於 fadeIn : 0 這個參數 ( 設置為零表示禁用 )

  fadeIn 為淡出淡入的效果,也就是說第一種愚蠢的寫法如果設定 fadeIn : 0 ,在數字切換時亦不會閃動

  雖然可達成一樣的效果,為了可讀性及維護性,還是使用 setInterval 吧~

  Ajax讀取時使用BlockUI

  乍看之下很簡單,這不一下就完成了?

                $.blockUI();
 
                $.ajax({
                    url: myUrl,
                    contentType: 'application/json',
                    type: "POST",
                    cache: false,
                    dataType: "json",
                    success: function (data) {
                        alert(data);
                    },
                    error: function (ex) {
                        console.log(ex.responseText);
                    }
                });
 
                $.unblockUI();

  結果這不也發現,遮罩也一下就消失了~ 

  這是因為前端運行的規則,一起來看看下圖

  image

  所以在Ajax還沒有跑完,(瞬間)遮罩就被關閉了。

  這樣到底該怎麼辦? 眼尖的人應該發現上面多了一個關鍵字,沒錯,就是 beforeSend

  將 blockUI 事件寫在 beforeSend , unblockUI 事件寫在 complete

                $.ajax({
                    beforeSend: function () {
                        $.blockUI();
                    },
                    url: myUrl,
                    contentType: 'application/json',
                    type: "POST",
                    cache: false,
                    dataType: "json",
                    success: function (data) {
                        alert(data);
                    },
                    error: function (ex) {
                        console.log(ex.responseText);
                    },
                    complete: function(XMLHttpRequest, status) { 
                        $.unblockUI();
                    }
                });

  但一個系統中使用 Ajax 的次數有可能極為頻繁,這樣寫在維護也不是很方便

  這時也可以考慮使用 $(document).ajaxStart 、ajaxStop

  原本 Ajax 的部分簡單化

                $.ajax({
                    url: myUrl,
                    contentType: 'application/json',
                    type: "POST",
                    cache: false,
                    dataType: "json",
                    success: function (data) {
                        alert(data);
                    },
                    error: function (ex) {
                        console.log(ex.responseText);
                    }
                });

  而另外在 $(document).ready 中加入事件

    <script>
        $(document).ready(function () {
            $(document).ajaxStart(function () {
                $.blockUI();
            });
            $(document).ajaxStop(function () {
                $.unblockUI();
            });
 
            $('#test').on('click'function () {
                //寫產生遮罩的指令,為剛剛的 Ajax
            });
        });
    </script>

  更加簡潔的就可以產生跟原本寫法一樣的效果

  要特別注意的是,如果以上任意寫法,遮罩都還是有一閃即消失的狀況,請檢查你 Ajax 的 async 屬性是否設定為 false

   async 屬性其預設值為 true , 當設定為 false 時無法正常產生遮罩,須注意~

 

最後


  結果這篇還是洋洋灑灑的寫了好久,最近真的太忙了。

  本來是還想加入官網的一些說明細節,可能也只能先放坑中了~

  如果有其他更特殊的使用也歡迎大家提出分享

 

參考資料


  將網頁輸入欄位設為唯讀的做法

  JQUERY BLOCKUI 網頁讀取中讓使用者不要進行別的動作

  jQuery實現帶遮罩層效果的blockUI彈出層示例【附demo原始碼下載】

  jQuery : Button Click Event 使用Block UI

  使用 jQuery 的blockUI 顯示 讀取中

  [程式筆記][jQuery]顯示loading畫面

  jQuery : Button Click Event 使用Block UI

  [jQuery]外掛特輯15:BlockUI-區塊遮蔽讓使用者不再看到不該看的

  [BlockUI] 使用在blockUI中使用讀取動畫(JQuery BlockUI Using Animated Image)

  simple example for .blockUI in jquery

  Jquery彈出層BlockUI的用法(包括登陸界面)

  [jQuery] BlockUI Plugin - 功能完善的頁面、訊息遮罩

  [jQuery] 修改 jQuery BlockUI 預設遮罩樣式

  [jQuery] blockUI

  [jQuery]blockUI搭配ajax

arrow
arrow
    創作者介紹
    創作者 律晴音 的頭像
    律晴音

    聆風之境

    律晴音 發表在 痞客邦 留言(0) 人氣()