Runtime Toolbox Customization
Toolbox Customization
Standard Elements
Custom Elements
const options = { showLogicTab: true };
var creator = new SurveyCreator.SurveyCreator(options);
ReactDOM.render(
<React.StrictMode>
<SurveyCreator.SurveyCreatorComponent creator={creator} />
</React.StrictMode>,
document.getElementById("creatorElement")
);
creator.onDefineElementMenuItems.add(function(editor, options) {
if(options.obj.isPage) return;
const objToAdd = options.obj;
options.items.unshift({
id: "addtosharedrepo",
title: "Save as Toolbox Item",
iconName: "icon-toolbox",
iconSize: 16,
action: () => { addIntoCustomItems(objToAdd); }
});
});
// Create and configure a custom button
const customizeToolboxAction = new Survey.Action({
id: "toolbox-customization",
iconName: "icon-toolbox",
title: "Customize Toolbox",
visible: new Survey.ComputedUpdater(() => {
return creator.activeTab === "designer";
}),
showTitle: false,
enabled: true,
action: function() { showToolboxCustomization(); }
});
// Add the custom button to the top toolbar
creator.toolbarItems.push(customizeToolboxAction);
// Add the custom button to the bottom toolbar (visible only on mobile devices)
creator.footerToolbar.actions.push(customizeToolboxAction);
creator.toolbox.showTitleOnCategoryChange = false;
var allToolboxItems = [];
//You have to replace getCustomItems/setCustomItems functions with the code that get/set data in the database
function getCustomItems() {
var res = window.localStorage.getItem("sharedquestions");
if(!res) return {};
return JSON.parse(res);
}
function setCustomItems(items) {
var str = JSON.stringify(items);
window.localStorage.setItem("sharedquestions", str);
}
function addIntoCustomItems(element) {
var json = new Survey.JsonObject().toJsonObject(element);
json.type = element.getType();
var item = { id: element.name, name: element.name, iconName: 'icon-' + element.getType(), title: element.title,
json: json, isCopied: false, isUsed: isItemUsed(element.name), isStandard: false, category: "Custom questions" };
var items = getCustomItems();
items[item.name] = item;
setCustomItems(items);
creator.toolbox.addItem(item);
}
function removeCustomItem(name) {
var items = getCustomItems();
for(var i = 0; i < allToolboxItems.length; i++){
if (allToolboxItems[i].name == name) {
allToolboxItems[i].isUsed = false;
}
}
delete items[name];
setCustomItems(items);
var container = document.getElementById("customItems");
var div = document.getElementById("toobaritem_" + name);
container.removeChild(div);
}
function isItemUsed(name) {
var toolboxItem = creator.toolbox.getItemByName(name);
return !!toolboxItem && toolboxItem.visible;
}
function addToolBoxItemIntoList(container, item) {
allToolboxItems.push(item);
var div = document.createElement("div");
div.id = "toobaritem_" + item.name;
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.name = item.name;
checkbox.checked = item.isUsed;
checkbox.id = item.name;
checkbox.dataItem = item;
checkbox.onchange = function() {this.dataItem.isUsed = this.checked; }
var label = document.createElement('label')
label.style.marginLeft = "5px";
label.htmlFor = item.name;
label.appendChild(document.createTextNode(item.title));
var removeButton = null;
if(!item.isStandard) {
removeButton = document.createElement("button");
removeButton.style.marginLeft = "7px";
removeButton.appendChild(document.createTextNode("Remove"));
removeButton.onclick = function() { removeCustomItem(item.name) };
}
div.appendChild(checkbox);
div.appendChild(label);
if(removeButton) {
div.appendChild(removeButton);
}
container.appendChild(div);
}
function createDefaultItem(typeName) {
var question = Survey.ElementFactory.Instance.createElement(typeName, "q1");
if(!question) {
question = Survey.Serializer.createClass(typeName);
}
var json = new Survey.JsonObject().toJsonObject(question);
json.type = question.getType();
return { id: typeName, name: typeName, iconName: 'icon-' + typeName, title: SurveyCreator.localization.getString('qt.' + typeName),
json: json, isCopied: false, isUsed: isItemUsed(typeName), isStandard: true };
}
function loadAllToolboxItems() {
allToolboxItems = [];
var container = document.getElementById("standardItems");
container.innerHTML = "";
var allTypes = Survey.ElementFactory.Instance.getAllTypes().filter(name => SurveyCreatorCore.QuestionToolbox.hiddenTypes.indexOf(name) < 0);
for(var i = 0; i < allTypes.length; i ++) {
addToolBoxItemIntoList(container, createDefaultItem(allTypes[i]));
}
container = document.getElementById("customItems");
container.innerHTML = "";
var customItems = getCustomItems();
for(var name in customItems) {
var item = customItems[name];
item.isUsed = isItemUsed(name);
addToolBoxItemIntoList(container, item);
}
if(container.children.length == 0) {
container.innerHTML = "Select the question, click on '...' and then click on the first item to add the question here.";
}
}
window.applyToolboxItems = function () {
allToolboxItems.forEach(item => {
var toolboxItem = creator.toolbox.getItemByName(item.name);
if(!!toolboxItem) {
toolboxItem.visible = item.isUsed;
} else if(item.isUsed) {
item.category = "Custom questions";
creator.toolbox.addItem(item);
}
});
}
function showToolboxCustomization() {
loadAllToolboxItems();
modal.open();
}
window.modal = new RModal(document.querySelector("#toolboxCustomization"),{
closeTimeout: 100,
dialogClass: "modal__dialog",
dialogOpenClass: "modal__dialog--animated modal__dialog--fade-in-down",
focus: false
});
<!DOCTYPE html>
<html lang="en">
<head>
<title>Customize the Toolbox at Runtime | Reactjs Example</title>
<meta name="viewport" content="width=device-width" />
<script src="https://unpkg.com/react@17.0.1/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.1/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone@7.2.5/babel.min.js"></script>
<script src="/DevBuilds/survey-core/survey.core.min.js"></script>
<script src="/DevBuilds/survey-core/survey.i18n.min.js"></script>
<script src="/DevBuilds/survey-react-ui/survey-react-ui.min.js"></script>
<link href="/DevBuilds/survey-core/defaultV2.min.css" type="text/css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.10/ace.min.js" type="text/javascript" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.10/ext-language_tools.js" type="text/javascript" charset="utf-8"></script>
<script src="/DevBuilds/survey-creator-core/survey-creator-core.min.js"></script>
<link href="/DevBuilds/survey-creator-core/survey-creator-core.min.css" type="text/css" rel="stylesheet" />
<script src="/DevBuilds/survey-creator-core/survey-creator-core.i18n.min.js"></script>
<script src="/DevBuilds/survey-creator-react/survey-creator-react.min.js"></script>
<style>
:root {
--tab-min-height: 600px;
}
</style>
<link rel="stylesheet" href="./index.css">
<script type="text/javascript" src="https://unpkg.com/rmodal/dist/rmodal.js"></script>
</head>
<body style="margin: 0">
<svg style="display: none;">
<symbol viewBox="0 0 16 16" id="icon-actionaddtosharedrepo"><path d="M7.3 8H1v2h5.2c.2-.7.6-1.4 1.1-2zM10 6.2V5H1v2h7.3c.5-.3 1.1-.6 1.7-.8zM1 2h9v2H1zM11.5 7C9 7 7 9 7 11.5S9 16 11.5 16s4.5-2 4.5-4.5S14 7 11.5 7zm2.5 5h-2v2h-1v-2H9v-1h2V9h1v2h2v1z"></path></symbol>
</svg>
<div id="toolboxCustomization" class="modal builder-page__modal" role="dialog">
<div class="modal__dialog">
<div class="modal__content">
<div class="modal__header">
<h4 class="modal__title">Toolbox Customization</h4>
</div>
<div class="modal__body">
<div class="row">
<div class="row__column">
<div class="panel panel--default builder-page__panel">
<div class="panel__header">Standard Elements</div>
<div class="panel__body">
<div id="standardItems"></div>
</div>
</div>
</div>
<div class="row__column">
<div class="panel panel--default builder-page__panel">
<div class="panel__header">Custom Elements</div>
<div class="panel__body">
<div id="customItems"></div>
</div>
</div>
</div>
</div>
</div>
<div class="modal__footer">
<input type="button" class="modal__button modal__button--default" data-dismiss="modal" value="OK" onclick="applyToolboxItems(); modal.close();" style="width:100px" />
<input type="button" class="modal__button modal__button--danger" data-dismiss="modal" value="Cancel" onclick="modal.close();" style="width:100px" />
</div>
</div>
</div>
</div>
<div id="surveyContainer">
<div id="creatorElement" style="height: 100vh;"></div>
</div>
<script type="text/babel" src="./index.js"></script>
</body>
</html>
.builder-page__modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 999;
display: none;
overflow: hidden;
-webkit-overflow-scrolling: touch;
outline: 0;
}
.modal {
font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
background: rgba(0, 0, 0, 0.3);
}
.modal__dialog {
position: relative;
max-width: 600px;
margin: 30px auto;
}
.modal__content {
position: relative;
background-color: #fff;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #999;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 6px;
outline: 0;
-webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
}
.modal__header {
font-size: 18px;
padding: 15px;
border-bottom: 1px solid #e5e5e5;
}
.modal__button{
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-size: 14px;
font-weight: 400;
line-height: 1.42857143;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
}
.modal__button--default {
color: #333;
background-color: #fff;
border-color: #ccc;
margin-right: 10px;
}
.modal__button--danger {
color: #fff;
background-color: #d9534f;
border-color: #d43f3a;
}
.modal__body {
font-size: 14px;
padding: 15px;
max-height: 70vh;
}
.modal__footer {
padding: 15px;
text-align: right;
border-top: 1px solid #e5e5e5;
}
.modal__dialog--animated {
-webkit-animation-duration: 0.2s;
animation-duration: 0.2s;
}
@keyframes fadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
to {
opacity: 1;
-webkit-transform: none;
transform: none;
}
}
.modal__dialog--fade-in-down {
-webkit-animation-name: fadeInDown;
animation-name: fadeInDown;
}
.builder-page__panel {
margin-bottom: 20px;
border: 1px solid transparent;
border-radius: 4px;
-webkit-box-shadow: 0 1px 1px rgba(0,0,0,.05);
box-shadow: 0 1px 1px rgba(0,0,0,.05);
}
.panel {
background-color: #fff;
}
.panel--default {
border-color: #ddd;
}
.panel__header {
color: #333;
background-color: #f5f5f5;
border-color: #ddd;
padding-left: 5px;
}
.panel__body {
padding: 15px;
max-height: 62vh;
overflow: auto;
}
.panel label {
margin-bottom: 5px;
display: inline-block;
font-weight:normal;
}
.row {
padding: 0;
}
.row::after{
display: table;
content: " ";
clear: both;
}
.row__column {
width: 48%;
float: left;
padding-right: 0;
padding-left: 0;
}
.row__column:first-child {
padding-right: 20px;
}
Loading...
Sorry, we can't retrieve the data from server. Please comeback later.