Toast Message - 整合到Joomla!中的模組

整合到Joomla!中的模組

在開始下面的步驟之前,你需要先把Joomla!系統先安裝好。並且確定你可以在管理區中安裝套件。

建立工作用模組

在Joomla!系統中的套件,需要先安裝註冊後,才能在管理區和網站上使用。一開始我們需要三個檔案,打包後安裝到Joomla!上,以便建立一個開發和測試的環境,你可以先新增一個工作資料夾,這裡我們用的是mod_toast

  • mod_toast.xml
  • mod_toast.php
  • index.html

index.html這個檔案只是為了多一層安全性使用的,並沒有特別的功能,它的內容如下:

<html><body bgcolor="#FFFFFF"></body></html>

mod_toast.php這個檔案之後會放我們的主要的程式碼。現在暫時先放一個訊息在裡面,並且加上Joomla!系統的特殊保護程式碼在程式碼的最前面,這是確保這個程式只能由Joomla!系統來執行,每個套件都需要的:

<?php

defined('_JEXEC') or die;

echo "我是吐司訊息模組";

mod_toast.xml檔案的如以下的內容:

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.0" client="site" method="upgrade">
    <name>Toast Message</name>
    <author>Eddy Chang</author>
    <version>1.0.0</version>
    <description>一個簡單的吐司訊息模組</description>
    <files>
        <filename module="mod_toast">mod_toast.php</filename>
        <filename>index.html</filename>
    </files>
    <config>
    </config>
</extension>

將這三個檔案用壓縮軟體壓縮為mod_toast.zip(註:這個壓縮檔名稱沒有限制一定要使用這個名稱,只是方便識別而已,通常後面會加上版本編號例如mod_toast_v1.0.zip更容易看得清楚),然後在Joomla!後台的擴充套件管理中安裝它,這就算註冊完成了。

然後我們在模組管理中,把這個模組暫時先顯示在首頁中可以看到的一個位置中。下面我們要開始撰寫功能。

調整js/css檔案的連結位置

我們接著要把在第1步驟中的所有已經製作好的檔案,先複製到我們在Joomla!系統的工作目錄裡,這是在Joomla!網站目錄中的modules/mod_toast/的這個目錄。

接著我們要把第1步驟中的test.html的內容,都複製到mod_toast.php裡。不過test.html裡都只有加入css檔和javascript檔的宣告而已,這些事情都需要交給Joomla!來作,我們用這些語法之後,Joomla!會自動在網頁輸出時,幫我們加到網頁的<head>標記中,所以我們在mod_toast.php裡應該在接下來的空白處填入:

$doc = JFactory::getDocument();

$doc->addStyleSheet( JURI::base().'modules/mod_toast/css/Lobibox.min.css' );
$doc->addStyleSheet( JURI::base().'modules/mod_toast/font-awesome/css/font-awesome.min.css' );
$doc->addScript( 'https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js');
$doc->addScript( JURI::base().'modules/mod_toast/js/ifvisible.min.js' );
$doc->addScript( JURI::base().'modules/mod_toast/js/notifications.min.js' );
$doc->addScript( JURI::base().'modules/mod_toast/js/custom.js' );

jQuery函式庫則不需要再加了,jQuery預設都會在前台的佈景中載入。

註:JHtml::script與JHtml::stylesheet一樣可以用於加入javascript與css檔案,並提供更多的選項彈性。

這個時候如果你測試的話,會發現我們的的功能並不會正常出現,這是因為在Joomla!裡的jQuery變成no-conflict(不衝突)模式,需要調整一下我們的custom.js的程式碼,在最外面"包上一層"程式碼:

(function($){

// 原先的程式碼

})(jQuery);

另一個問題是我們用的notification.min.js這個函式庫,裡面要修改一下,讓它可以在jQuery變成no-conflict(不衝突)模式中正常執行,我們要改用notification.js這個檔案,比較方便修改,修改的概念類似上面的包覆程式碼。首先找到這一行,應該是在第19行左右:

(function () {

改為

(function ($) {

然後找到最後一行(第335行):

})();

改為

})(jQuery);

最後,我們還需要在mod_toast.php檔案裡,把原本載入notifications.min.js檔案的那行PHP程式碼,改成以下的:

$doc->addScript( JURI::base().'modules/mod_toast/js/notifications.js' );

這樣子就可以在Joomla!的首頁網頁上,看到之前寫好的訊息框程式了。

檢查點:看看網頁的首頁是不是有出現你的之前寫好的訊息框程式。

改在模組管理區中填入訊息

因為我們要改用在模組管理區填入標題、訊息與連結,所以先把可以要讓使用者設定的選項寫在mod_toast.xml檔案裡,我們用了三個一樣的設定,作為三組訊息的標題、訊息與連結,以下為mod_toast.xml中在 <config></config>標記區段裡的程式碼:

<fields name="params">
          <fieldset name="basic">
            <field name="title1"
                   type="text"
                   default="標題1"
                   label="標題1"
                   description=""
                   size="20" />
            <field name="message1"
                   type="text"
                   default="訊息1"
                   label="訊息1"
                   description=""
                   size="200" />
            <field name="url1"
                   type="url"
                   default="http://www.example.com"
                   label="網址1"
                   description=""
                   size="50" />
            <field type="spacer" name="myspacer1" hr="true" label="第二訊息" />
            <field name="title2"
                   type="text"
                   default="標題2"
                   label="標題2"
                   description=""
                   size="20" />
            <field name="message2"
                   type="text"
                   default="訊息2"
                   label="訊息2"
                   description=""
                   size="200" />
            <field name="url2"
                   type="url"
                   default="http://www.example.com"
                   label="網址2"
                   description=""
                   size="50" />
            <field type="spacer" name="myspacer2" hr="true" label="第三訊息" />
            <field name="title3"
                   type="text"
                   default="標題3"
                   label="標題3"
                   description=""
                   size="20" />
            <field name="message3"
                   type="text"
                   default="訊息3"
                   label="訊息3"
                   description=""
                   size="200" />
            <field name="url3"
                   type="url"
                   default="http://www.example.com"
                   label="網址3"
                   description=""
                   size="50" />
          </fieldset>
        </fields>

接著我們要用程式碼先取得在模組裡設定的這些字串值,打開mod_toast.php檔案,在下面空白處加入以下的程式碼:

$title1 = $params->get('title1', '');
$title2 = $params->get('title2', '');
$title3 = $params->get('title3', '');

$message1 = $params->get('message1', '');
$message2 = $params->get('message2', '');
$message3 = $params->get('message3', '');

$url1 = $params->get('url1', '');
$url2 = $params->get('url2', '');
$url3 = $params->get('url3', '');

最後,我們需要把原本在custom.js的內容,先放到mod_toast.php這個PHP檔案中,先把設定值裡的字串處理過後,再叫Joomla!系統幫我們放到網頁的<head>標記中。因為是Javascript碼要放在PHP程式碼中,我們使用了Heredoc的語法較為方便,以下為程式碼:

$js = <<<JS
(function($){

$( document ).ready(function() {
    Lobibox.notify.DEFAULTS = $.extend({}, Lobibox.notify.DEFAULTS, {
        iconSource: "fontAwesome"
    });

var allMessagebox = function(){
    Lobibox.notify('info', {
        title: '{$title1}',
        msg: '{$message1}<br><a href="{$url1}">前往了解</a>',
        delay: 5000,
        sound: false,
    });

    setTimeout(function(){
      if( ifvisible.now() ){
        Lobibox.notify('success', {
        title: '{$title2}',
        msg: '{$message2}<br><a href="{$url2}">前往了解</a>',
        delay: 5000,
        sound: false,
        });
      }
    }, 7000);

    setTimeout(function(){
     if( ifvisible.now() ){
        Lobibox.notify('error', {
        title: '{$title3}',
        msg: '{$message3}<br><a href="{$url3}">前往了解</a>',
        delay: 5000,
        sound: false,
        });
      }
    }, 14000);
};

setTimeout(allMessagebox, 0);
ifvisible.onEvery(21, allMessagebox);

});

})(jQuery);
JS;

$doc->addScriptDeclaration($js);

好的,這樣模組的整合工作告一段落了,我們要把那個用來測試的模組訊息拿掉,不需要在網頁上看得到。所以我們先刪除或註解掉在mod_toast.php的這一行顯示資訊:

echo "我是吐司訊息模組";

然後在後台管理區的模組管理區的吐司訊息模組頁面,在"進階"的設定資訊標籤裡,把模組樣式,設為none,就如同下圖一樣:

設定圖

回家作業

  1. 打包這個模組,讓它可以在別的Joomla!系統上也能安裝使用
  2. 使用模組管理,讓它可以在訊息裡加上設定的圖片
  3. 使用模組管理,讓它可以選擇要出現幾個訊息
  4. 使用模組管理,改用自動抓取某個分類的最新文章標題與文章內容當作訊息,並加上文章連結
  5. 改用有callback的通知訊息Javascript函式庫,可以方便的呈現更多訊息框

結語

Joomla!的模組開發過程:

  1. 先建立一個可安裝的模組資料夾,以及加入安裝/設定用XML定義檔,與最少需要的檔案
  2. 安裝到Joomla!系統中,在對應的modules裡開發與測試
  3. 複製已完成的檔案回原先的模組資料夾,調整安裝/設定用XML定義檔,將所需的檔案與目錄都加入安裝區段
  4. 壓縮打包套件,然後安裝再測試,對外發佈套件

幾個可能問題說明一下:

Joomla!套件開發時,為何不使用自動化程序像phing?

或許你有聽過或用過像phing或ant之類的自動化程序,協助你在套件開發時,可以自動安裝,或是打包套件。我們在教學裡不使用這些程序的原因有幾個:

  • 複雜。因為你還要多些設定或調整,如果你是要開發簡單的套件似乎又多了一些麻煩的事。
  • 資料庫。對於資料庫中的部份要另外再用別的方式。自動化程序多半針對檔案,資料庫與資料表你還是得要手動匯出與調整。

為何不用外掛而用模組?系統外掛不是可以套用到全站?

  • 選項的彈性:系統外掛並沒有"選擇某個網站區域(用選單項目來選)",然後再出現我們的功能的選項。這部份如果你需要要自己再寫。為了簡單教學起見所以用模組來教,你也可以寫成系統外掛。
  • 系統外掛要更小心:通常系統外掛很容易造成網站壞掉,所以開發時要更小心。

能夠多少個訊息?還有這個訊息的輪流播放方式有點不太順的感覺?

  • 因為我們這個教學用了無callback(回呼)的Toast訊息,也就是一個訊息出現後,我們無法直接得知它何時會關閉,只能用計算秒數的方式再播下一個訊息。如果你改成有callback(回呼)的函式庫,就可以直接在關閉的callback(回呼)中執行下一個,這應該目前最佳的方式。不過建議要配合jQuery的deferred物件。
  • 能夠多少訊息是由你自己決定,愈多的訊息代表愈複雜的程式碼和需要更多的資源。
  • 對於瀏覽器tab(資訊標籤)在不可見時的問題,ifvisible的解決方式可能不是最完美,或許有更好的方式也說不定。