mirror of
https://github.com/psychopy/psychojs.git
synced 2025-05-10 10:40:54 +00:00
_
This commit is contained in:
parent
f87431e6af
commit
61a2f4286a
48
src/visual/survey/components/DropdownExtensions.js
Normal file
48
src/visual/survey/components/DropdownExtensions.js
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @desc: Extensions for default dropdown component of SurveyJS to make it more nice to interact with on mobile devices.
|
||||
* @type: SurveyJS component modification.
|
||||
*/
|
||||
|
||||
function handleValueChange (survey, options, e)
|
||||
{
|
||||
options.question.value = e.currentTarget.value;
|
||||
}
|
||||
|
||||
function handleValueChangeForDOM (survey, options)
|
||||
{
|
||||
options.htmlElement.querySelector("select").value = options.question.value;
|
||||
}
|
||||
|
||||
function handleDropdownRendering (survey, options)
|
||||
{
|
||||
// Default SurveyJS drop down is actually an <input> with customly built options list
|
||||
// It works well on desktop, but not that convenient on mobile.
|
||||
// Adding native <select> here that's hidden by default but visible on mobile.
|
||||
const surveyCSS = options.question.css;
|
||||
const choices = options.question.getChoices();
|
||||
let optionsHTML = `<option value=""></option>`;
|
||||
let i;
|
||||
for (i = 0; i < choices.length; i++)
|
||||
{
|
||||
optionsHTML += `<option value="${choices[i].value}">${choices[i].text}</option>`;
|
||||
}
|
||||
const selectHTML = `<select data-name="${options.question.name}" class="${surveyCSS.dropdown.control} dropdown-mobile">${optionsHTML}</select>`;
|
||||
options.htmlElement.querySelector('.sd-selectbase').insertAdjacentHTML("beforebegin", selectHTML);
|
||||
|
||||
const selectDOM = options.htmlElement.querySelector("select");
|
||||
selectDOM.addEventListener("change", handleValueChange.bind(this, survey, options));
|
||||
|
||||
options.question.valueChangedCallback = handleValueChangeForDOM.bind(this, survey, options);
|
||||
}
|
||||
|
||||
export default {
|
||||
registerModelCallbacks (surveyModel)
|
||||
{
|
||||
surveyModel.onAfterRenderQuestion.add((survey, options) => {
|
||||
if (options.question.getType() === "dropdown")
|
||||
{
|
||||
handleDropdownRendering(survey, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
89
src/visual/survey/extensions/customExpressionFunctions.js
Normal file
89
src/visual/survey/extensions/customExpressionFunctions.js
Normal file
@ -0,0 +1,89 @@
|
||||
// Wrapping everything in Class and defining as static methods to prevent esbuild from renaming when bundling.
|
||||
// NOTE! Survey stim uses property .name of these methods on registering stage.
|
||||
// Methods are available inside SurveyJS expressions using their actual names.
|
||||
class ExpressionFunctions {
|
||||
static rnd ()
|
||||
{
|
||||
return Math.random();
|
||||
}
|
||||
|
||||
static arrayContains (params)
|
||||
{
|
||||
if (params[0] instanceof Array)
|
||||
{
|
||||
let searchValue = params[1];
|
||||
let searchResult = params[0].indexOf(searchValue) !== -1;
|
||||
|
||||
// If no results at first, trying conversion combinations, since array of values sometimes might
|
||||
// contain both string and number data types.
|
||||
if (searchResult === false)
|
||||
{
|
||||
if (typeof searchValue === "string")
|
||||
{
|
||||
searchValue = parseFloat(searchValue);
|
||||
searchResult = params[0].indexOf(searchValue) !== -1;
|
||||
}
|
||||
else if (typeof searchValue === "number")
|
||||
{
|
||||
searchValue = searchValue.toString();
|
||||
searchResult = params[0].indexOf(searchValue) !== -1;
|
||||
}
|
||||
}
|
||||
|
||||
return searchResult
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static stringContains (params)
|
||||
{
|
||||
if (typeof params[0] === "string")
|
||||
{
|
||||
return params[0].indexOf(params[1]) !== -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static isEmpty (params)
|
||||
{
|
||||
let questionIsEmpty = false;
|
||||
if (params[0] instanceof Array || typeof params[0] === "string")
|
||||
{
|
||||
questionIsEmpty = params[0].length === 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
questionIsEmpty = params[0] === undefined || params[0] === null;
|
||||
}
|
||||
return questionIsEmpty;
|
||||
}
|
||||
|
||||
static isNotEmpty (params)
|
||||
{
|
||||
return !ExpressionFunctions.isEmpty(params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default [
|
||||
{
|
||||
func: ExpressionFunctions.rnd,
|
||||
isAsync: false
|
||||
},
|
||||
{
|
||||
func: ExpressionFunctions.arrayContains,
|
||||
isAsync: false
|
||||
},
|
||||
{
|
||||
func: ExpressionFunctions.stringContains,
|
||||
isAsync: false
|
||||
},
|
||||
{
|
||||
func: ExpressionFunctions.isEmpty,
|
||||
isAsync: false
|
||||
},
|
||||
{
|
||||
func: ExpressionFunctions.isNotEmpty,
|
||||
isAsync: false
|
||||
}
|
||||
];
|
Loading…
Reference in New Issue
Block a user