Limesurvey是一個開源網路調查軟體。可以註冊使用它的服務,或者使用Community Edition架設自己的網路調查系統。
Limesurvey具有功能完整的圖形界面,可以讓任何人輕鬆的建立自己的問卷進行網路調查。與許多網路調查系統不同的是,除了圖形界面,它也支援部分可程式編輯功能,並支援javascript及css,讓這套系統,具備更大的彈性空間。
Limesurvey的架設及基本操作,可以在網路上找到一些教學,Limesurvey官方也有詳細的操作說明。撰寫這篇文章的目的,是在這些基礎操作之外,分享一些進階應用,給使用這套軟體的朋友參考。
做為這一系列的第一篇文章,先分享一個變化較大的應用--縣市鄉鎮選單的製作。縣市鄉鎮選單是調查中很常見的一種題型。常見的設計,會以兩個相互連動的下拉選單呈現,先讓填答者選擇縣市,然後再選擇鄉鎮市區。例如以下的題目:
當然Limesurvey沒有這種題型可以直接套用。這就必須由我們自己創造出來了。有鑑於Limesurvey支援javascript,因此我們可以透過javascript來進行改造。我們的目標是建立兩個相互關聯的下來選單,一個是「縣市」,一個「鄉鎮市區」;同時為了以防特殊狀況,會在兩個選單中都加入「其他」的選項,若選擇「其他」時,則提供開放文字欄位,讓填答者自由輸入。據此,我們需要三個欄位來承接相對應的資料(欄位1紀錄縣市的答案,欄位2紀錄鄉鎮市區的答案或欄位1選擇其他時的文字,欄位3紀錄鄉鎮市區選擇其他時的文字)。
首先我們先把題目建立出來。我們採用的題型是「Array (Texts)」。其中,Y軸維持預設的一個題目即可,X軸則建立三個子題。同時子題的文字欄位都保持空白即可。如下圖:
接著,我們利用javascript對題目進行改造。我們只需在題目欄位點選"</>"按鈕,並將javascript填入題目的source(原始碼)中即可。程式如下:
<script type="text/javascript">
$(document).on('ready pjax:scriptcomplete',function(){
var thisQuestion = $('#question{QID}');
//建立縣市鄉鎮列表,為節省篇幅,以下僅以基隆市及台北市做代表。
var townships = {
"01": [
{ code: "200", name: "仁愛區" },
{ code: "201", name: "信義區" },
{ code: "202", name: "中正區" },
{ code: "203", name: "中山區" },
{ code: "204", name: "安樂區" },
{ code: "205", name: "暖暖區" },
{ code: "206", name: "七堵區" },
{ code: "997", name: "其他(請說明)" }],
"02": [
{ code: "100", name: "中正區" },
{ code: "103", name: "大同區" },
{ code: "104", name: "中山區" },
{ code: "105", name: "松山區" },
{ code: "106", name: "大安區" },
{ code: "108", name: "萬華區" },
{ code: "110", name: "信義區" },
{ code: "111", name: "士林區" },
{ code: "112", name: "北投區" },
{ code: "114", name: "內湖區" },
{ code: "115", name: "南港區" },
{ code: "116", name: "文山區" },
{ code: "997", name: "其他(請說明)" }]
};
// Column specific classes
$('tr.subquestion-list', thisQuestion).each(function(i) {
$('th, td', this).each(function(i) {
$(this).addClass('column-'+i);
});
});
// Insert selects into column 1
if($('.answer-item.column-1 .inserted-select', thisQuestion).length == 0) {
$('.answer-item.column-1', thisQuestion).addClass('with-select').append('<select class="inserted-select form-control list-question-select" id="city-select">\
<option value="">請選擇縣市</option>\
<option value="01">基隆市</option>\
<option value="02">台北市</option>\
<option value="97">其他(請說明)</option>\
</select>');
}
// Insert selects into column 2
if($('.answer-item.column-2 .inserted-select', thisQuestion).length == 0) {
$('.answer-item.column-2', thisQuestion).addClass('with-select').append('<select class="inserted-select form-control list-question-select" id="township-select">\
<option value="">請選擇鄉鎮市區</option>\
</select>');
}
// 初始時隱藏原本的文字框
$('.answer-item.column-1 input:text', thisQuestion).css({
'display': 'none'
});
$('.answer-item.column-2 input:text', thisQuestion).css({
'display': 'none'
});
$('.answer-item.column-3 input:text', thisQuestion).css({
'display': 'none'
});
// 縣市選單改變時,動態更新鄉鎮市區選單
$('#city-select').on('change', function() {
var selectedCity = $(this).val(); // 使用選項的 value
var $townshipSelect = $('#township-select');
var $textInput = $('.answer-item.column-2 input:text', thisQuestion); // 原本的文字框
//當縣市選擇「其他」時,鄉鎮市區欄位顯示原本的文字框
if (selectedCity === '97') {
$townshipSelect.hide();
$textInput.val('')
$textInput.show();
} else {
$townshipSelect.show();
$textInput.hide();
// 更新鄉鎮市區選單
$townshipSelect.empty();
$townshipSelect.append('<option value="">請選擇鄉鎮市區</option>');
var townshipOptions = townships[selectedCity] || [];
townshipOptions.forEach(function(township) {
// 使用鄉鎮市區名稱作為顯示,代碼作為 value
$townshipSelect.append('<option value="' + township.code + '">' + township.name + '</option>');
});
}
$('#township-select').on('change', function() {
var selectedTown = $(this).val();
var $textInput2 = $('.answer-item.column-3 input:text', thisQuestion);
//當鄉鎮市欄位選擇「其他」時,顯示第二個文字框(column-3)
if (selectedTown === '997') {
$textInput2.val('')
$textInput2.show();
}else {
$textInput2.hide();
}
});
// 同步選擇的縣市 value 到 column-1 的輸入框中
$('.answer-item.column-1 input:text', thisQuestion).val(selectedCity).trigger('keyup');
//當縣市選擇其他時,此時不會用到第三個欄位,因此主動在第三個欄位填入NA,避免空值導致此題無法送出
if (selectedCity == "97") {
$('.answer-item.column-3 input:text', thisQuestion).val("NA").trigger('keyup');
}
});
// 當使用者在 column-2 的文字框中輸入時,將資料同步到該題的答案字段中
$('.answer-item.column-2 input:text').on('input', function() {
var enteredText = $(this).val();
$(this).closest('.answer-item').find('input:text').val(enteredText);
});
// 鄉鎮市區選單改變時,同步選擇的 code 到 column-2 的文字框
$('#township-select').on('change', function() {
var selectedTownshipCode = $('#township-select').val(); // 使用選項的 code
$('.answer-item.column-2 input:text', thisQuestion).val(selectedTownshipCode).trigger('keyup');
//當鄉鎮市區不是選擇其他時,此時不會用到第三個欄位,因此主動在第三個欄位填入NA,避免空值導致此題無法送出
if (selectedTownshipCode != "997") {
$('.answer-item.column-3 input:text', thisQuestion).val("NA").trigger('keyup');
}
});
});
</script>
為了方便調查後的資料進行統計分析,我選擇將縣市鄉鎮的代碼記錄在欄位中;由於題目的本質是文字欄位,因此如果希望直接記錄縣市鄉鎮的名稱也沒問題,只要做適當的修改,將文字寫入欄位中即可。
將這段javascript貼到題目的source中,就可以存檔,然後預覽看看效果了。這個做法也可以適用其他多層選單的題目。在此也提供Limesurvey建立地區題的範例,可直接匯入Limesurvey測試。
此功能是參考Limesurvey Community討論區中,一篇名為Array (Text) Type Question With Customized Drop Down In Specific Columns的討論串裡,Tony Partner的範例進行修改的。如果有其他更方便的做法或問題,也歡迎討論。