JSFiddle - React, Tailwind, and code Playground
by romanych
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-debug.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.js"></script>
<script type="text/html" id="questions-editor-tpl">
<div data-bind="foreach: questions">
<input type="text" data-bind="textInput: question" placeholder="Question text" />
<button data-bind="click: $parent.deleteQuestion">x</button>
<ul data-bind="foreach: options ">
<li>
<input type="text" data-bind="textInput: text" placeholder="Option " />
<button data-bind="click: $parent.removeOption, visible: $data.hideDelete ? $data.hideDelete() : true ">x</button>
</li>
</ul>
<br />
<p>
<label>
<input type="checkbox" data-bind="checked: anonymous" />Anonymous</label>
<a href="#" data-bind="click: toggleSettings">Settings</a>
</p>
<div data-bind="visible: showSettings">
<p>
User need to choose
<select data-bind=" value: max_options, options: availableMaxOptions ">
</select>
</p>
<p>
End accept answers:
<select data-bind="
value: end_date,
valueAllowUnset: true,
optionsCaption: 'Never',
optionsText: 'caption',
optionsValue: 'date',
options: availableEndDates"></select>
<br />
<label>
<input type="checkbox" data-bind="checked: show_results_after_end, enable: end_date" />Show results only when survey ends</label>
</p>
<p>
</p>
</div>
</div>
<button data-bind="click: addQuestion ">Add question</button>
<br />
</script>
<div id="questions-editor ">
<div data-bind="template: {name: 'questions-editor-tpl'} ">
</div>
<pre data-bind="text: JSON.stringify(ko.mapping.toJS(questions), null, 2) "></pre>
</div>
JavaScript
var questions = [{
"id": 1,
"anonymous": false,
"end_date": "2017-04-01",
"show_results_after_end": true,
"question": "Question 1",
"max_options": 1,
"options": [{
"id": 1,
"text": "Q1 O1"
}, {
"id": 2,
"text": "Q1 O2"
}, {
"id": 3,
"text": "Q1 O3"
}, {
"id": 4,
"text": "Q1 O4"
}]
}, {
"id": 2,
"anonymous": true,
"end_date": null,
"show_results_after_end": false,
"max_options": 2,
"options": [{
"id": 5,
"text": "Q2 O1"
}, {
"id": 6,
"text": "Q2 O2"
}, {
"id": 7,
"text": "Q2 O3"
}]
}];
function getAvailableEndDates() {
var result = [];
var days = 31;
var d = moment();
for (var i = 1; i <= days; i++) {
d.add(1, 'days');
result.push({
date: d.format("YYYY-MM-DD"),
caption: d.format("LL")
})
};
return result;
}
function createNewOption() {
var newOption = {
"text": ko.observable(),
"new": true
};
newOption.hideDelete = ko.computed(function() {
return !!this.text();
}, newOption)
return newOption;
}
function QuestionViewModel(question) {
if (!question) {
question = {
question: "",
max_options: 1,
options: [],
anonymous: false,
end_date: null,
show_results_after_end: false
}
};
var isDefaultSettins = question.max_options === 1 && question.end_date === null && question.show_results_after_end === false;
ko.mapping.fromJS(question, {}, this);
var self = this;
self.showSettings = ko.observable(!isDefaultSettins);
self.toggleSettings = function() {
self.showSettings(!self.showSettings());
}
self.removeOption = function(option) {
self.options.remove(option);
}
self.availableMaxOptions = ko.computed(function() {
var count = self.options().filter(o => !!o.text()).length;
var result = [1];
for (var i = 2; i <= count; i++) {
result.push(i);
}
return result;
});
self.availableEndDates =...