I have followed DenisChenu's suggestion above and developed a little jQuery plugin that leverages the
ImageMapster plugin to do the following with image maps in list(radio) or multiple choice questions:
- Highlight the map area when hovered or clicked
- Hide the LS radio and checkbox buttons
- Click the corresponding radio or checkbox buttons when an area is clicked
Some requirements for the plugin:
- The ImageMapster plugin must be included (see below).
- If using more than one image map/page, all maps must have unique IDs.
- Image map areas MUST have IDs matching the corresponding answer codes.
To add the plugin to your template:
-
Download the ImageMapster plugin and upload jquery.imagemapster.min.js to your template directory
- Add an inclusion for that file to the <head> element in startpage.pstpl:
<script type="text/javascript" src="{TEMPLATEURL}jquery.imagemapster.min.js"></script>- Add the following to the end of your template.js file:
// A jQuery plugin to handle image maps in LimeSurvey
// Requires ImageMapster - http://www.outsharked.com/imagemapster/
(function( $ ){
$.fn.handleImageMap = function(options) {
// The defaults, extended and modified with any passed in the function call
var opts = $.extend( {
optHideAnswers: false, // Show or hide the LimeSurvey answers
optListKey: 'id', // The attribute of the map area that holds the answer code
optHighlightFill: true, // Use foreground fill when hovered
optHighlightFillColor: 'D2F2D3', // Foreground colour when hovered
optHighlightStroke: true, // Use border when hovered
optHighlightStrokeColor: '328639', // Border colour when hovered
optHighlightStrokeWidth: 1, // Border width when hovered
optHighlightFillOpacity: 0.2, // Foreground opacity when hovered
optSelectFill: true, // Use foreground fill when active (checked)
optSelectFillColor: 'D2F2D3', // Foreground colour when active (checked)
optSelectStroke: true, // Use border when active
optSelectStrokeColor: '328639', // Border colour when active
optSelectStrokeWidth: 3, // Border width when active
optSelectFillOpacity: 0.5 // Foreground opacity when active
}, options);
return this.each(function() {
if(($(this).hasClass('list-radio') || $(this).hasClass('multiple-opt')) && $('map', this).length > 0) { // Only for plain radio or checkbox questions with maps
var $thisQuestion = $(this);
var qID = $thisQuestion.attr('id').split('question')[1];
if(opts.optHideAnswers == true) {
$('#question'+qID+' li[id^="javatbd"]').parent().hide();
}
// Find the survey and group IDs
if($('input#fieldnames').length != 0) {
var fieldNames = $( 'input#fieldnames' ).attr('value');
var tmp = fieldNames.split('X');
var sID = tmp[0];
var gID = tmp[1];
}
// Only single choice for radios (obviously)
var limeSingleSelect;
if($(this).hasClass('multiple-opt')) {
limeSingleSelect = false;
}
else {
limeSingleSelect = true;
}
// Add an attribute to the image map areas that correspond to the input IDs
$('#question'+qID+' area').each(function(i){
$(this).attr('data-state', 'answer'+sID+'X'+gID+'X'+qID+$(this).attr('id'));
});
// Click event on the image map areas
function limeHandleMapClick(data) {
// data: jQuery eventObject
// data.listTarget: $(item) from boundList
// data.key: mapKey for this area
// data.selected: true | false
if($('#question'+qID).hasClass('list-radio')) {
// Prevent unclicking of radios
// (this seems reversed but the event occurs AFTER the map area has been toggled)
if(data.selected == false) {
return false;
}
}
// Fire conditions (need a small delay for the checkboxes)
setTimeout(function() {
checkconditions($(data.listTarget).attr('value'), $(data.listTarget).attr('name'), $(data.listTarget).attr('type'));
}, 100);
}
// Initialize the ImageMapster plugin
$('#question'+qID+' img').mapster( {
render_highlight: {
fill: opts.optHighlightFill,
fillColor: opts.optHighlightFillColor,
stroke: opts.optHighlightStroke,
strokeColor: opts.optHighlightStrokeColor,
strokeWidth: opts.optHighlightStrokeWidth,
fillOpacity:opts.optHighlightFillOpacity
},
render_select: {
fill: opts.optSelectFill,
fillColor: opts.optSelectFillColor,
stroke: opts.optSelectStroke,
strokeColor: opts.optSelectStrokeColor,
strokeWidth: opts.optSelectStrokeWidth,
fillOpacity: opts.optSelectFillOpacity
},
isSelectable: true,
singleSelect: limeSingleSelect,
listSelectedAttribute: 'checked',
boundList: $('#question'+qID+' input[type="checkbox"], #question'+qID+' input[type="radio"]'),
mapKey: 'data-state',
listKey: opts.optListKey,
onClick: limeHandleMapClick
});
// Initial imag map area state(s)
$('#question'+qID+' input.checkbox:checked, #question'+qID+' input.radio:checked').each(function(i){
$('#question'+qID+' area[data-state="'+$(this).attr('id')+'"]').mapster('select');
});
// Click events for the LS inputs (if not hidden);
$('#question'+qID+' input.radio').click(function(event){
$('area[data-state="'+$(this).attr('id')+'"]').mapster('select');
});
$('#question'+qID+' input.checkbox').click(function(){
var selected = $(this).is(':checked');
$('#question'+qID+' img').mapster('set', selected, $(this).attr('id'));
});
}
});
};
})( jQuery );
The plugin can either be applied globally to all questions in a survey that contain image maps or to individual questions.
To apply the plugin globally to all questions, add the following to the end of your template.js file:
$(document).ready(function(){
$('map area').parents('.list-radio').handleImageMap(); // Apply the plugin to all list(radio) questions
$('map area').parents('.multiple-opt').handleImageMap(); // Apply the plugin to all multiple choice questions
});
To apply the plugin to individual questions, add the following to the question source:
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
$('#question{QID}').handleImageMap(); // Apply the plugin to this question
});
</script>
You can see the default options in the plugin code above. These can be over-ridden when calling the plugin. So, you may want to use something like this:
$(document).ready(function(){
$('map area').parents('.multiple-opt').handleImageMap( {
optHighlightFillColor: 'FF0000',
optHighlightStrokeColor: 'FF0000',
optHighlightStrokeWidth: 2,
optHighlightFillOpacity: 0.2,
optSelectFillColor: 'D2F2D3',
optSelectStrokeColor: 'FF0000',
optSelectStrokeWidth: 3,
optSelectFillOpacity: 0.5
});
});
To show the LS answers (for debugging) use:
$('map area').parents('.multiple-opt').handleImageMap({ optHideAnswers: false });