From a90ade18e52a8136c5027586d5c320bceb6bd93f Mon Sep 17 00:00:00 2001 From: Hristo Alexiev Date: Wed, 21 Feb 2018 15:28:29 +0200 Subject: [PATCH] Add support for: 'boolean' question type; multiple states based on provided css classes in widget.settings. --- src/pretty-checkbox.js | 304 ++++++++++++++++++++++++----------------- 1 file changed, 176 insertions(+), 128 deletions(-) diff --git a/src/pretty-checkbox.js b/src/pretty-checkbox.js index a2944860..b108a626 100644 --- a/src/pretty-checkbox.js +++ b/src/pretty-checkbox.js @@ -1,138 +1,186 @@ function init(Survey) { - var widget = { - settings: { - radiogroup: { - rootClass: "pretty p-default p-round", - inputType: "radio", - addOn: "", - titleClass: "state p-success" - }, - checkbox: { - rootClass: "pretty p-default", - inputType: "checkbox", - addOn: "", - titleClass: "state p-success" - } - }, - name: "pretty-checkbox", - activatedBy: "property", - widgetIsLoaded: function() { - return true; - }, - htmlTemplate: "
", - isFit: function(question) { - var isFitByType = - question.getType() === "radiogroup" || - question.getType() === "checkbox"; - if (widget.activatedBy === "property") - return question["renderAs"] === "prettycheckbox" && isFitByType; - if (widget.activatedBy === "type") return isFitByType; - return false; - }, - activatedByChanged: function(activatedBy) { - if (!this.widgetIsLoaded()) return; - widget.activatedBy = activatedBy; - Survey.JsonObject.metaData.removeProperty("radiogroup", "renderAs"); - Survey.JsonObject.metaData.removeProperty("checkbox", "renderAs"); - if (activatedBy === "property") { - Survey.JsonObject.metaData.addProperty("radiogroup", { - name: "renderAs", - default: "standard", - choices: ["standard", "prettycheckbox"] - }); - Survey.JsonObject.metaData.addProperty("checkbox", { - name: "renderAs", - default: "standard", - choices: ["standard", "prettycheckbox"] - }); - } - }, - isDefaultRender: false, - afterRender: function(question, el) { - var itemInputs = {}; - var options = this.settings[question.getType()]; - var inChangeHandler = false; - var changeHandler = function(event) { - inChangeHandler = true; - try { - var value = arguments[0].target.value; - if (question.getType() === "checkbox") { - var qValue = question.value || []; - if (arguments[0].target.checked) { - if (qValue.indexOf(value) === -1) { - qValue.push(value); - } - } else { - if (qValue.indexOf(value) !== -1) { - qValue.splice(qValue.indexOf(value), 1); - } + const widget = { + settings: { + supportedTypes: ["radiogroup", "checkbox", "boolean"], + radiogroup: { + rootClass: "pretty p-default p-round", + inputType: "radio", + states: [ + {stateClass: "state p-success", addOn: ""} + ] + }, + checkbox: { + rootClass: "pretty p-default", + inputType: "checkbox", + states: [ + {stateClass: "state p-success", addOn: ""} + ] + }, + boolean: { + rootClass: "pretty p-icon p-default p-has-indeterminate", + inputType: "checkbox", + states: [ + {stateClass: "state p-success", addOn: ""}, + {stateClass: "state p-success p-is-indeterminate", iconClass: "icon mdi mdi-minus", addOn: ""} + ] } - question.value = qValue; - } else { - question.value = value; - } - } finally { - inChangeHandler = false; - } - }; - var itemWidth = - question.colCount > 0 ? 100 / question.colCount + "%" : ""; - question.choices.forEach(function(choiceItem, index) { - var itemRoot = document.createElement("div"); - itemRoot.className = "sv_cw_pretty_checkbox_" + question.getType(); - itemRoot.style.display = "inline-block"; - itemRoot.style.width = itemWidth; - var controlRoot = document.createElement("div"); - controlRoot.className = options.rootClass; - var input = document.createElement("input"); - input.type = options.inputType; - input.name = - question.name + (question.getType() === "checkbox" ? "" + index : ""); - input.onchange = changeHandler; - input.value = choiceItem.value; - var titleRoot = document.createElement("div"); - titleRoot.className = options.titleClass; - var label = document.createElement("label"); - label.textContent = choiceItem.text; - titleRoot.appendChild(label); - controlRoot.appendChild(input); - controlRoot.appendChild(titleRoot); - if (!!options.addOn) { - titleRoot.insertAdjacentHTML("afterbegin", options.addOn); - } - itemRoot.appendChild(controlRoot); - el.appendChild(itemRoot); - - itemInputs[choiceItem.value] = input; - }); - var updateValueHandler = function(newValue) { - if (!inChangeHandler) { - var checkedItems = newValue || []; - if (question.getType() === "radiogroup") { - checkedItems = [newValue]; - } - Object.values(itemInputs).forEach(function(inputItem) { - if (checkedItems.indexOf(inputItem.value) !== -1) { - inputItem.setAttribute("checked", undefined); - } else { - inputItem.removeAttribute("checked"); + }, + name: "pretty-checkbox", + activatedBy: "property", + widgetIsLoaded: function () { + return true; + }, + htmlTemplate: "
", + isFit: function (question) { + const isFitByType = widget.settings.supportedTypes.indexOf(question.getType()) !== -1; + + if (widget.activatedBy === "property") { + return question["renderAs"] === "prettycheckbox" && isFitByType; + } else if (widget.activatedBy === "type") { + return isFitByType; + } + + return false; + }, + activatedByChanged: function (value) { + if (this.widgetIsLoaded()) { + widget.activatedBy = value; + widget.settings.supportedTypes.forEach(function(supportedType) { + Survey.JsonObject.metaData.removeProperty(supportedType, "renderAs"); + + if (value === "property") { + Survey.JsonObject.metaData.addProperty(supportedType, { + name: "renderAs", + default: "standard", + choices: ["standard", "prettycheckbox"] + }); + } + }); } - }); + }, + isDefaultRender: false, + afterRender: function (question, element) { + const itemInputs = {}; + const questionType = question.getType(); + const options = this.settings[questionType]; + const checkboxType = questionType === "checkbox"; + const radiogroupType = questionType === "radiogroup"; + const booleanType = questionType === "boolean"; + + var inChangeHandler = false; + const changeHandler = function (event) { + inChangeHandler = true; + try { + const target = arguments[0].target; + const targetValue = target.value; + const targetChecked = target.checked; + + if (checkboxType) { + const questionValue = question.value || []; + const valueIndex = questionValue.indexOf(targetValue); + if (targetChecked) { + if (valueIndex === -1) { + questionValue.push(targetValue); + } + } else { + if (valueIndex !== -1) { + questionValue.splice(valueIndex, 1); + } + } + + question.value = questionValue; + } else if (radiogroupType) { + question.value = targetValue; + } else { + question.value = targetChecked; + } + } finally { + inChangeHandler = false; + } + }; + + const itemWidth = question.colCount > 0 ? 100 / question.colCount + "%" : ""; + + const choices = booleanType ? [{locText: question.locTitle, value: !!question.value}] : question.choices; + choices.forEach(function (choiceItem, index) { + const input = document.createElement("input"); + input.type = options.inputType; + input.name = question.name + (checkboxType ? "" + index : ""); + input.onchange = changeHandler; + input.value = choiceItem.value; + + if (booleanType) { + input.indeterminate = (question.defaultValue === 'indeterminate'); + } + + const controlRoot = document.createElement("div"); + controlRoot.className = options.rootClass; + controlRoot.appendChild(input); + + options.states.forEach(function(state) { + const stateRoot = document.createElement("div"); + stateRoot.className = state.stateClass; + if (!!state.iconClass) { + const icon = document.createElement("i"); + icon.className = state.iconClass; + stateRoot.appendChild(icon); + } + + const label = document.createElement("label"); + if (choiceItem.locText.hasHtml) { + label.innerHTML = choiceItem.locText.html; + } else { + label.textContent = choiceItem.locText.text; + } + stateRoot.appendChild(label); + + controlRoot.appendChild(stateRoot); + if (!!state.addOn) { + stateRoot.insertAdjacentHTML("afterbegin", state.addOn); + } + }); + + const itemRoot = document.createElement("div"); + itemRoot.className = "sv_cw_pretty_checkbox_" + questionType; + itemRoot.style.display = "inline-block"; + itemRoot.style.width = itemWidth; + itemRoot.appendChild(controlRoot); + + element.appendChild(itemRoot); + + itemInputs[choiceItem.value] = input; + }); + + const updateValueHandler = function (newValue) { + if (!inChangeHandler) { + var checkedItems = newValue || []; + if (radiogroupType) { + checkedItems = [newValue]; + } + + Object.values(itemInputs).forEach(function (inputItem) { + if (checkedItems.indexOf(inputItem.value) !== -1) { + inputItem.setAttribute("checked", undefined); + } else { + inputItem.removeAttribute("checked"); + } + }); + } + }; + + question.valueChangedCallback = updateValueHandler; + updateValueHandler(question.value); + }, + willUnmount: function (question, el) { + question.valueChangedCallback = undefined; } - }; - question.valueChangedCallback = updateValueHandler; - updateValueHandler(question.value); - }, - willUnmount: function(question, el) { - question.valueChangedCallback = undefined; - } - }; - - Survey.CustomWidgetCollection.Instance.addCustomWidget(widget, "property"); + }; + + Survey.CustomWidgetCollection.Instance.addCustomWidget(widget, "property"); } if (typeof Survey !== "undefined") { - init(Survey); + init(Survey); } export default init;