├── .eslintrc.json
├── .gitattributes
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── api.html
├── babel.config.json
├── css
├── awesome-bootstrap-checkbox.css
├── bootstrap.css
├── bootstrap.min.css
├── demo-stackslider.css
├── demo.css
├── doc.css
├── font-awesome.css
├── prism.css
└── stackSlider.css
├── demos.html
├── demos
├── demo-basic-extended.html
├── demo-basic-lite.html
├── demo-basic.html
├── demo-stackslider-1.html
└── demo-stackslider-2.html
├── dist
├── lite
│ ├── surveyjs-esm.js
│ ├── surveyjs-esm.min.js
│ ├── surveyjs-esm.min.js.map
│ ├── surveyjs-systemjs.js
│ ├── surveyjs-systemjs.min.js
│ ├── surveyjs-systemjs.min.js.map
│ ├── surveyjs.js
│ ├── surveyjs.min.js
│ └── surveyjs.min.js.map
├── surveyjs-esm.js
├── surveyjs-esm.min.js
├── surveyjs-esm.min.js.map
├── surveyjs-systemjs.js
├── surveyjs-systemjs.min.js
├── surveyjs-systemjs.min.js.map
├── surveyjs.js
├── surveyjs.min.js
└── surveyjs.min.js.map
├── fonts
├── FontAwesome.otf
├── fontawesome-webfont.eot
├── fontawesome-webfont.svg
├── fontawesome-webfont.ttf
├── fontawesome-webfont.woff
└── fontawesome-webfont.woff2
├── get-started.html
├── index.d.ts
├── index.html
├── js
├── demo.js
├── demos
│ ├── demo-basic-extended.js
│ ├── demo-basic-lite.js
│ ├── demo-basic.js
│ ├── demo-stackslider-1.js
│ ├── demo-stackslider-2.js
│ └── doc.js
├── include.js
├── prism.js
└── vendors
│ ├── bootstrap.bundle.min.js
│ ├── formjs.js
│ ├── formjs.min.js
│ ├── formjs.min.js.map
│ ├── jquery-1.12.4.min.js
│ ├── jquery_stackslider.js
│ └── modernizr_custom_63321.js
├── json
├── survey-simple.json
└── survey.json
├── package-lock.json
├── package.json
├── rollup.config.js
├── rollup.config.lite.js
├── rollup.config.server.js
└── src
├── index-lite.js
├── index.js
├── modules-lite
└── options.js
└── modules
├── buildSurvey
├── buildSurvey.js
├── generateQAcode.js
├── generateQAcodeUtils
│ ├── generateAnswers.js
│ ├── generateOptionTags.js
│ ├── getAttributesStringHTML.js
│ └── getTemplates.js
└── populateAnswers.js
├── destroy.js
├── helpers.js
├── helpers
├── ajaxCall.js
├── arrayMove.js
├── checkFormEl.js
├── customEvents.js
├── deepFreeze.js
├── dispatchCustomEvent.js
├── fieldsStringSelectorSurvey.js
├── getQuestionId.js
├── isDOMNode.js
├── isEmptyObject.js
├── isNodeList.js
├── isPlainObject.js
├── mergeObjects.js
├── replaceObjectKeysInString.js
├── sortList.js
├── toKebabCase.js
└── webStorage.js
├── internals.js
├── listenerCallbacks.js
├── listenerCallbacks
├── submit.js
└── validationEnd.js
├── options.js
├── optionsUtils.js
├── utils
├── getAnswerIndex.js
└── getQuestionObject.js
└── version.js
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2021": true
5 | },
6 | "extends": "eslint:recommended",
7 | "overrides": [
8 | ],
9 | "parserOptions": {
10 | "ecmaVersion": "latest",
11 | "sourceType": "module"
12 | },
13 | "ignorePatterns": ["js", "dist", "node_modules"],
14 | "rules": {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 | *.html linguist-documentation
4 | css/* linguist-documentation
5 | demos/* linguist-documentation
6 | fonts/* linguist-documentation
7 | img/* linguist-documentation
8 | json/* linguist-documentation
9 | js/demo.js linguist-documentation
10 | js/include.js linguist-documentation
11 | js/prism.js linguist-documentation
12 | js/demos/* linguist-vendored
13 | js/vendors/* linguist-vendored
14 | dist/* linguist-generated=true
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.zip
3 | .DS_Store
4 | **/.DS_Store
5 | Thumbs.db
6 | **/Thumbs.db
7 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | css
2 | demos
3 | fonts
4 | js
5 | json
6 | *.html
7 | *.config.js
8 | *.config.*.js
9 | *.zip
10 | .gitattributes
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Valerio Di Punzio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | surveyJS is available on
4 | NPM |
5 | jsDelivr |
6 | UNPKG
7 |
8 |
9 | # surveyJS
10 |
11 | Visit the [Plugin Documentation Page](https://www.valeriodipunzio.com/plugins/surveyJS/) for more info.
12 |
13 |
14 |
15 | ## Changelog
16 |
17 | See the [Changelog Page](https://www.valeriodipunzio.com/plugins/surveyJS/#changelog) for details.
18 |
19 |
20 |
21 | ## Releases
22 |
23 | See the [Releases Page](https://github.com/SimplySayHi/surveyJS/releases) to download provious versions.
24 |
25 |
26 |
27 | ## License
28 |
29 | MIT
30 |
--------------------------------------------------------------------------------
/babel.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "build": {
4 | "exclude": "node_modules/**",
5 | "presets": [
6 | [ "@babel/env", {"modules": false} ]
7 | ]
8 | },
9 | "test": {
10 | "presets": [
11 | [ "@babel/env", {"targets": {"node": "current"}} ]
12 | ]
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/css/awesome-bootstrap-checkbox.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | .abc-checkbox {
3 | cursor: default;
4 | padding-left: 4px; }
5 | .abc-checkbox label {
6 | cursor: pointer;
7 | display: inline;
8 | vertical-align: top;
9 | position: relative;
10 | padding-left: 5px; }
11 | .abc-checkbox label::before {
12 | cursor: pointer;
13 | content: "";
14 | display: inline-block;
15 | position: absolute;
16 | width: 17px;
17 | height: 17px;
18 | top: 2px;
19 | left: 0;
20 | margin-left: -1.25rem;
21 | border: 1px solid rgba(0, 0, 0, 0.15);
22 | border-radius: 3px;
23 | background-color: #fff;
24 | transition: border 0.15s ease-in-out, color 0.15s ease-in-out; }
25 | .abc-checkbox label::after {
26 | cursor: pointer;
27 | display: inline-block;
28 | position: absolute;
29 | width: 16px;
30 | height: 16px;
31 | left: 0;
32 | top: 2px;
33 | margin-left: -1.25rem;
34 | padding-left: 3px;
35 | padding-top: 1px;
36 | font-size: 11px;
37 | color: #495057; }
38 | .abc-checkbox input[type="checkbox"],
39 | .abc-checkbox input[type="radio"] {
40 | position: static;
41 | margin-left: 0;
42 | cursor: pointer;
43 | opacity: 0;
44 | z-index: 1; }
45 | .abc-checkbox input[type="checkbox"]:focus + label::before,
46 | .abc-checkbox input[type="radio"]:focus + label::before {
47 | outline: thin dotted;
48 | outline: 5px auto -webkit-focus-ring-color;
49 | outline-offset: -2px; }
50 | .abc-checkbox input[type="checkbox"]:checked + label::after,
51 | .abc-checkbox input[type="radio"]:checked + label::after {
52 | font-family: "FontAwesome";
53 | content: ""; }
54 | .abc-checkbox input[type="checkbox"]:indeterminate + label::after,
55 | .abc-checkbox input[type="radio"]:indeterminate + label::after {
56 | display: block;
57 | content: "";
58 | width: 10px;
59 | height: 3px;
60 | background-color: #555555;
61 | border-radius: 2px;
62 | margin-left: -16.5px;
63 | margin-top: 7px; }
64 | .abc-checkbox input[type="checkbox"]:disabled + label,
65 | .abc-checkbox input[type="radio"]:disabled + label {
66 | opacity: 0.65; }
67 | .abc-checkbox input[type="checkbox"]:disabled + label::before,
68 | .abc-checkbox input[type="radio"]:disabled + label::before {
69 | background-color: #e9ecef;
70 | cursor: not-allowed; }
71 | .abc-checkbox input[type="checkbox"]:disabled + label::after,
72 | .abc-checkbox input[type="radio"]:disabled + label::after {
73 | cursor: not-allowed; }
74 | .abc-checkbox.abc-checkbox-circle label::before {
75 | border-radius: 50%; }
76 | .abc-checkbox.checkbox-inline {
77 | margin-top: 0; }
78 |
79 | .abc-checkbox-primary input[type="checkbox"]:checked + label::before,
80 | .abc-checkbox-primary input[type="radio"]:checked + label::before {
81 | background-color: #007bff;
82 | border-color: #007bff; }
83 | .abc-checkbox-primary input[type="checkbox"]:checked + label::after,
84 | .abc-checkbox-primary input[type="radio"]:checked + label::after {
85 | color: #fff; }
86 |
87 | .abc-checkbox-danger input[type="checkbox"]:checked + label::before,
88 | .abc-checkbox-danger input[type="radio"]:checked + label::before {
89 | background-color: #dc3545;
90 | border-color: #dc3545; }
91 | .abc-checkbox-danger input[type="checkbox"]:checked + label::after,
92 | .abc-checkbox-danger input[type="radio"]:checked + label::after {
93 | color: #fff; }
94 |
95 | .abc-checkbox-info input[type="checkbox"]:checked + label::before,
96 | .abc-checkbox-info input[type="radio"]:checked + label::before {
97 | background-color: #17a2b8;
98 | border-color: #17a2b8; }
99 | .abc-checkbox-info input[type="checkbox"]:checked + label::after,
100 | .abc-checkbox-info input[type="radio"]:checked + label::after {
101 | color: #fff; }
102 |
103 | .abc-checkbox-warning input[type="checkbox"]:checked + label::before,
104 | .abc-checkbox-warning input[type="radio"]:checked + label::before {
105 | background-color: #ffc107;
106 | border-color: #ffc107; }
107 | .abc-checkbox-warning input[type="checkbox"]:checked + label::after,
108 | .abc-checkbox-warning input[type="radio"]:checked + label::after {
109 | color: #fff; }
110 |
111 | .abc-checkbox-success input[type="checkbox"]:checked + label::before,
112 | .abc-checkbox-success input[type="radio"]:checked + label::before {
113 | background-color: #28a745;
114 | border-color: #28a745; }
115 | .abc-checkbox-success input[type="checkbox"]:checked + label::after,
116 | .abc-checkbox-success input[type="radio"]:checked + label::after {
117 | color: #fff; }
118 |
119 | .abc-checkbox-primary input[type="checkbox"]:indeterminate + label::before,
120 | .abc-checkbox-primary input[type="radio"]:indeterminate + label::before {
121 | background-color: #007bff;
122 | border-color: #007bff; }
123 | .abc-checkbox-primary input[type="checkbox"]:indeterminate + label::after,
124 | .abc-checkbox-primary input[type="radio"]:indeterminate + label::after {
125 | background-color: #fff; }
126 |
127 | .abc-checkbox-danger input[type="checkbox"]:indeterminate + label::before,
128 | .abc-checkbox-danger input[type="radio"]:indeterminate + label::before {
129 | background-color: #dc3545;
130 | border-color: #dc3545; }
131 | .abc-checkbox-danger input[type="checkbox"]:indeterminate + label::after,
132 | .abc-checkbox-danger input[type="radio"]:indeterminate + label::after {
133 | background-color: #fff; }
134 |
135 | .abc-checkbox-info input[type="checkbox"]:indeterminate + label::before,
136 | .abc-checkbox-info input[type="radio"]:indeterminate + label::before {
137 | background-color: #17a2b8;
138 | border-color: #17a2b8; }
139 | .abc-checkbox-info input[type="checkbox"]:indeterminate + label::after,
140 | .abc-checkbox-info input[type="radio"]:indeterminate + label::after {
141 | background-color: #fff; }
142 |
143 | .abc-checkbox-warning input[type="checkbox"]:indeterminate + label::before,
144 | .abc-checkbox-warning input[type="radio"]:indeterminate + label::before {
145 | background-color: #ffc107;
146 | border-color: #ffc107; }
147 | .abc-checkbox-warning input[type="checkbox"]:indeterminate + label::after,
148 | .abc-checkbox-warning input[type="radio"]:indeterminate + label::after {
149 | background-color: #fff; }
150 |
151 | .abc-checkbox-success input[type="checkbox"]:indeterminate + label::before,
152 | .abc-checkbox-success input[type="radio"]:indeterminate + label::before {
153 | background-color: #28a745;
154 | border-color: #28a745; }
155 | .abc-checkbox-success input[type="checkbox"]:indeterminate + label::after,
156 | .abc-checkbox-success input[type="radio"]:indeterminate + label::after {
157 | background-color: #fff; }
158 |
159 | .abc-radio {
160 | cursor: default;
161 | padding-left: 4px; }
162 | .abc-radio label {
163 | cursor: pointer;
164 | display: inline;
165 | vertical-align: top;
166 | position: relative;
167 | padding-left: 5px; }
168 | .abc-radio label::before {
169 | cursor: pointer;
170 | content: "";
171 | display: inline-block;
172 | position: absolute;
173 | width: 17px;
174 | height: 17px;
175 | top: 2px;
176 | left: 0;
177 | margin-left: -20px;
178 | border: 1px solid rgba(0, 0, 0, 0.15);
179 | border-radius: 50%;
180 | background-color: #fff;
181 | transition: border 0.15s ease-in-out; }
182 | .abc-radio label::after {
183 | cursor: pointer;
184 | display: inline-block;
185 | position: absolute;
186 | content: " ";
187 | width: 11px;
188 | height: 11px;
189 | left: 3px;
190 | top: 5px;
191 | margin-left: -20px;
192 | border-radius: 50%;
193 | background-color: #495057;
194 | transform: scale(0, 0);
195 | transition: transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33); }
196 | .abc-radio input[type="radio"] {
197 | position: static;
198 | margin-left: 0;
199 | cursor: pointer;
200 | opacity: 0;
201 | z-index: 1; }
202 | .abc-radio input[type="radio"]:focus + label::before {
203 | outline: thin dotted;
204 | outline: 5px auto -webkit-focus-ring-color;
205 | outline-offset: -2px; }
206 | .abc-radio input[type="radio"]:checked + label::after {
207 | transform: scale(1, 1); }
208 | .abc-radio input[type="radio"]:disabled + label {
209 | opacity: 0.65; }
210 | .abc-radio input[type="radio"]:disabled + label::before {
211 | cursor: not-allowed; }
212 | .abc-radio input[type="radio"]:disabled + label::after {
213 | cursor: not-allowed; }
214 | .abc-radio.radio-inline {
215 | margin-top: 0; }
216 |
217 | .abc-radio-primary input[type="radio"] + label::after {
218 | background-color: #007bff; }
219 | .abc-radio-primary input[type="radio"]:checked + label::before {
220 | border-color: #007bff; }
221 | .abc-radio-primary input[type="radio"]:checked + label::after {
222 | background-color: #007bff; }
223 |
224 | .abc-radio-danger input[type="radio"] + label::after {
225 | background-color: #dc3545; }
226 | .abc-radio-danger input[type="radio"]:checked + label::before {
227 | border-color: #dc3545; }
228 | .abc-radio-danger input[type="radio"]:checked + label::after {
229 | background-color: #dc3545; }
230 |
231 | .abc-radio-info input[type="radio"] + label::after {
232 | background-color: #17a2b8; }
233 | .abc-radio-info input[type="radio"]:checked + label::before {
234 | border-color: #17a2b8; }
235 | .abc-radio-info input[type="radio"]:checked + label::after {
236 | background-color: #17a2b8; }
237 |
238 | .abc-radio-warning input[type="radio"] + label::after {
239 | background-color: #ffc107; }
240 | .abc-radio-warning input[type="radio"]:checked + label::before {
241 | border-color: #ffc107; }
242 | .abc-radio-warning input[type="radio"]:checked + label::after {
243 | background-color: #ffc107; }
244 |
245 | .abc-radio-success input[type="radio"] + label::after {
246 | background-color: #28a745; }
247 | .abc-radio-success input[type="radio"]:checked + label::before {
248 | border-color: #28a745; }
249 | .abc-radio-success input[type="radio"]:checked + label::after {
250 | background-color: #28a745; }
251 |
252 | label .was-validated .form-check-input:invalid .abc-checkbox:before, label
253 | .was-validated .form-check-input:invalid .abc-radio:before, label .form-check-input.is-invalid .abc-checkbox:before, label
254 | .form-check-input.is-invalid .abc-radio:before {
255 | border-color: #dc3545; }
256 |
--------------------------------------------------------------------------------
/css/demo-stackslider.css:
--------------------------------------------------------------------------------
1 | html, body, .input-group-addon, .input-group-prepend, .form-control {
2 | font-size: 16px;
3 | }
4 |
5 | .btn {
6 | border: 0 none;
7 | font-weight: bold;
8 | }
9 |
10 | .btn-red {
11 | background-color: #ef476f;
12 | color: #fff;
13 | }
14 |
15 | .btn-red:hover {
16 | color: #ffd166;
17 | }
18 |
19 | .form-control {
20 | color: #073b4c;
21 | }
22 |
23 | .st-wrapper {
24 | overflow: visible;
25 | }
26 |
27 | .st-wrapper nav .st-arrow:before {
28 | content: '' !important;
29 | }
30 |
31 | .st-wrapper nav .st-arrow:after {
32 | content: '';
33 | position: absolute;
34 | top: 50%;
35 | left: 50%;
36 | width: 0;
37 | height: 0;
38 | border-style: solid;
39 | }
40 |
41 | .st-wrapper nav .st-arrow.st-prev:after {
42 | transform: translate(-75%, -50%);
43 | border-width: 7px 7px 7px 0;
44 | border-color: transparent white transparent transparent;
45 | }
46 |
47 | .st-wrapper nav .st-arrow.st-prev:hover:after,
48 | .st-wrapper nav .st-arrow.st-prev:focus:after {
49 | border-color: transparent #ffd166 transparent transparent;
50 | }
51 |
52 | .st-wrapper nav .st-arrow.st-next:after {
53 | transform: translate(-25%, -50%);
54 | border-width: 7px 0 7px 7px;
55 | border-color: transparent transparent transparent white;
56 | }
57 |
58 | .st-wrapper nav .st-arrow.st-next:hover:after,
59 | .st-wrapper nav .st-arrow.st-next:focus:after {
60 | border-color: transparent transparent transparent #ffd166;
61 | }
62 |
63 | .st-wrapper nav .st-arrow.st-disabled,
64 | .st-wrapper nav .st-arrow.st-disabled:before {
65 | cursor: auto;
66 | }
67 |
68 | .st-wrapper nav .st-arrow.st-disabled:before {
69 | background-color: #fff;
70 | }
71 |
72 | .st-wrapper nav .st-arrow.st-prev.st-disabled:after {
73 | border-color: transparent #eee transparent transparent;
74 | }
75 |
76 | .st-wrapper nav .st-arrow.st-next.st-disabled:after {
77 | border-color: transparent transparent transparent #eee;
78 | }
79 |
80 | .surveyjs-wrapper {
81 | background-color: transparent;
82 | color: #fff;
83 | border-radius: 8px;
84 | border: 0 none;
85 | }
86 |
87 | .surveyjs-title {
88 | text-transform: uppercase;
89 | }
90 |
91 | .surveyjs-description {
92 | margin: 0;
93 | }
94 |
95 | .surveyjs-loading p {
96 | margin: 0;
97 | }
98 |
99 | .surveyjs-form {
100 | color: #073b4c;
101 | }
102 |
103 | .surveyjs-loading,
104 | .surveyjs-message {
105 | text-align: center;
106 | color: #fff;
107 | }
108 |
109 | .surveyjs-form .surveyjs-body [data-formjs-question],
110 | .surveyjs-form .surveyjs-body .surveyjs-question-wrapper {
111 | background-color: #fff;
112 | color: #073b4c;
113 | border-radius: 8px 8px 0 0;
114 | }
115 |
116 | .surveyjs-form .surveyjs-body .surveyjs-question-wrapper {
117 | padding: 60px 30px 20px;
118 | }
119 |
120 | .surveyjs-form .surveyjs-question-text {
121 | text-transform: inherit;
122 | background-color: inherit;
123 | color: inherit;
124 | border-radius: 0;
125 | }
126 |
127 | .surveyjs-form .surveyjs-question-text,
128 | .surveyjs-form .surveyjs-answers-wrapper,
129 | .surveyjs-form .surveyjs-question-wrapper {
130 | padding: 0;
131 | }
132 |
133 | .surveyjs-footer {
134 | border-top: 4px dashed #073b4c;
135 | padding: 30px;
136 | background-color: #fff;
137 | border-radius: 0 0 8px 8px;
138 | width: 100%;
139 | margin: -1px auto;
140 | max-width: 600px;
141 | }
142 |
143 | .surveyjs-wrapper .alert {
144 | margin-bottom: 0;
145 | margin-top: 15px;
146 | }
147 |
148 | .modal-body h3 {
149 | margin: 0;
150 | }
151 |
152 | .modal-body p {
153 | margin-bottom: 0;
154 | }
155 |
--------------------------------------------------------------------------------
/css/demo.css:
--------------------------------------------------------------------------------
1 |
2 | /* SURVEY */
3 | .surveyjs-wrapper {
4 | background-color: #fff;
5 | color: #073B4C;
6 | border-radius: 8px;
7 | border: 0 none;
8 | }
9 |
10 | .surveyjs-wrapper .card-header-inner {
11 | padding-bottom: 1rem;
12 | border-bottom: 4px dotted #06d6a0;
13 | }
14 |
15 | .surveyjs-title {
16 | text-transform: uppercase;
17 | }
18 |
19 | .surveyjs-description {
20 | margin: 0;
21 | }
22 |
23 | .surveyjs-loading p {
24 | margin: 0;
25 | }
26 |
27 | .surveyjs-form .surveyjs-question-wrapper {
28 | padding-bottom: 30px;
29 | }
30 |
31 | .surveyjs-form .surveyjs-question-text,
32 | .surveyjs-form .surveyjs-answers-wrapper {
33 | padding: 15px;
34 | }
35 | .surveyjs-form .surveyjs-question-text {
36 | background-color: #06d6a0;
37 | color: #fff;
38 | border-radius: 8px;
39 | }
40 |
41 | .surveyjs-form .input-group .form-control,
42 | .surveyjs-form .input-group .surveyjs-select:not([size]):not([multiple]) {
43 | height: auto;
44 | }
45 |
46 | .surveyjs-form .surveyjs-submit-btn.surveyjs-submit-sending .surveyjs-submit-text {
47 | display: none;
48 | }
49 |
50 | .surveyjs-form .surveyjs-submit-btn.surveyjs-submit-sending:before {
51 | content: 'Sending data...';
52 | }
53 |
54 | .surveyjs-footer {
55 | border-top: 4px dotted #06d6a0;
56 | padding-top: 15px;
57 | }
58 |
59 | .surveyjs-wrapper .alert {
60 | margin-bottom: 0;
61 | margin-top: 15px;
62 | }
63 |
64 | .surveyjs-wrapper .surveyjs-nested-inner {
65 | padding-left: 20px;
66 | }
67 |
68 | .surveyjs-wrapper .input-group {
69 | margin-left: -0.75em;
70 | margin-top: 0.3125em;
71 | margin-bottom: 0.3125em;
72 | width: auto;
73 | }
74 |
75 | .surveyjs-wrapper .input-group .form-check-input {
76 | position: static;
77 | margin: 0;
78 | }
79 |
80 | .surveyjs-wrapper .input-group .surveyjs-label {
81 | padding-left: .3125rem;
82 | }
83 |
84 | .surveyjs-wrapper .surveyjs-errors-wrapper,
85 | .surveyjs-wrapper .surveyjs-footer {
86 | display: none;
87 | }
88 |
89 | .surveyjs-wrapper .has-error .surveyjs-errors-wrapper,
90 | .surveyjs-wrapper.surveyjs-init-success .surveyjs-footer {
91 | display: block;
92 | }
93 |
94 | .surveyjs-wrapper .surveyjs-errors-wrapper {
95 | padding: 0 15px;
96 | }
97 |
98 | /* SURVEY WITH CUSTOM INPUTS */
99 | .surveyjs-wrapper.surveyjs-custom-inputs .form-check.abc-checkbox,
100 | .surveyjs-wrapper.surveyjs-custom-inputs .form-check.abc-radio {
101 | padding-left: 0;
102 | }
103 |
104 | .surveyjs-wrapper.surveyjs-custom-inputs .form-check .surveyjs-input[type="checkbox"],
105 | .surveyjs-wrapper.surveyjs-custom-inputs .form-check .surveyjs-input[type="radio"] {
106 | width: 17px;
107 | margin: 0;
108 | padding: 0;
109 | }
110 |
111 | /* INHERIT THESE PROPS VALUES IS USEFUL DUE TO BOOTSTRAP INCONSISTENCY USAGE OF CSS CLASS custom-select */
112 | .surveyjs-wrapper.surveyjs-custom-inputs .surveyjs-field-container.custom-select {
113 | height: inherit;
114 | padding: inherit;
115 | background: inherit;
116 | border: inherit;
117 | }
118 |
119 | .surveyjs-wrapper.surveyjs-custom-inputs .surveyjs-label:before,
120 | .surveyjs-wrapper.surveyjs-custom-inputs .surveyjs-label:after {
121 | margin-left: -17px;
122 | }
123 |
124 | .surveyjs-wrapper.surveyjs-custom-inputs .surveyjs-nested-wrapper > .surveyjs-label.custom-control-label:before,
125 | .surveyjs-wrapper.surveyjs-custom-inputs .surveyjs-nested-wrapper > .surveyjs-label.custom-control-label:after {
126 | display: none;
127 | }
128 |
129 | .surveyjs-wrapper.surveyjs-custom-inputs .input-group .input-group-prepend {
130 | padding: 0;
131 | }
132 |
133 | .surveyjs-wrapper.surveyjs-custom-inputs .input-group .custom-control {
134 | padding-left: 2rem;
135 | }
136 |
137 | .surveyjs-wrapper.surveyjs-custom-inputs .input-group .custom-control-label:before,
138 | .surveyjs-wrapper.surveyjs-custom-inputs .input-group .custom-control-label:after {
139 | left: auto;
140 | right: 100%;
141 | margin-right: 5px;
142 | }
143 |
144 | .surveyjs-wrapper.surveyjs-custom-inputs .input-group .custom-control .surveyjs-label {
145 | position: relative;
146 | }
147 |
148 | .surveyjs-wrapper.surveyjs-custom-inputs .custom-control .surveyjs-label:before,
149 | .surveyjs-wrapper.surveyjs-custom-inputs .custom-control .surveyjs-label:after {
150 | margin-left: 0;
151 | }
152 |
153 |
154 |
155 | /* MODAL */
156 | .modal-body h3 {
157 | margin: 0;
158 | }
159 |
160 | .modal-body p {
161 | margin-bottom: 0;
162 | }
163 |
164 |
165 |
166 | /* GENERIC */
167 | .text-white {
168 | color: #fff;
169 | }
170 |
171 | .margin-lg {
172 | margin-top: 30px;
173 | margin-bottom: 30px;
174 | }
175 |
176 |
177 |
178 | /* FIELD ERROR */
179 | .has-error .help-block,
180 | .has-error .control-label,
181 | .has-error .radio,
182 | .has-error .checkbox,
183 | .has-error .radio-inline,
184 | .has-error .checkbox-inline,
185 | .has-error .form-check,
186 | .has-error .form-check-inline,
187 | .has-error.radio label,
188 | .has-error.checkbox label,
189 | .has-error.radio-inline label,
190 | .has-error.checkbox-inline label,
191 | .has-error.form-check label,
192 | .has-error.form-check-inline label
193 | {
194 | color: #ef476f;
195 | }
196 |
197 | .has-error .custom-select,
198 | .has-error .custom-select:focus,
199 | .has-error .form-control,
200 | .has-error .form-control:focus {
201 | border-color: #ef476f;
202 | border-width: 2px;
203 | -webkit-box-shadow: none;
204 | box-shadow: none;
205 | }
206 |
207 | .has-error .input-group-addon,
208 | .has-error .input-group-prepend .input-group-text {
209 | color: #ef476f;
210 | border-width: 2px;
211 | border-color: #ef476f;
212 | border-right-color: #ef476f;
213 | background-color: #fcdde4;
214 | }
215 |
216 |
217 |
218 | /* TOGGABLE CONTENT */
219 | .toggable-content-outer .fake-checkbox.btn-toggable-content,
220 | .toggable-content-outer .fake-checkbox.btn-toggable-content ~ .toggable-label span,
221 | .toggable-content-outer .toggable-content {
222 | display: none;
223 | }
224 |
225 | .toggable-content-outer .toggable-label {
226 | position: relative;
227 | }
228 |
229 | .toggable-content-outer .toggable-label span {
230 | cursor: pointer;
231 | font-size: 1rem;
232 | }
233 |
234 | .toggable-content-outer .toggable-label span:after {
235 | display: inline-block;
236 | margin-left: .255em;
237 | vertical-align: .255em;
238 | content: "";
239 | border-right: .3em solid transparent;
240 | border-bottom: 0;
241 | border-left: .3em solid transparent;
242 | }
243 |
244 | .toggable-content-outer .toggable-label span:first-child:after {
245 | border-top: .3em solid;
246 | border-top-color: #ef476f;
247 | }
248 |
249 | .toggable-content-outer .toggable-label span:last-child:after {
250 | border-bottom: .3em solid;
251 | border-bottom-color: #ef476f;
252 | }
253 |
254 | .toggable-content-outer .fake-checkbox.btn-toggable-content:not(:checked) ~ .toggable-label span:first-child {
255 | display: block;
256 | }
257 |
258 | .toggable-content-outer .fake-checkbox.btn-toggable-content:checked ~ .toggable-label span:last-child,
259 | .toggable-content-outer .fake-checkbox.btn-toggable-content:checked ~ .toggable-content {
260 | display: block;
261 | }
262 |
--------------------------------------------------------------------------------
/css/doc.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | font-size: 16px;
3 | font-family: 'Raleway', sans-serif;
4 | }
5 |
6 | body {
7 | background-color: #073b4c;
8 | color: #06d6a0;
9 | }
10 |
11 | ul, ol {
12 | padding-left: 1em;
13 | }
14 |
15 | .card-header p {
16 | margin: 0;
17 | }
18 |
19 | code{display: inline-block;padding: 8px;color: #ccc;background-color: rgba(0,0,0,0.1);border: 2px solid rgba(0,0,0,0.15);border-radius: 4px;}
20 | pre{display: block;padding: 9.5px;margin: 0 0 10px;font-size: 14px;line-height: 1.5;word-break: break-all;word-wrap: break-word;color: #ccc;background-color: rgba(0,0,0,0.1);border: 2px solid rgba(0,0,0,0.15);border-radius: 4px;}
21 | pre code{padding: 0;font-size: inherit;color: inherit;white-space: pre-wrap;background-color: rgba(0,0,0,0.1);border-radius: 0;}
22 |
23 | p code,
24 | li code {
25 | padding: 0 4px;
26 | }
27 |
28 | .btn {
29 | cursor: pointer;
30 | border: 0 none;
31 | border-radius: 8px;
32 | padding: 0.75em 3em;
33 | }
34 |
35 | .overflow-auto {
36 | -webkit-overflow-scrolling: touch;
37 | }
38 |
39 | .container-fluid { max-width: 1400px; }
40 |
41 | body > .container-fluid > div { position: relative; z-index: 0; }
42 | #menu { top: 0; right: 0; z-index: 10; }
43 | #menu a { text-decoration: none !important; }
44 | #menu a.github-logo { border-radius: 100px; border: 2px solid #073b4c; background-color: #073b4c; }
45 | #menu .dropdown, #menu .nav-desktop { top: 0; right: 0; }
46 | /* #menu .nav-desktop, */
47 | #menu .dropdown-toggle { background-color: #073b4c; }
48 | #menu .dropdown-menu,
49 | #hero .dropdown-menu {
50 | left: auto !important; right: 0 !important;
51 | transform: none !important; top: 100% !important;
52 | }
53 |
54 | #hero { min-height: calc(100vh - 120px); z-index: 5; overflow: hidden; }
55 |
56 | a { transition: all 0.15s linear; }
57 | h1, h2, h3 { font-family: 'Expletus Sans', sans-serif; }
58 | h2, h3 { color: #ffd166; margin-top: 2em; }
59 | h1 { font-size: 6em; line-height: 1; display: inline-block; border-bottom: 2px solid rgba(0,0,0,0.15); padding: 0.1em 0.05em; }
60 | h2 { font-size: 3em; border-bottom: 2px solid rgba(0,0,0,0.15); padding: 0.25em 0.0625em; }
61 | h3 { font-size: 2em; }
62 | h1 .small { font-family: 'Raleway', sans-serif; font-size: 0.5em; color: inherit; }
63 | h3 .small { color: inherit; }
64 | .small-title { font-size: 1.25em; }
65 | .claim { font-size: 2rem; }
66 | .logo {
67 | font-family: 'Expletus Sans', sans-serif;
68 | font-size: 32px;
69 | position: absolute;
70 | top: 10px;
71 | left: 0;
72 | width: 40px;
73 | height: 40px;
74 | text-align: center;
75 | border-radius: 1000px;
76 | background-color:#fff;
77 | }
78 | .sticky-title {
79 | position: -webkit-sticky; position: sticky; margin-bottom: 0;
80 | top: 0; z-index: 10; background: #073B4C; border-bottom: 2px solid rgba(0,0,0,0.15);
81 | padding: 0.45em 0.05em 0.33em 52px;
82 | height: 60px;
83 | }
84 | .sticky-title + * { margin-top: 1rem !important; }
85 | .sticky-title + p, .sticky-title + ul { margin-top: 0.5rem !important; }
86 | .sticky-title ~ .panel .sticky-header {
87 | position: -webkit-sticky; position: sticky; top: 98px; z-index: 5;
88 | }
89 | .interline-normal { line-height: 1.2; }
90 | .interline-sm { line-height: 1; }
91 | hr { border-top: 1px solid rgba(0, 0, 0, 0.2); }
92 | .mt-0 { margin-top: 0; }
93 | .ml-4em { margin-left: 4em; }
94 | .title-min { line-height: 0.75; }
95 | .text-yellow { color: #ffd166; }
96 | .text-red { color: #ef476f; }
97 | .text-green { color: #06d6a0; }
98 | .border-red { border-color: #ef476f !important; }
99 | .border-green { border-color: #06d6a0 !important; }
100 | .badge-yellow { background-color: #ffd166; color: #073b4c; }
101 | .text-opacity { opacity: 0.5; }
102 | ul { padding-left: 1em; }
103 | a { color: #ef476f; }
104 | a:hover, a:focus { color: inherit; }
105 | pre { max-height: 355px; }
106 | u { text-decoration: none; border-bottom: 1px solid #06d6a0; }
107 | .panel { background-color: transparent; border-width: 2px; border-radius: 8px; /*color: #ccc;*/ }
108 | .card-header { border: 0 none; border-top-right-radius: 6px; border-top-left-radius: 6px; }
109 | .panel-transparent { color: #ccc; }
110 | .no-bg { background: none; }
111 | .padding-tb-md { padding-top: 1em; padding-bottom: 1em; }
112 | .row-list-separator { border-top: 2px solid rgba(204, 204, 204, 0.2); }
113 | .row-list-separator:first-child { border-top: 0 none; }
114 | .dropdown-menu { min-width: auto; }
115 | .dropdown-toggle.dropdown-red-outline { border: 1px solid #ef476f; color: #ef476f; }
116 | .dropdown-toggle.dropdown-red-outline:after { border-top-color: #ef476f; }
117 | .dropdown-toggle.dropdown-red-outline[aria-expanded="true"] { background-color: #ef476f !important; color: #fff; }
118 | .dropdown-toggle.dropdown-red-outline[aria-expanded="true"]:after { border-top-color: #fff; }
119 | .version-num { min-width: 32px; }
120 | .bg-white {
121 | background-color: #fff;
122 | }
123 | .no-bg {
124 | background-color: transparent !important;
125 | }
126 |
127 | .sticky-nav-2 {
128 | top: 60px;
129 | z-index: 100;
130 | background:#073b4c;
131 | height: 40px;
132 | }
133 | .sticky-nav-2 a {
134 | display: block;
135 | padding: 5px;
136 | white-space: nowrap;
137 | }
138 |
139 | /* PANELS */
140 | .panel {
141 | border: 2px solid #fff;
142 | }
143 | .panel-collapsible .card-header,
144 | .panel-collapsible .panel-heading {
145 | cursor: pointer;
146 | position: relative;
147 | }
148 | .panel-collapsible .panel-heading:after {
149 | content: '\e114';
150 | font-family:'Glyphicons Halflings';
151 | position: absolute;
152 | top: 50%;
153 | right: 15px;
154 | -webkit-transform: translateY(-50%);
155 | transform: translateY(-50%);
156 | }
157 | .panel-collapsible .panel-heading.active:after {
158 | content: '\e113';
159 | }
160 | .panel-collapsible .card-body,
161 | .panel-collapsible .panel-body {
162 | display: none;
163 | }
164 |
165 | .panel-collapsible .card-header > div {
166 | position: relative;
167 | }
168 |
169 | .panel-collapsible .card-header > div:after {
170 | content: '';
171 | position: absolute;
172 | top: 50%;
173 | right: 0;
174 | transform: translateY(-50%);
175 | width: 0;
176 | height: 0;
177 | border-style: solid;
178 | border-width: 7px 7px 0 7px;
179 | border-color: black transparent transparent transparent;
180 | }
181 |
182 | .panel-collapsible .card-header.active > div:after {
183 | border-width: 0 7px 7px 7px;
184 | border-color: transparent transparent black transparent;
185 | }
186 |
187 | .toggable-content-outer .fake-checkbox.btn-toggable-content,
188 | .toggable-content-outer .fake-checkbox.btn-toggable-content ~ .toggable-label span,
189 | .toggable-content-outer .toggable-content {
190 | display: none;
191 | }
192 |
193 | .toggable-content-outer .toggable-label {
194 | position: relative;
195 | }
196 |
197 | .toggable-content-outer .toggable-label.btn {
198 | background-color: #fff;
199 | border: 2px solid #fff;
200 | }
201 |
202 | .toggable-content-outer .toggable-label.btn span:after {
203 | display: none !important;
204 | }
205 |
206 | .toggable-content-outer .toggable-label span {
207 | cursor: pointer;
208 | font-size: 1rem;
209 | }
210 |
211 | .toggable-content-outer .toggable-label span:after {
212 | display: inline-block;
213 | margin-left: .255em;
214 | vertical-align: .255em;
215 | content: "";
216 | border-right: .3em solid transparent;
217 | border-bottom: 0;
218 | border-left: .3em solid transparent;
219 | }
220 |
221 | .toggable-content-outer .toggable-label span:first-child:after {
222 | border-top: .3em solid;
223 | border-top-color: #ef476f;
224 | }
225 |
226 | .toggable-content-outer .toggable-label span:last-child:after {
227 | border-bottom: .3em solid;
228 | border-bottom-color: #ef476f;
229 | }
230 |
231 | .toggable-content-outer .fake-checkbox.btn-toggable-content:checked ~ .toggable-label.btn {
232 | background-color: transparent;
233 | border: 2px solid #06d6a0;
234 | color: #fff;
235 | }
236 |
237 | .toggable-content-outer .fake-checkbox.btn-toggable-content:not(:checked) ~ .toggable-label span:first-child {
238 | display: block;
239 | }
240 |
241 | .toggable-content-outer .fake-checkbox.btn-toggable-content:checked ~ .toggable-label span:last-child,
242 | .toggable-content-outer .fake-checkbox.btn-toggable-content:checked ~ .toggable-content {
243 | display: block;
244 | }
245 |
246 | .toggable-content-outer .fake-checkbox.btn-toggable-content:not(:checked) ~ .panel .validation-list .additional-validation,
247 | .toggable-content-outer .fake-checkbox.btn-toggable-content:not(:checked) ~ .panel .errors-list .additional-error {
248 | display: none !important;
249 | }
250 |
251 | .demos-list > a {
252 | -ms-flex: 0 0 246px;
253 | flex: 0 0 246px;
254 | height: 100px;
255 | margin: 14px;
256 | padding: 14px;
257 | background-color: transparent;
258 | color: #fff;
259 | border: 1px solid #ef476f;
260 | text-decoration: none !important;
261 | transition: all 0.15s linear;
262 | }
263 |
264 | .demos-list > a:hover {
265 | background-color: #ef476f;
266 | color: #fff;
267 | }
268 |
269 | [class*="language-"] {
270 | border: 0 none;
271 | }
272 |
273 | :not(pre) > code[class*="language-"], pre[class*="language-"] {
274 | border: 2px solid rgba(0,0,0,0.15);
275 | }
276 |
277 | footer hr {
278 | border-top: 2px solid rgba(0,0,0,0.15);
279 | }
280 |
281 | @media (max-width: 767px){
282 | h1 { font-size: 4em; }
283 | h2 { font-size: 2.25em; }
284 | h3 { font-size: 1.75em; }
285 | .logo {
286 | font-size: 26px;
287 | top: 10px;
288 | left: 0;
289 | width: 32px;
290 | height: 32px;
291 | }
292 | #menu .dropdown { top: 13px; }
293 | .dropdown-item {
294 | font-size: 20px;
295 | padding-top: 0.5rem;
296 | padding-bottom: 0.5rem;
297 | }
298 | .sticky-title { height: 55px; padding-left: 40px; }
299 | .sticky-nav-2 { top: 55px; }
300 | }
301 |
302 | @media (max-width: 580px){
303 | .demos-list > a {
304 | -ms-flex: 0 0 100%;
305 | flex: 0 0 100%;
306 | margin-left: 0;
307 | margin-right: 0;
308 | }
309 | }
310 |
311 | @media (max-width: 413px){
312 | h1 { font-size: 3em; }
313 | h2 { font-size: 1.75em; }
314 | h3 { font-size: 1.375em; }
315 | .logo { top: 4px; }
316 | #menu .dropdown { top: 7px; }
317 | .sticky-title { height: 43px; }
318 | .sticky-nav-2 { top: 43px; }
319 | }
--------------------------------------------------------------------------------
/css/prism.css:
--------------------------------------------------------------------------------
1 | /* PrismJS 1.19.0
2 | https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript&plugins=line-highlight+file-highlight */
3 | /**
4 | * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
5 | * Based on https://github.com/chriskempson/tomorrow-theme
6 | * @author Rose Pritchard
7 | */
8 |
9 | code[class*="language-"],
10 | pre[class*="language-"] {
11 | color: #ccc;
12 | background: none;
13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
14 | font-size: 1em;
15 | text-align: left;
16 | white-space: pre;
17 | word-spacing: normal;
18 | word-break: normal;
19 | word-wrap: normal;
20 | line-height: 1.5;
21 |
22 | -moz-tab-size: 4;
23 | -o-tab-size: 4;
24 | tab-size: 4;
25 |
26 | -webkit-hyphens: none;
27 | -moz-hyphens: none;
28 | -ms-hyphens: none;
29 | hyphens: none;
30 |
31 | }
32 |
33 | /* Code blocks */
34 | pre[class*="language-"] {
35 | padding: 1em;
36 | margin: .5em 0;
37 | overflow: auto;
38 | }
39 |
40 | :not(pre) > code[class*="language-"],
41 | pre[class*="language-"] {
42 | background: #2d2d2d;
43 | }
44 |
45 | /* Inline code */
46 | :not(pre) > code[class*="language-"] {
47 | padding: .1em;
48 | border-radius: .3em;
49 | white-space: normal;
50 | }
51 |
52 | .token.comment,
53 | .token.block-comment,
54 | .token.prolog,
55 | .token.doctype,
56 | .token.cdata {
57 | color: #999;
58 | }
59 |
60 | .token.punctuation {
61 | color: #ccc;
62 | }
63 |
64 | .token.tag,
65 | .token.attr-name,
66 | .token.namespace,
67 | .token.deleted {
68 | color: #e2777a;
69 | }
70 |
71 | .token.function-name {
72 | color: #6196cc;
73 | }
74 |
75 | .token.boolean,
76 | .token.number,
77 | .token.function {
78 | color: #f08d49;
79 | }
80 |
81 | .token.property,
82 | .token.class-name,
83 | .token.constant,
84 | .token.symbol {
85 | color: #f8c555;
86 | }
87 |
88 | .token.selector,
89 | .token.important,
90 | .token.atrule,
91 | .token.keyword,
92 | .token.builtin {
93 | color: #cc99cd;
94 | }
95 |
96 | .token.string,
97 | .token.char,
98 | .token.attr-value,
99 | .token.regex,
100 | .token.variable {
101 | color: #7ec699;
102 | }
103 |
104 | .token.operator,
105 | .token.entity,
106 | .token.url {
107 | color: #67cdcc;
108 | }
109 |
110 | .token.important,
111 | .token.bold {
112 | font-weight: bold;
113 | }
114 | .token.italic {
115 | font-style: italic;
116 | }
117 |
118 | .token.entity {
119 | cursor: help;
120 | }
121 |
122 | .token.inserted {
123 | color: green;
124 | }
125 |
126 | pre[data-line] {
127 | position: relative;
128 | padding: 1em 0 1em 3em;
129 | }
130 |
131 | .line-highlight {
132 | position: absolute;
133 | left: 0;
134 | right: 0;
135 | padding: inherit 0;
136 | margin-top: 1em; /* Same as .prism’s padding-top */
137 |
138 | background: hsla(24, 20%, 50%,.08);
139 | background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
140 |
141 | pointer-events: none;
142 |
143 | line-height: inherit;
144 | white-space: pre;
145 | }
146 |
147 | .line-highlight:before,
148 | .line-highlight[data-end]:after {
149 | content: attr(data-start);
150 | position: absolute;
151 | top: .4em;
152 | left: .6em;
153 | min-width: 1em;
154 | padding: 0 .5em;
155 | background-color: hsla(24, 20%, 50%,.4);
156 | color: hsl(24, 20%, 95%);
157 | font: bold 65%/1.5 sans-serif;
158 | text-align: center;
159 | vertical-align: .3em;
160 | border-radius: 999px;
161 | text-shadow: none;
162 | box-shadow: 0 1px white;
163 | }
164 |
165 | .line-highlight[data-end]:after {
166 | content: attr(data-end);
167 | top: auto;
168 | bottom: .4em;
169 | }
170 |
171 | .line-numbers .line-highlight:before,
172 | .line-numbers .line-highlight:after {
173 | content: none;
174 | }
175 |
176 |
--------------------------------------------------------------------------------
/css/stackSlider.css:
--------------------------------------------------------------------------------
1 | .js .st-stack-raw {
2 | display: none;
3 | }
4 |
5 | .st-wrapper {
6 | width: 100%;
7 | height: auto;
8 | position: relative;
9 | margin: 0 auto;
10 | padding: 40px 0 0;
11 | overflow: hidden;
12 | }
13 |
14 | .st-stack {
15 | position: absolute;
16 | height: 10px;
17 | bottom: 0px;
18 | background-image: linear-gradient(to bottom, #fff 50%, #e7ae38 50%);
19 | background-size: 5px 5px;
20 | background-position: bottom center;
21 | }
22 |
23 | .st-stack:before {
24 | content: '';
25 | position: absolute;
26 | width: 140%;
27 | left: -20%;
28 | bottom: -10px;
29 | height: 20px;
30 | z-index: -1;
31 | background: radial-gradient(center, ellipse cover, rgba(0,0,0,0.1) 0%,rgba(0,0,0,0) 60%);
32 | }
33 |
34 | .st-stack-left {
35 | left: 0px;
36 | }
37 |
38 | .st-stack-right {
39 | right: 0px;
40 | }
41 |
42 | .st-wrapper .st-title {
43 | color: #fff;
44 | position: absolute;
45 | top: 0;
46 | left: 50%;
47 | margin-left: -40px;
48 | padding: 0;
49 | width: 80px;
50 | height: 80px;
51 | line-height: 80px;
52 | border-radius: 1000px;
53 | text-align: center;
54 | background-color: #06d6a0;
55 | z-index: 2;
56 | }
57 |
58 | .st-wrapper nav {
59 | position: absolute;
60 | width: 100%;
61 | top: 20px;
62 | left: 0;
63 | text-align: center;
64 | -webkit-touch-callout: none;
65 | -webkit-user-select: none;
66 | -khtml-user-select: none;
67 | -moz-user-select: none;
68 | -ms-user-select: none;
69 | user-select: none;
70 | z-index: 3;
71 | }
72 |
73 | .st-wrapper .st-container {
74 | position: relative;
75 | transition: all 0.4s linear;
76 | z-index: 1;
77 | }
78 |
79 | .st-wrapper nav span {
80 | color: transparent;
81 | position: absolute;
82 | width: 40px;
83 | height: 40px;
84 | left: 50%;
85 | top: 0;
86 | cursor: pointer;
87 | }
88 |
89 | .st-wrapper nav span:first-child {
90 | margin-left: -90px;
91 | }
92 |
93 | .st-wrapper nav span:last-child {
94 | margin-left: 50px;
95 | }
96 |
97 | .st-wrapper nav span:before {
98 | font-family: 'Glyphicons Halflings';
99 | font-size: 20px;
100 | font-style: normal;
101 | speak: none;
102 | font-weight: normal;
103 | line-height: 40px;
104 | text-align: center;
105 | -webkit-font-smoothing: antialiased;
106 | position: absolute;
107 | width: 100%;
108 | height: 100%;
109 | left: 0;
110 | color: #fff;
111 | background-color: #ef476f;
112 | border-radius: 50%;
113 | cursor: pointer;
114 | }
115 |
116 | .st-wrapper nav span:first-child:before {
117 | content: "\e079";
118 | }
119 |
120 | .st-wrapper nav span:last-child:before {
121 | content: "\e080";
122 | }
123 |
124 | .st-wrapper nav span:hover:before {
125 | color: #ffd166;
126 | }
127 |
128 | .st-wrapper .st-item {
129 | transform: rotate(-90deg) translateX(-50%) rotateX(90deg);
130 | transform-origin: 50% 0;
131 | transform-style : preserve-3d;
132 | backface-visibility: hidden;
133 | transition: all 0.4s linear;
134 |
135 | position: absolute;
136 | top: 0;
137 | left: 50%;
138 | width: 100%;
139 | margin: 0 auto;
140 | max-width: 600px;
141 | opacity: 0;
142 | z-index: -1;
143 | }
144 |
145 | .st-wrapper .st-item.st-center {
146 | opacity: 1;
147 | transform: rotate(0deg) translateX(-50%) rotateX(0deg);
148 | z-index: 10;
149 | }
150 |
151 | .st-wrapper .st-item.st-leftflow-in {
152 | transform: rotate(-90deg) translateX(-50%) rotateX(0deg);
153 | pointer-events: none;
154 | opacity: 0;
155 | }
156 |
157 | .st-wrapper .st-item.st-rightflow-in {
158 | transform: rotate(90deg) translateX(-50%) rotateX(0deg);
159 | pointer-events: none;
160 | opacity: 0;
161 | }
162 |
163 | .st-wrapper .st-item.st-left,
164 | .st-wrapper .st-item.st-leftflow {
165 | transform: rotate(90deg) translateX(-50%) rotateX(90deg);
166 | pointer-events: none;
167 | opacity: 0;
168 | }
169 |
170 | .st-wrapper .st-item.st-right,
171 | .st-wrapper .st-item.st-rightflow {
172 | transform: rotate(-90deg) translateX(-50%) rotateX(90deg);
173 | pointer-events: none;
174 | opacity: 0;
175 | }
176 |
177 | .st-wrapper .st-item.st-leftflow-in,
178 | .st-wrapper .st-item.st-rightflow-in {
179 | transition-duration: 0.001s !important;
180 | }
181 |
182 | .st-wrapper .st-item.st-center {
183 | opacity: 1;
184 | }
185 |
186 | .surveyjs-cards .st-wrapper .st-item {
187 | transform: translateX(10%) rotate(7deg) rotateY(90deg);
188 | transition: opacity 0.45s linear, transform 0.3s linear;
189 | }
190 |
191 | .surveyjs-cards .st-wrapper .st-item.st-center {
192 | transition-delay: 0.15s;
193 | opacity: 1;
194 | transform: translateX(-50%) rotate(0deg) rotateY(0deg);
195 | }
196 |
197 | .surveyjs-cards .st-wrapper .st-item.st-leftflow-in {
198 | transform: translateX(10%) rotate(7deg) rotateY(0deg);
199 | pointer-events: none;
200 | opacity: 0;
201 | }
202 |
203 | .surveyjs-cards .st-wrapper .st-item.st-rightflow-in {
204 | transform: translateX(-110%) rotate(-7deg) rotateY(0deg);
205 | pointer-events: none;
206 | opacity: 0;
207 | }
208 |
209 | .surveyjs-cards .st-wrapper .st-item.st-leftflow {
210 | transform: translateX(-110%) rotate(-7deg) rotateY(0deg);
211 | pointer-events: none;
212 | opacity: 0;
213 | }
214 |
215 | .surveyjs-cards .st-wrapper .st-item.st-left {
216 | transition-duration: 0.15s;
217 | transform: translateX(-110%) rotate(-7deg) rotateY(90deg);
218 | pointer-events: none;
219 | opacity: 0;
220 | }
221 |
222 | .surveyjs-cards .st-wrapper .st-item.st-rightflow {
223 | transform: translateX(10%) rotate(7deg) rotateY(0deg);
224 | pointer-events: none;
225 | opacity: 0;
226 | }
227 |
228 | .surveyjs-cards .st-wrapper .st-item.st-right {
229 | transition-duration: 0.15s;
230 | transform: translateX(10%) rotate(7deg) rotateY(90deg);
231 | pointer-events: none;
232 | opacity: 0;
233 | }
234 |
235 | .surveyjs-cards .st-wrapper .st-item.st-leftflow-in,
236 | .surveyjs-cards .st-wrapper .st-item.st-rightflow-in {
237 | transition-duration: 0.001s !important;
238 | }
239 |
240 | .surveyjs-cards .st-wrapper .st-item.st-center {
241 | opacity: 1;
242 | }
--------------------------------------------------------------------------------
/demos.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Demos | surveyJS - JavaScript Survey Creation & Management. Made Easy
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
59 |
60 |
61 |
surveyJS
62 |
Demos
63 |
86 |
87 |
88 |
89 |
90 |
91 | Made with passion by Valerio Di Punzio
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/demos/demo-basic-lite.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Demo Basic Lite | surveyJS - JavaScript Survey Creation & Management. Made Easy
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
67 |
68 |
69 |
70 |
71 |
surveyJS
72 | /
73 | Demos
74 |
75 |
76 |
Demo Basic Lite
77 |
78 |
79 |
80 |
81 |
82 |
87 |
88 |
89 | <div class="surveyjs-wrapper card panel-primary mb-4 pt-2" data-surveyjs-wrapper>
90 | <div class="card-header no-bg">
91 | <div class="card-header-inner">
92 | <h3 class="surveyjs-title panel-title text-green mt-0">My Survey</h3>
93 | <p class="surveyjs-description">Answer the questions</p>
94 | </div>
95 | </div>
96 | <div class="card-body">
97 | <form action="../json/survey.json" name="surveyjs-form" class="surveyjs-form" data-surveyjs-form novalidate>
98 | <div class="surveyjs-body questionsList" data-surveyjs-body></div>
99 | <div class="surveyjs-footer">
100 | <button class="btn btn-primary d-block mx-auto" type="submit">SEND</button>
101 | </div>
102 | </form>
103 | </div>
104 | </div>
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
117 |
118 |
119 | // FULL CODE: /js/demos/demo-basic-lite.js
120 | const $form = document.querySelector('[data-surveyjs-form]');
121 | const options = { url: '../json/survey.json' };
122 |
123 | $form.addEventListener('submit', event => {
124 | event.preventDefault();
125 | console.log('FORM SUBMIT');
126 | // FORM VALIDATION IS UP TO YOU :)
127 | });
128 |
129 | const mySurvey = new Survey( $form, options );
130 |
131 |
132 |
133 |
134 |
135 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 | Made with passion by Valerio Di Punzio
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
172 |
173 |
Congratulations!
174 |
175 | You completed the survey and gained 100 points .
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/demos/demo-basic.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Demo Basic | surveyJS - JavaScript Survey Creation & Management. Made Easy
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
69 |
70 |
71 |
72 |
73 |
surveyJS
74 | /
75 | Demos
76 |
77 |
78 |
Demo Basic
79 |
80 |
81 |
82 |
83 |
84 |
89 |
90 |
91 | <div class="surveyjs-wrapper card panel-primary mb-4 pt-2" data-surveyjs-wrapper>
92 | <div class="card-header no-bg">
93 | <div class="card-header-inner">
94 | <h3 class="surveyjs-title panel-title text-green mt-0">My Survey</h3>
95 | <p class="surveyjs-description">Answer the questions</p>
96 | </div>
97 | </div>
98 | <div class="card-body">
99 | <form action="../json/survey.json" name="surveyjs-form" class="surveyjs-form" data-surveyjs-form novalidate>
100 | <div class="surveyjs-body questionsList" data-surveyjs-body></div>
101 | <div class="surveyjs-footer">
102 | <button class="btn btn-primary d-block mx-auto" type="submit">SEND</button>
103 | </div>
104 | </form>
105 | </div>
106 | </div>
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
119 |
120 |
121 | // FULL CODE: /js/demos/demo-basic.js
122 | const $form = document.querySelector('[data-surveyjs-form]');
123 | const options = { url: '../json/survey.json' };
124 |
125 | $form.addEventListener('fjs.form:submit', event => {
126 | event.detail
127 | .then(response => {...})
128 | .catch(error => {...})
129 | .finally(() => {...});
130 | });
131 |
132 | const mySurvey = new Survey( $form, options );
133 |
134 |
135 |
136 |
137 |
138 |
139 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | Made with passion by Valerio Di Punzio
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
176 |
177 |
Congratulations!
178 |
179 | You completed the survey and gained 100 points .
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/dist/lite/surveyjs-esm.min.js:
--------------------------------------------------------------------------------
1 | /* surveyJS Lite v4.0.2 | Valerio Di Punzio (@SimplySayHi) | https://www.valeriodipunzio.com/plugins/surveyJS/ | https://github.com/SimplySayHi/surveyJS | MIT license */
2 | const e=e=>Element.prototype.isPrototypeOf(e),s="sjs:destroy",t="sjs:init",r=e=>(Object.getOwnPropertyNames(e).forEach((s=>{const t=e[s];"object"==typeof t&&null!==t&&r(t)})),Object.freeze(e)),a=e=>"[object Object]"===Object.prototype.toString.call(e),o=function(e={}){return Array.from(arguments).slice(1).filter((e=>!!e)).forEach((s=>{Object.keys(s).forEach((t=>{Array.isArray(s[t])?e[t]=(e[t]||[]).concat(s[t].slice(0)):a(s[t])?e[t]=o(e[t]||{},s[t]):Array.isArray(e[t])?e[t].push(s[t]):e[t]=s[t]}))})),e},i=(e,s,t)=>{t=o({},{bubbles:!0},t);const r=new CustomEvent(s,t);e.dispatchEvent(r)},l=(e,s)=>Object.keys(e).reduce(((s,t)=>{const r=new RegExp("{{"+t+"}}","g");return s.replace(r,e[t])}),s),n=e=>(e[0].sort&&e.sort(((e,s)=>e.sort>s.sort)),e),d=(e=[])=>n(e).reduce(((e,s)=>e+`${s.label} `),""),c=(e,s,t)=>{const r=["data","id","label","nested","related","sort"];/^(option|textarea)$/.test(e.type)&&r.push("type","value");let a="";return Object.keys(e).filter((e=>-1===r.indexOf(e))).forEach((s=>{a+=` ${s}="${e[s]}"`})),e.data&&Object.keys(e.data).forEach((s=>{a+=` data-${((e="",s=!1)=>{let t=e.trim().replace(/(([_ ])([a-z]))|(([a-z])?([A-Z]))/g,((e,s,t,r,a,o,i)=>(r?"-"+r:(o||"")+"-"+i).toLowerCase()));return s?t.toUpperCase():t})(s)}="${e.data[s]}"`})),t&&(a+=" required"),e.related&&(a+=" data-require-more"),a+=` id="${s}"`,a.trim()},u=(e,s,t)=>{let r="",a="";return n(e).forEach(((i,n)=>{let p="";const y="option"===i.type?"select":i.type;if("select"===y&&a===y)return;a=y,s.question.checks&&(i=o({},i,{data:{checks:s.question.checks}}));const m=`${y}-${s.surveyId}-${s.question.id}-${"select"===y?n+1:i.id}`,f={questionNumber:s.question.index+1,wrapperClasses:t.cssClasses.wrapper[y]||t.cssClasses.wrapper.field,fieldAttributes:c(i,m,s.question.isRequired),fieldClasses:t.cssClasses[y]||t.cssClasses.field,answerType:y,answerCode:m,addMoreName:"",labelString:i.label||"",labelClasses:t.cssClasses.label};let v="";if(i.related){const e=i.related.type||"select",s="select"===e,r=s?o({},i):i.related;r.type=s?"option":e,r.id="",r.data=o({},r.data,{requiredFrom:"#"+m}),delete r.related;const a={fieldAttributes:c(r,"",!1),answerType:e,addMoreName:"-more",fieldClasses:s?t.cssClasses.select:t.cssClasses[e]||t.cssClasses.field};if(v=t.templates[e]||t.templates.input,s){const e=d(i.related);v=v.replace("{{optionsHtml}}",e)}v=l(a,v)}const w=((e,s)=>({field:s[e]||s.input,label:/^(checkbox|nested|radio|related)$/.test(e)?s.label:"",wrapper:s.wrapper[e]||s.wrapper.field}))(i.related?"related":i.nested?"nested":y,t.templates);let h="";i.nested&&(h=u(i.nested,s,t));let b="";"select"===y&&(b=d(e)),p=w.wrapper.replace("{{relatedFieldHTML}}",v).replace("{{fieldTemplate}}",w.field).replace("{{optionsHtml}}",b).replace("{{labelTemplate}}",w.label).replace("{{nestedFieldsHTML}}",h),r+=l(f,p)})),r},p=(e,s,t)=>{const r=((e,s,t)=>n(e).reduce(((e,r,o)=>{if(r.external)return e;let i=t.templates.wrapper.question;const n=r.id,d=o+1,c={surveyId:s,question:{id:n,index:o,isRequired:!!r.required}};r.checks&&(c.question.checks=r.checks);const p=u(r.answers,c,t),y=r.checks?JSON.parse(r.checks):"",m=y[0]||"",f=y[1]||"",v=y&&t.messages.maxChoice?" ("+f+" "+t.messages.maxChoice+")":"",w={questionId:n,questionNumber:d,questionText:r.question+v,answersHTML:p};if(i=l(w,i),t.showErrorMessage){let e=""!==y?t.messages.errorMultiChoice:r.errorMessage||t.messages.error;a(e)&&(e=""),i=i.replace(/{{errorTemplates}}/g,e)}return e+l({checksMin:m,checksMax:f},i)}),""))(e.questions,e.id,t);s.querySelector("[data-surveyjs-body]").insertAdjacentHTML("beforeend",r);const o=e.questions.filter((e=>e.external));if(o.length>0){const t=s.closest("[data-surveyjs-wrapper]");o.forEach(((s,r)=>{const a=t.querySelector('[data-surveyjs-external="'+(r+1)+'"]');a.setAttribute("data-question-id",s.id),s.answers.forEach(((t,r)=>{const o=a.querySelectorAll("[data-field]")[r],i={id:`${t.type}-${e.id}-${s.id}-${t.id}`,type:t.type,value:t.value,required:!!s.required};Object.keys(i).forEach((e=>{o[e]=i[e]}));const l=o.closest("[data-answer]");l.querySelector("label").setAttribute("for",i.id),l.querySelector("[data-label]").innerHTML=t.label,a.querySelector("[data-question]").innerHTML=s.question}))}))}};class y{constructor(s,a={}){const l=arguments.length,n=(s=>{const t=typeof s,r="string"===t&&e(document.querySelector(s))&&"form"===document.querySelector(s).tagName.toLowerCase();return{result:e(s)||r,element:"string"===t?document.querySelector(s):s}})(s);if(0===l||l>0&&!s)throw new Error('First argument "$form" is missing or falsy!');if(d=s,NodeList.prototype.isPrototypeOf(d))throw new Error('First argument "$form" must be a single DOM node or a form CSS selector, not a NodeList!');var d;if(!n.result)throw new Error('First argument "$form" is not a DOM node nor a form CSS selector!');if(!a.url||"string"!=typeof a.url)throw new Error('"options.url" is missing or not a string!');const c=this;c.$form=n.element,c.options=o({},y.prototype.options,a),s=c.$form,a=c.options,s.surveyjs=c,s.querySelector("[data-surveyjs-body]").insertAdjacentHTML("beforebegin",a.templates.loading);const u=((e=location.href,s={})=>{let t;if(s.headers=new Headers(s.headers),s.timeout>0){const e=new AbortController,r=e.signal;s.signal=r,t=window.setTimeout((()=>{e.abort()}),s.timeout)}return fetch(e,s).then((e=>{if(!e.ok)throw new Error(e.statusText);return e.json()})).catch((e=>{throw new Error(e.message)})).finally((()=>{t&&window.clearTimeout(t)}))})(a.url,a.initAjaxOptions).then((e=>"success"!==e.status.toLowerCase()?Promise.reject(e):(e.data.questions&&e.data.questions.length>0&&(p(e.data,s,a),Object.defineProperty(c,"data",{value:r(e.data)}),c.isInitialized=!0,s.closest("[data-surveyjs-wrapper]").classList.add("surveyjs-init-success")),e))).finally((()=>{const e=s.querySelector("[data-surveyjs-loading]");e&&e.parentNode.removeChild(e)}));i(s,t,{detail:u})}destroy(){delete this.$form.surveyjs,i(this.$form,s)}static setOptions(e){y.prototype.options=o({},y.prototype.options,e)}}y.prototype.isInitialized=!1,y.prototype.options={cssClasses:{checkbox:"form-check-input",field:"form-control",file:"form-control-file",label:"form-check-label",radio:"form-check-input",wrapper:{checkbox:"form-check",field:"",radio:"form-check"}},initAjaxOptions:{cache:"no-store",credentials:"same-origin",headers:{"Content-Type":"application/json",Accept:"application/json"},method:"GET",mode:"same-origin",redirect:"follow",timeout:0},messages:{maxChoice:"answers max",error:"Answer is necessary.",errorMultiChoice:"You must choose from {{checksMin}} to {{checksMax}} answers."},showErrorMessage:!0,templates:{error:'{{errorMessage}}
',input:' ',label:'{{labelString}} ',loading:'Loading...
',select:'{{optionsHtml}} ',textarea:'',wrapper:{field:'{{fieldTemplate}}{{labelTemplate}}
',nested:'{{labelTemplate}}
{{nestedFieldsHTML}}
',question:'{{questionText}}
{{answersHTML}}
{{errorTemplates}}
',related:''}}},y.prototype.version="4.0.2";export{y as default};
3 | //# sourceMappingURL=surveyjs-esm.min.js.map
4 |
--------------------------------------------------------------------------------
/dist/lite/surveyjs-systemjs.min.js:
--------------------------------------------------------------------------------
1 | /* surveyJS Lite v4.0.2 | Valerio Di Punzio (@SimplySayHi) | https://www.valeriodipunzio.com/plugins/surveyJS/ | https://github.com/SimplySayHi/surveyJS | MIT license */
2 | System.register([],(function(e){"use strict";return{execute:function(){function r(e){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r(e)}function t(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}function s(e,r){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:location.href,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(t.headers=new Headers(t.headers),t.timeout>0){var s=new AbortController,a=s.signal;t.signal=a,e=window.setTimeout((function(){s.abort()}),t.timeout)}return fetch(r,t).then((function(e){if(!e.ok)throw new Error(e.statusText);return e.json()})).catch((function(e){throw new Error(e.message)})).finally((function(){e&&window.clearTimeout(e)}))},o=function(e){return Element.prototype.isPrototypeOf(e)},n=function(e){var t=r(e),s="string"===t&&o(document.querySelector(e))&&"form"===document.querySelector(e).tagName.toLowerCase();return{result:o(e)||s,element:"string"===t?document.querySelector(e):e}},i="sjs:destroy",l="sjs:init",c=function e(t){return Object.getOwnPropertyNames(t).forEach((function(s){var a=t[s];"object"===r(a)&&null!==a&&e(a)})),Object.freeze(t)},u=function(e){return"[object Object]"===Object.prototype.toString.call(e)},d=function e(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return Array.from(arguments).slice(1).filter((function(e){return!!e})).forEach((function(t){Object.keys(t).forEach((function(s){Array.isArray(t[s])?r[s]=(r[s]||[]).concat(t[s].slice(0)):u(t[s])?r[s]=e(r[s]||{},t[s]):Array.isArray(r[s])?r[s].push(t[s]):r[s]=t[s]}))})),r},p=function(e,r,t){t=d({},{bubbles:!0},t);var s=new CustomEvent(r,t);e.dispatchEvent(s)},f=function(e){return NodeList.prototype.isPrototypeOf(e)},v=function(e,r){return Object.keys(e).reduce((function(r,t){var s=new RegExp("{{"+t+"}}","g");return r.replace(s,e[t])}),r)},y=function(e){return e[0].sort&&e.sort((function(e,r){return e.sort>r.sort})),e},m=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return y(e).reduce((function(e,r){return e+'').concat(r.label," ")}),"")},b=function(e,r,t){var s=["data","id","label","nested","related","sort"];/^(option|textarea)$/.test(e.type)&&s.push("type","value");var a="";return Object.keys(e).filter((function(e){return-1===s.indexOf(e)})).forEach((function(r){a+=" ".concat(r,'="').concat(e[r],'"')})),e.data&&Object.keys(e.data).forEach((function(r){a+=" data-".concat(function(){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").trim().replace(/(([_ ])([a-z]))|(([a-z])?([A-Z]))/g,(function(e,r,t,s,a,o,n){return(s?"-"+s:(o||"")+"-"+n).toLowerCase()}));return e?r.toUpperCase():r}(r),'="').concat(e.data[r],'"')})),t&&(a+=" required"),e.related&&(a+=" data-require-more"),(a+=' id="'.concat(r,'"')).trim()},h=function e(r,t,s){var a="",o="";return y(r).forEach((function(n,i){var l,c="option"===n.type?"select":n.type;if("select"!==c||o!==c){o=c,t.question.checks&&(n=d({},n,{data:{checks:t.question.checks}}));var u="".concat(c,"-").concat(t.surveyId,"-").concat(t.question.id,"-").concat("select"===c?i+1:n.id),p={questionNumber:t.question.index+1,wrapperClasses:s.cssClasses.wrapper[c]||s.cssClasses.wrapper.field,fieldAttributes:b(n,u,t.question.isRequired),fieldClasses:s.cssClasses[c]||s.cssClasses.field,answerType:c,answerCode:u,addMoreName:"",labelString:n.label||"",labelClasses:s.cssClasses.label},f="";if(n.related){var y=n.related.type||"select",h="select"===y,w=h?d({},n):n.related;w.type=h?"option":y,w.id="",w.data=d({},w.data,{requiredFrom:"#"+u}),delete w.related;var g={fieldAttributes:b(w,"",!1),answerType:y,addMoreName:"-more",fieldClasses:h?s.cssClasses.select:s.cssClasses[y]||s.cssClasses.field};if(f=s.templates[y]||s.templates.input,h){var j=m(n.related);f=f.replace("{{optionsHtml}}",j)}f=v(g,f)}var q=function(e,r){return{field:r[e]||r.input,label:/^(checkbox|nested|radio|related)$/.test(e)?r.label:"",wrapper:r.wrapper[e]||r.wrapper.field}}(n.related?"related":n.nested?"nested":c,s.templates),C="";n.nested&&(C=e(n.nested,t,s));var T="";"select"===c&&(T=m(r)),l=q.wrapper.replace("{{relatedFieldHTML}}",f).replace("{{fieldTemplate}}",q.field).replace("{{optionsHtml}}",T).replace("{{labelTemplate}}",q.label).replace("{{nestedFieldsHTML}}",C),a+=v(p,l)}})),a},w=function(e,r,t){return y(e).reduce((function(e,s,a){if(s.external)return e;var o=t.templates.wrapper.question,n=s.id,i=a+1,l={surveyId:r,question:{id:n,index:a,isRequired:!!s.required}};s.checks&&(l.question.checks=s.checks);var c=h(s.answers,l,t),d=s.checks?JSON.parse(s.checks):"",p=d[0]||"",f=d[1]||"",y=d&&t.messages.maxChoice?" ("+f+" "+t.messages.maxChoice+")":"",m={questionId:n,questionNumber:i,questionText:s.question+y,answersHTML:c};if(o=v(m,o),t.showErrorMessage){var b=""!==d?t.messages.errorMultiChoice:s.errorMessage||t.messages.error;u(b)&&(b=""),o=o.replace(/{{errorTemplates}}/g,b)}return e+v({checksMin:p,checksMax:f},o)}),"")},g=function(e,r,t){var s=w(e.questions,e.id,t);r.querySelector("[data-surveyjs-body]").insertAdjacentHTML("beforeend",s);var a=e.questions.filter((function(e){return e.external}));if(a.length>0){var o=r.closest("[data-surveyjs-wrapper]");a.forEach((function(r,t){var s=o.querySelector('[data-surveyjs-external="'+(t+1)+'"]');s.setAttribute("data-question-id",r.id),r.answers.forEach((function(t,a){var o=s.querySelectorAll("[data-field]")[a],n={id:"".concat(t.type,"-").concat(e.id,"-").concat(r.id,"-").concat(t.id),type:t.type,value:t.value,required:!!r.required};Object.keys(n).forEach((function(e){o[e]=n[e]}));var i=o.closest("[data-answer]");i.querySelector("label").setAttribute("for",n.id),i.querySelector("[data-label]").innerHTML=t.label,s.querySelector("[data-question]").innerHTML=r.question}))}))}},j=e("default",function(){function e(r){var s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};t(this,e);var o=arguments.length,i=n(r);if(0===o||o>0&&!r)throw new Error('First argument "$form" is missing or falsy!');if(f(r))throw new Error('First argument "$form" must be a single DOM node or a form CSS selector, not a NodeList!');if(!i.result)throw new Error('First argument "$form" is not a DOM node nor a form CSS selector!');if(!s.url||"string"!=typeof s.url)throw new Error('"options.url" is missing or not a string!');var u=this;u.$form=i.element,u.options=d({},e.prototype.options,s),r=u.$form,s=u.options,r.surveyjs=u,r.querySelector("[data-surveyjs-body]").insertAdjacentHTML("beforebegin",s.templates.loading);var v=a(s.url,s.initAjaxOptions).then((function(e){return"success"!==e.status.toLowerCase()?Promise.reject(e):(e.data.questions&&e.data.questions.length>0&&(g(e.data,r,s),Object.defineProperty(u,"data",{value:c(e.data)}),u.isInitialized=!0,r.closest("[data-surveyjs-wrapper]").classList.add("surveyjs-init-success")),e)})).finally((function(){var e=r.querySelector("[data-surveyjs-loading]");e&&e.parentNode.removeChild(e)}));p(r,l,{detail:v})}var r,o,u;return r=e,u=[{key:"setOptions",value:function(r){e.prototype.options=d({},e.prototype.options,r)}}],(o=[{key:"destroy",value:function(){delete this.$form.surveyjs,p(this.$form,i)}}])&&s(r.prototype,o),u&&s(r,u),Object.defineProperty(r,"prototype",{writable:!1}),e}());j.prototype.isInitialized=!1,j.prototype.options={cssClasses:{checkbox:"form-check-input",field:"form-control",file:"form-control-file",label:"form-check-label",radio:"form-check-input",wrapper:{checkbox:"form-check",field:"",radio:"form-check"}},initAjaxOptions:{cache:"no-store",credentials:"same-origin",headers:{"Content-Type":"application/json",Accept:"application/json"},method:"GET",mode:"same-origin",redirect:"follow",timeout:0},messages:{maxChoice:"answers max",error:"Answer is necessary.",errorMultiChoice:"You must choose from {{checksMin}} to {{checksMax}} answers."},showErrorMessage:!0,templates:{error:'{{errorMessage}}
',input:' ',label:'{{labelString}} ',loading:'Loading...
',select:'{{optionsHtml}} ',textarea:'',wrapper:{field:'{{fieldTemplate}}{{labelTemplate}}
',nested:'{{labelTemplate}}
{{nestedFieldsHTML}}
',question:'{{questionText}}
{{answersHTML}}
{{errorTemplates}}
',related:''}}},j.prototype.version="4.0.2"}}}));
3 | //# sourceMappingURL=surveyjs-systemjs.min.js.map
4 |
--------------------------------------------------------------------------------
/dist/lite/surveyjs.min.js:
--------------------------------------------------------------------------------
1 | /* surveyJS Lite v4.0.2 | Valerio Di Punzio (@SimplySayHi) | https://www.valeriodipunzio.com/plugins/surveyJS/ | https://github.com/SimplySayHi/surveyJS | MIT license */
2 | !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(e="undefined"!=typeof globalThis?globalThis:e||self).Survey=r()}(this,(function(){"use strict";function e(r){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(r)}function r(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}function t(e,r){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:location.href,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(t.headers=new Headers(t.headers),t.timeout>0){var s=new AbortController,a=s.signal;t.signal=a,e=window.setTimeout((function(){s.abort()}),t.timeout)}return fetch(r,t).then((function(e){if(!e.ok)throw new Error(e.statusText);return e.json()})).catch((function(e){throw new Error(e.message)})).finally((function(){e&&window.clearTimeout(e)}))},a=function(e){return Element.prototype.isPrototypeOf(e)},o=function(r){var t=e(r),s="string"===t&&a(document.querySelector(r))&&"form"===document.querySelector(r).tagName.toLowerCase();return{result:a(r)||s,element:"string"===t?document.querySelector(r):r}},n="sjs:destroy",i="sjs:init",l=function r(t){return Object.getOwnPropertyNames(t).forEach((function(s){var a=t[s];"object"===e(a)&&null!==a&&r(a)})),Object.freeze(t)},c=function(e){return"[object Object]"===Object.prototype.toString.call(e)},u=function e(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return Array.from(arguments).slice(1).filter((function(e){return!!e})).forEach((function(t){Object.keys(t).forEach((function(s){Array.isArray(t[s])?r[s]=(r[s]||[]).concat(t[s].slice(0)):c(t[s])?r[s]=e(r[s]||{},t[s]):Array.isArray(r[s])?r[s].push(t[s]):r[s]=t[s]}))})),r},d=function(e,r,t){t=u({},{bubbles:!0},t);var s=new CustomEvent(r,t);e.dispatchEvent(s)},p=function(e){return NodeList.prototype.isPrototypeOf(e)},f=function(e,r){return Object.keys(e).reduce((function(r,t){var s=new RegExp("{{"+t+"}}","g");return r.replace(s,e[t])}),r)},y=function(e){return e[0].sort&&e.sort((function(e,r){return e.sort>r.sort})),e},v=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return y(e).reduce((function(e,r){return e+'').concat(r.label," ")}),"")},m=function(e,r,t){var s=["data","id","label","nested","related","sort"];/^(option|textarea)$/.test(e.type)&&s.push("type","value");var a="";return Object.keys(e).filter((function(e){return-1===s.indexOf(e)})).forEach((function(r){a+=" ".concat(r,'="').concat(e[r],'"')})),e.data&&Object.keys(e.data).forEach((function(r){a+=" data-".concat(function(){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"").trim().replace(/(([_ ])([a-z]))|(([a-z])?([A-Z]))/g,(function(e,r,t,s,a,o,n){return(s?"-"+s:(o||"")+"-"+n).toLowerCase()}));return e?r.toUpperCase():r}(r),'="').concat(e.data[r],'"')})),t&&(a+=" required"),e.related&&(a+=" data-require-more"),(a+=' id="'.concat(r,'"')).trim()},b=function e(r,t,s){var a="",o="";return y(r).forEach((function(n,i){var l,c="option"===n.type?"select":n.type;if("select"!==c||o!==c){o=c,t.question.checks&&(n=u({},n,{data:{checks:t.question.checks}}));var d="".concat(c,"-").concat(t.surveyId,"-").concat(t.question.id,"-").concat("select"===c?i+1:n.id),p={questionNumber:t.question.index+1,wrapperClasses:s.cssClasses.wrapper[c]||s.cssClasses.wrapper.field,fieldAttributes:m(n,d,t.question.isRequired),fieldClasses:s.cssClasses[c]||s.cssClasses.field,answerType:c,answerCode:d,addMoreName:"",labelString:n.label||"",labelClasses:s.cssClasses.label},y="";if(n.related){var b=n.related.type||"select",h="select"===b,w=h?u({},n):n.related;w.type=h?"option":b,w.id="",w.data=u({},w.data,{requiredFrom:"#"+d}),delete w.related;var g={fieldAttributes:m(w,"",!1),answerType:b,addMoreName:"-more",fieldClasses:h?s.cssClasses.select:s.cssClasses[b]||s.cssClasses.field};if(y=s.templates[b]||s.templates.input,h){var j=v(n.related);y=y.replace("{{optionsHtml}}",j)}y=f(g,y)}var q=function(e,r){return{field:r[e]||r.input,label:/^(checkbox|nested|radio|related)$/.test(e)?r.label:"",wrapper:r.wrapper[e]||r.wrapper.field}}(n.related?"related":n.nested?"nested":c,s.templates),C="";n.nested&&(C=e(n.nested,t,s));var T="";"select"===c&&(T=v(r)),l=q.wrapper.replace("{{relatedFieldHTML}}",y).replace("{{fieldTemplate}}",q.field).replace("{{optionsHtml}}",T).replace("{{labelTemplate}}",q.label).replace("{{nestedFieldsHTML}}",C),a+=f(p,l)}})),a},h=function(e,r,t){return y(e).reduce((function(e,s,a){if(s.external)return e;var o=t.templates.wrapper.question,n=s.id,i=a+1,l={surveyId:r,question:{id:n,index:a,isRequired:!!s.required}};s.checks&&(l.question.checks=s.checks);var u=b(s.answers,l,t),d=s.checks?JSON.parse(s.checks):"",p=d[0]||"",y=d[1]||"",v=d&&t.messages.maxChoice?" ("+y+" "+t.messages.maxChoice+")":"",m={questionId:n,questionNumber:i,questionText:s.question+v,answersHTML:u};if(o=f(m,o),t.showErrorMessage){var h=""!==d?t.messages.errorMultiChoice:s.errorMessage||t.messages.error;c(h)&&(h=""),o=o.replace(/{{errorTemplates}}/g,h)}return e+f({checksMin:p,checksMax:y},o)}),"")},w=function(e,r,t){var s=h(e.questions,e.id,t);r.querySelector("[data-surveyjs-body]").insertAdjacentHTML("beforeend",s);var a=e.questions.filter((function(e){return e.external}));if(a.length>0){var o=r.closest("[data-surveyjs-wrapper]");a.forEach((function(r,t){var s=o.querySelector('[data-surveyjs-external="'+(t+1)+'"]');s.setAttribute("data-question-id",r.id),r.answers.forEach((function(t,a){var o=s.querySelectorAll("[data-field]")[a],n={id:"".concat(t.type,"-").concat(e.id,"-").concat(r.id,"-").concat(t.id),type:t.type,value:t.value,required:!!r.required};Object.keys(n).forEach((function(e){o[e]=n[e]}));var i=o.closest("[data-answer]");i.querySelector("label").setAttribute("for",n.id),i.querySelector("[data-label]").innerHTML=t.label,s.querySelector("[data-question]").innerHTML=r.question}))}))}},g=function(){function e(t){var a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};r(this,e);var n=arguments.length,c=o(t);if(0===n||n>0&&!t)throw new Error('First argument "$form" is missing or falsy!');if(p(t))throw new Error('First argument "$form" must be a single DOM node or a form CSS selector, not a NodeList!');if(!c.result)throw new Error('First argument "$form" is not a DOM node nor a form CSS selector!');if(!a.url||"string"!=typeof a.url)throw new Error('"options.url" is missing or not a string!');var f=this;f.$form=c.element,f.options=u({},e.prototype.options,a),t=f.$form,a=f.options,t.surveyjs=f,t.querySelector("[data-surveyjs-body]").insertAdjacentHTML("beforebegin",a.templates.loading);var y=s(a.url,a.initAjaxOptions).then((function(e){return"success"!==e.status.toLowerCase()?Promise.reject(e):(e.data.questions&&e.data.questions.length>0&&(w(e.data,t,a),Object.defineProperty(f,"data",{value:l(e.data)}),f.isInitialized=!0,t.closest("[data-surveyjs-wrapper]").classList.add("surveyjs-init-success")),e)})).finally((function(){var e=t.querySelector("[data-surveyjs-loading]");e&&e.parentNode.removeChild(e)}));d(t,i,{detail:y})}var a,c,f;return a=e,f=[{key:"setOptions",value:function(r){e.prototype.options=u({},e.prototype.options,r)}}],(c=[{key:"destroy",value:function(){delete this.$form.surveyjs,d(this.$form,n)}}])&&t(a.prototype,c),f&&t(a,f),Object.defineProperty(a,"prototype",{writable:!1}),e}();return g.prototype.isInitialized=!1,g.prototype.options={cssClasses:{checkbox:"form-check-input",field:"form-control",file:"form-control-file",label:"form-check-label",radio:"form-check-input",wrapper:{checkbox:"form-check",field:"",radio:"form-check"}},initAjaxOptions:{cache:"no-store",credentials:"same-origin",headers:{"Content-Type":"application/json",Accept:"application/json"},method:"GET",mode:"same-origin",redirect:"follow",timeout:0},messages:{maxChoice:"answers max",error:"Answer is necessary.",errorMultiChoice:"You must choose from {{checksMin}} to {{checksMax}} answers."},showErrorMessage:!0,templates:{error:'{{errorMessage}}
',input:' ',label:'{{labelString}} ',loading:'Loading...
',select:'{{optionsHtml}} ',textarea:'',wrapper:{field:'{{fieldTemplate}}{{labelTemplate}}
',nested:'{{labelTemplate}}
{{nestedFieldsHTML}}
',question:'{{questionText}}
{{answersHTML}}
{{errorTemplates}}
',related:''}}},g.prototype.version="4.0.2",g}));
3 | //# sourceMappingURL=surveyjs.min.js.map
4 |
--------------------------------------------------------------------------------
/dist/surveyjs-esm.min.js:
--------------------------------------------------------------------------------
1 | /* surveyJS v4.0.2 | Valerio Di Punzio (@SimplySayHi) | https://www.valeriodipunzio.com/plugins/surveyJS/ | https://github.com/SimplySayHi/surveyJS | MIT license */
2 | import e from"formjs-plugin";const s="sjs:destroy",t="sjs:init",r=e=>(Object.getOwnPropertyNames(e).forEach((s=>{const t=e[s];"object"==typeof t&&null!==t&&r(t)})),Object.freeze(e)),a=e=>"[object Object]"===Object.prototype.toString.call(e),o=function(e={}){return Array.from(arguments).slice(1).filter((e=>!!e)).forEach((s=>{Object.keys(s).forEach((t=>{Array.isArray(s[t])?e[t]=(e[t]||[]).concat(s[t].slice(0)):a(s[t])?e[t]=o(e[t]||{},s[t]):Array.isArray(e[t])?e[t].push(s[t]):e[t]=s[t]}))})),e},i=(e,s,t)=>{t=o({},{bubbles:!0},t);const r=new CustomEvent(s,t);e.dispatchEvent(r)},n=e=>{const s=e.closest("[data-question-id]");return s&&s.getAttribute("data-question-id")||""},l=e=>a(e)&&0===Object.getOwnPropertyNames(e).length,c=(e,s)=>Object.keys(e).reduce(((s,t)=>{const r=new RegExp("{{"+t+"}}","g");return s.replace(r,e[t])}),s),d=e=>(e[0].sort&&e.sort(((e,s)=>e.sort>s.sort)),e),u=()=>{const e=(()=>{const e="check_storage";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(e){return!1}})();return e&&(Storage.prototype.setObject=function(e,s){this.setItem(e,JSON.stringify(s))},Storage.prototype.getObject=function(e){const s=this.getItem(e);return s&&JSON.parse(s)}),{isAvailable:e}},p=(e,s)=>{const t=e.length;let r={};for(let a=0;a{const a=e.type,d=e.name;if(d===i&&a===c)return;e.matches("[data-required-from]")||(i=d,c=a);const u=n(e),m={question:u,answer:{value:s?e.value.trim():e.value||""}};if(!e.matches("[data-required-from]")&&""!==u&&!l(p(t.data.questions,u))){if("radio"===a){const s=(e.closest("form")?r:e.closest(t.options.fieldOptions.questionContainer)).querySelector('[name="'+d+'"]:checked');m.answer.value=s&&s.value||"",s&&s.matches("[data-require-more]")&&(m.answer.related=r.querySelector('[data-required-from="#'+s.id+'"]').value)}"checkbox"===a&&e.matches("[data-checks]")&&(m.answer.value=[],Array.from(r.querySelectorAll('[name="'+d+'"]:checked')).forEach((e=>{m.answer.value.push(e.value)}))),o.answers.push(m)}})),o}}}.formOptions.getFormData},initAjaxOptions:{cache:"no-store",credentials:"same-origin",headers:{"Content-Type":"application/json",Accept:"application/json"},method:"GET",mode:"same-origin",redirect:"follow",timeout:0},messages:{maxChoice:"answers max",error:"Answer is necessary.",errorMultiChoice:"You must choose from {{checksMin}} to {{checksMax}} answers."},showErrorMessage:!0,templates:{error:'{{errorMessage}}
',input:' ',label:'{{labelString}} ',loading:'Loading...
',select:'{{optionsHtml}} ',textarea:'',wrapper:{field:'{{fieldTemplate}}{{labelTemplate}}
',nested:'{{labelTemplate}}
{{nestedFieldsHTML}}
',question:'{{questionText}}
{{answersHTML}}
{{errorTemplates}}
',related:''}},useWebStorage:!0},f={storageName:"Survey_"+location.href+"_{{surveyFormName}}_surveyId[{{surveyId}}]"};function y(e){const s=e.target.surveyjs;e.detail.then((()=>{s.options.useWebStorage&&sessionStorage.removeItem(s.internals.storageName)}))}const v=(e,s,t="")=>{const r=e.length;for(let a=0;a{const t=d.errorMessage[s]||"";return e+(t?o.templates.error.replace("{{errorMessage}}",t):"")}),"");i.innerHTML=s}var u,m,f;if(!e.detail.isCheckingForm&&o.useWebStorage&&!s.matches("[data-exclude-storage]")){const e=r.internals.storageName;let t=sessionStorage.getObject(e)||[];const a=s.name,o=s.value,i=s.matches("[data-required-from]"),n=s.matches("[data-checks]"),l=s.matches("[data-require-more]"),c=i?document.querySelector(s.getAttribute("data-required-from")):null,d=v(t,a+"-more");!l&&!i&&d>=0&&t.splice(d,1);const u=v(t,a,!!n&&o);if(u>=0)t.splice(u,1),(n&&s.checked||!n&&""!==o)&&t.push({name:a,value:o});else if(""!==o){if(i){const e=v(t,c.name);e>=0&&t.splice(e,1),t.push({name:c.name,value:c.value})}t.push({name:a,value:o})}sessionStorage.setObject(e,t)}!d.required||s.required||s.matches("[data-required-from]")||(s.required=!0,r.validateField(s))}const b=(e=[])=>d(e).reduce(((e,s)=>e+`${s.label} `),""),g=(e,s,t)=>{const r=["data","id","label","nested","related","sort"];/^(option|textarea)$/.test(e.type)&&r.push("type","value");let a="";return Object.keys(e).filter((e=>-1===r.indexOf(e))).forEach((s=>{a+=` ${s}="${e[s]}"`})),e.data&&Object.keys(e.data).forEach((s=>{a+=` data-${((e="",s=!1)=>{let t=e.trim().replace(/(([_ ])([a-z]))|(([a-z])?([A-Z]))/g,((e,s,t,r,a,o,i)=>(r?"-"+r:(o||"")+"-"+i).toLowerCase()));return s?t.toUpperCase():t})(s)}="${e.data[s]}"`})),t&&(a+=" required"),e.related&&(a+=" data-require-more"),a+=` id="${s}"`,a.trim()},j=(e,s,t)=>{let r="",a="";return d(e).forEach(((i,n)=>{let l="";const d="option"===i.type?"select":i.type;if("select"===d&&a===d)return;a=d,s.question.checks&&(i=o({},i,{data:{checks:s.question.checks}}));const u=`${d}-${s.surveyId}-${s.question.id}-${"select"===d?n+1:i.id}`,p={questionNumber:s.question.index+1,wrapperClasses:t.cssClasses.wrapper[d]||t.cssClasses.wrapper.field,fieldAttributes:g(i,u,s.question.isRequired),fieldClasses:t.cssClasses[d]||t.cssClasses.field,answerType:d,answerCode:u,addMoreName:"",labelString:i.label||"",labelClasses:t.cssClasses.label};let m="";if(i.related){const e=i.related.type||"select",s="select"===e,r=s?o({},i):i.related;r.type=s?"option":e,r.id="",r.data=o({},r.data,{requiredFrom:"#"+u}),delete r.related;const a={fieldAttributes:g(r,"",!1),answerType:e,addMoreName:"-more",fieldClasses:s?t.cssClasses.select:t.cssClasses[e]||t.cssClasses.field};if(m=t.templates[e]||t.templates.input,s){const e=b(i.related);m=m.replace("{{optionsHtml}}",e)}m=c(a,m)}const f=((e,s)=>({field:s[e]||s.input,label:/^(checkbox|nested|radio|related)$/.test(e)?s.label:"",wrapper:s.wrapper[e]||s.wrapper.field}))(i.related?"related":i.nested?"nested":d,t.templates);let y="";i.nested&&(y=j(i.nested,s,t));let v="";"select"===d&&(v=b(e)),l=f.wrapper.replace("{{relatedFieldHTML}}",m).replace("{{fieldTemplate}}",f.field).replace("{{optionsHtml}}",v).replace("{{labelTemplate}}",f.label).replace("{{nestedFieldsHTML}}",y),r+=c(p,l)})),r},w=(e,s,t)=>{const r=((e,s,t)=>d(e).reduce(((e,r,o)=>{if(r.external)return e;let i=t.templates.wrapper.question;const n=r.id,l=o+1,d={surveyId:s,question:{id:n,index:o,isRequired:!!r.required}};r.checks&&(d.question.checks=r.checks);const u=j(r.answers,d,t),p=r.checks?JSON.parse(r.checks):"",m=p[0]||"",f=p[1]||"",y=p&&t.messages.maxChoice?" ("+f+" "+t.messages.maxChoice+")":"",v={questionId:n,questionNumber:l,questionText:r.question+y,answersHTML:u};if(i=c(v,i),t.showErrorMessage){let e=""!==p?t.messages.errorMultiChoice:r.errorMessage||t.messages.error;a(e)&&(e=""),i=i.replace(/{{errorTemplates}}/g,e)}return e+c({checksMin:m,checksMax:f},i)}),""))(e.questions,e.id,t);s.querySelector("[data-surveyjs-body]").insertAdjacentHTML("beforeend",r);const o=e.questions.filter((e=>e.external));if(o.length>0){const t=s.closest("[data-surveyjs-wrapper]");o.forEach(((s,r)=>{const a=t.querySelector('[data-surveyjs-external="'+(r+1)+'"]');a.setAttribute("data-question-id",s.id),s.answers.forEach(((t,r)=>{const o=a.querySelectorAll("[data-field]")[r],i={id:`${t.type}-${e.id}-${s.id}-${t.id}`,type:t.type,value:t.value,required:!!s.required};Object.keys(i).forEach((e=>{o[e]=i[e]}));const n=o.closest("[data-answer]");n.querySelector("label").setAttribute("for",i.id),n.querySelector("[data-label]").innerHTML=t.label,a.querySelector("[data-question]").innerHTML=s.question}))}))}};class q extends e{constructor(e,s={}){if(!s.url||"string"!=typeof s.url)throw new Error('"options.url" is missing or not a string!');s=o({},q.prototype.options,s),u().isAvailable||(s.useWebStorage=!1),super(e,s);const a=this;a.internals=f;const n=a.$form;s=a.options;const l=a.internals;n.surveyjs=a,n.querySelector("[data-surveyjs-body]").insertAdjacentHTML("beforebegin",s.templates.loading);const c=((e=location.href,s={})=>{let t;if(s.headers=new Headers(s.headers),s.timeout>0){const e=new AbortController,r=e.signal;s.signal=r,t=window.setTimeout((()=>{e.abort()}),s.timeout)}return fetch(e,s).then((e=>{if(!e.ok)throw new Error(e.statusText);return e.json()})).catch((e=>{throw new Error(e.message)})).finally((()=>{t&&window.clearTimeout(t)}))})(s.url,s.initAjaxOptions).then((e=>"success"!==e.status.toLowerCase()?Promise.reject(e):e.data.questions&&e.data.questions.length>0?(l.storageName=l.storageName.replace(/{{surveyId}}/,e.data.id),l.storageName=l.storageName.replace(/{{surveyFormName}}/,n.getAttribute("name")||""),w(e.data,n,s),s.useWebStorage&&((e,s)=>{const t=sessionStorage.getObject(s.storageName);if(t){const s=e.closest("[data-surveyjs-wrapper]");t.forEach((e=>{const t=s.querySelector('[name="'+e.name+'"]'),r=t.matches('[type="radio"], [type="checkbox"]'),a=r?s.querySelector('[name="'+e.name+'"][value="'+e.value+'"]'):t;r?a.checked=!0:a.value=e.value}))}})(n,l),Object.defineProperty(a,"data",{value:r(e.data)}),n.addEventListener("fjs.field:validation",h),n.addEventListener("fjs.form:submit",y),s.formOptions.onInitCheckFilled?a._&&"function"==typeof a._.asyncInitEnd?a._.asyncInitEnd().then((()=>(a.isInitialized=!0,n.closest("[data-surveyjs-wrapper]").classList.add("surveyjs-init-success"),e))):super.validateFilledFields().then((()=>(a.isInitialized=!0,n.closest("[data-surveyjs-wrapper]").classList.add("surveyjs-init-success"),e))):(a.isInitialized=!0,n.closest("[data-surveyjs-wrapper]").classList.add("surveyjs-init-success"),e)):e)).finally((()=>{const e=n.querySelector("[data-surveyjs-loading]");e&&e.parentNode.removeChild(e)}));i(n,t,{detail:c})}destroy(){var e;super.destroy(),(e=this.$form).removeEventListener("fjs.field:validation",h),e.removeEventListener("fjs.form:submit",y),delete e.surveyjs,i(this.$form,s)}static setOptions(e){q.prototype.options=o({},q.prototype.options,e)}}q.prototype.isInitialized=!1,q.prototype.options=m,q.prototype.version="4.0.2";export{q as default};
3 | //# sourceMappingURL=surveyjs-esm.min.js.map
4 |
--------------------------------------------------------------------------------
/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySayHi/surveyJS/d87ef89e7e698e39b0ecd9c2797595b46b5fce7c/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySayHi/surveyJS/d87ef89e7e698e39b0ecd9c2797595b46b5fce7c/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySayHi/surveyJS/d87ef89e7e698e39b0ecd9c2797595b46b5fce7c/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySayHi/surveyJS/d87ef89e7e698e39b0ecd9c2797595b46b5fce7c/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySayHi/surveyJS/d87ef89e7e698e39b0ecd9c2797595b46b5fce7c/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 |
2 | declare module 'surveyjs';
3 |
--------------------------------------------------------------------------------
/js/demo.js:
--------------------------------------------------------------------------------
1 |
2 | var validationRules = {
3 |
4 | alphabetic: function( string ){
5 | var regex = new RegExp(/^[a-z]+$/i),
6 | obj = {
7 | result: regex.test( string )
8 | };
9 |
10 | return obj;
11 | },
12 |
13 | alphabeticExtended: function( string ){
14 | var regex = new RegExp(/^[-'A-ZÀ-ÖØ-öø-ÿ]+$/i),
15 | obj = {
16 | result: regex.test( string )
17 | };
18 |
19 | return obj;
20 | },
21 |
22 | alphanumeric: function( string ){
23 | var regex = new RegExp(/^[\w]+$/i), // OR [a-z0-9_]
24 | obj = {
25 | result: regex.test( string )
26 | };
27 |
28 | return obj;
29 | }
30 |
31 | };
32 |
33 | Form.addValidationRules( validationRules );
34 |
--------------------------------------------------------------------------------
/js/demos/demo-basic-extended.js:
--------------------------------------------------------------------------------
1 |
2 | var $surveyCont = $('[data-surveyjs-wrapper]');
3 | var $form = document.querySelector('[data-surveyjs-form]');
4 | var options = {
5 | url: '../json/survey.json',
6 | cssClasses: {
7 | select: 'custom-select'
8 | },
9 | formOptions: {
10 | beforeSend: function beforeSend_surveyDemo_1( data ){
11 | console.log('Survey beforeSend_surveyDemo_1', data);
12 |
13 | var surveyContEl = this.$form.closest('[data-surveyjs-wrapper]');
14 | var surveyBtn = this.$form.querySelector('button[type="submit"]');
15 |
16 | if( !data.stopExecution ){
17 | surveyBtn.classList.add('surveyjs-submit-sending');
18 | var elemToRemove = surveyContEl.querySelector('.alert');
19 | if(elemToRemove){
20 | elemToRemove.parentNode.removeChild(elemToRemove);
21 | }
22 | }
23 |
24 | return data;
25 | }
26 | }
27 | };
28 |
29 | var onInitSuccess = function( response ){
30 | if( response.status !== 'success' ){
31 | onInitError.call(mySurvey, response);
32 | }
33 | },
34 | onInitError = function( error ){
35 | var $surveyForm = this.$form;
36 | $surveyForm.querySelector('.surveyjs-body').innerHTML = 'Loading Error. Please, reload the page.
';
37 | },
38 | onValidation = function( fields ){
39 | console.log( 'onValidation', fields );
40 | if( fields.length > 1 ){
41 | var isFormSubmitting = $form.classList.contains('is-submitting');
42 | var submitDisabled = $form.querySelector('[type="submit"]').disabled;
43 |
44 | if( (submitDisabled && !isFormSubmitting) || !isFormSubmitting ){
45 | return;
46 | }
47 |
48 | var unanswered = fields.filter(function(obj){
49 | return !obj.result
50 | });
51 | if( unanswered.length > 0 ){
52 | var contEl = unanswered[0].$field.closest('[data-formjs-question]');
53 | scrollToElement(contEl);
54 | }
55 |
56 | } else {
57 | var fieldObj = fields[0];
58 | if( fieldObj.$field.name === 'prova-00' ){
59 | var btn = fieldObj.$field.closest('form').querySelector('[type="submit"]'),
60 | isValidValue = fieldObj.$field.value.trim().length > 0;
61 |
62 | btn.disabled = !isValidValue;
63 | }
64 | }
65 | }
66 | ;
67 |
68 | $form.addEventListener('fjs.field:validation', function(event){
69 | console.log(event.type);
70 | onValidation([event.detail]);
71 | });
72 |
73 | $form.addEventListener('fjs.form:validation', function(event){
74 | console.log(event.type);
75 | onValidation(event.detail.fields);
76 | });
77 |
78 | $form.addEventListener('fjs.form:submit', function(event){
79 | console.log(event.type);
80 | event.detail
81 | .then(function(response){
82 | console.log('then', response);
83 | if( response.status !== 'success' ){
84 | return Promise.reject(response);
85 | }
86 | // REMOVE THE SURVEY FROM THE PAGE
87 | $surveyCont.remove();
88 | // OPEN THE BOOTSTRAP MODAL TO SHOW A CONGRATULATION MESSAGE
89 | $('#modal-notification').modal('show');
90 | })
91 | .catch(function(error){
92 | console.log('catch', error);
93 | // PRINT THE ERROR MESSAGE AFTER THE FORM
94 | var surveyContEl = $form.closest('[data-surveyjs-wrapper]');
95 | surveyContEl.innerHTML = surveyContEl.innerHTML + 'Generic error, please retry.
';
96 | })
97 | .finally(function(){
98 | console.log('finally');
99 | $form.querySelector('button[type="submit"]').classList.remove('surveyjs-submit-sending');
100 | });
101 | });
102 |
103 | $form.addEventListener('sjs:init', function(event){
104 | console.log(event.type);
105 | event.detail
106 | .then(function( data ){
107 | console.log('Survey init then');
108 | console.log(data);
109 | onInitSuccess.call(mySurvey, data);
110 | })
111 | .catch(function( error ){
112 | console.log('Survey init catch');
113 | console.log(error);
114 | onInitError.call(mySurvey, error);
115 | });
116 | });
117 |
118 | var mySurvey = new Survey( $form, options );
119 |
--------------------------------------------------------------------------------
/js/demos/demo-basic-lite.js:
--------------------------------------------------------------------------------
1 |
2 | var $form = document.querySelector('[data-surveyjs-form]');
3 | var options = { url: '../json/survey-simple.json' };
4 |
5 | $form.addEventListener('submit', function( event ){
6 | event.preventDefault();
7 | console.log('FORM SUBMIT');
8 | // FORM VALIDATION IS UP TO YOU :)
9 | });
10 |
11 | var mySurvey = new Survey( $form, options );
12 |
--------------------------------------------------------------------------------
/js/demos/demo-basic.js:
--------------------------------------------------------------------------------
1 |
2 | var $form = document.querySelector('[data-surveyjs-form]');
3 | var options = { url: '../json/survey-simple.json' };
4 |
5 | $form.addEventListener('fjs.form:submit', function(event){
6 | console.log(event.type);
7 | event.detail
8 | .then(function(response){
9 | console.log('then', response);
10 | if( response.status !== 'success' ){
11 | return Promise.reject(response);
12 | }
13 | $('#modal-notification').modal('show');
14 | })
15 | .catch(function(error){
16 | console.log('catch', error);
17 | var surveyContEl = $form.closest('[data-surveyjs-wrapper]');
18 | surveyContEl.innerHTML = surveyContEl.innerHTML + 'Generic error, please retry.
';
19 | })
20 | .finally(function(){
21 | console.log('finally');
22 | });
23 | });
24 |
25 | var mySurvey = new Survey( $form, options );
26 |
--------------------------------------------------------------------------------
/js/demos/demo-stackslider-1.js:
--------------------------------------------------------------------------------
1 | var $surveyCont = $('[data-surveyjs-wrapper]'),
2 | $surveyForm = $surveyCont.find('[data-surveyjs-form]'),
3 | $surveyBtn = $surveyForm.find('.surveyjs-submit-btn');
4 |
5 | var $form = document.querySelector('[data-surveyjs-form]');
6 | var options = {
7 | url: '../json/survey.json',
8 | cssClasses: {
9 | checkbox: 'custom-control-input',
10 | radio: 'custom-control-input',
11 | label: 'custom-control-label',
12 | select: 'custom-select',
13 | wrapper: {
14 | checkbox: 'custom-control form-check',
15 | radio: 'custom-control form-check'
16 | }
17 | },
18 | templates: {
19 | wrapper: {
20 | field: ''+
21 | '{{fieldTemplate}}'+
22 | '{{labelTemplate}}'+
23 | '
',
24 |
25 | question: ''+
26 | '
'+
27 | '
{{questionText}}
'+
28 | '
'+
29 | '{{answersHTML}}'+
30 | '
'+
31 | '
'+
32 | '
',
33 |
34 | related: ''
43 | }
44 | },
45 | formOptions: {
46 | beforeSend: function beforeSend_doc( data ){
47 | console.log('Survey formOptions.beforeSend call...', data);
48 |
49 | if( !data.stopExecution ){
50 | $surveyBtn.addClass('surveyjs-submit-sending');
51 | $surveyCont.find('.alert').remove();
52 | }
53 |
54 | return data;
55 | }
56 | }
57 | };
58 |
59 | var onInitSuccess = function( ajaxData ){
60 | console.log('onInitSuccess', ajaxData);
61 |
62 | var surveyFormEl = this.$form,
63 | surveyBody = surveyFormEl.querySelector('.surveyjs-body'),
64 | initStatus = ajaxData.status;
65 |
66 | if( initStatus === 'success' ){
67 | $('.stackSlider').stackslider({ piles : false });
68 | } else {
69 | var elemToRemove = surveyFormEl.querySelector('.surveyjs-footer');
70 | elemToRemove.parentNode.removeChild(elemToRemove);
71 | surveyBody.innerHTML = 'Loading Error. Please, reload the page.
';
72 | }
73 | },
74 | onInitError = function( error ){
75 | var surveyFormEl = this.$form;
76 |
77 | console.log('onInitError', error);
78 | console.log('SURVEY init(\''+ surveyFormEl.getAttribute('action') +'\') RETURNED AN ERROR:');
79 |
80 | surveyFormEl.querySelector('.surveyjs-body').innerHTML = 'Loading Error. Please, reload the page.
';
81 | },
82 | onValidation = function( fields ){
83 | console.log( 'onValidation', fields );
84 | if( fields.length > 1 ){
85 | if( !$form.querySelector('[type="submit"]').disabled ){
86 | return;
87 | }
88 | // GO TO THE FIRST UNANSWERED QUESTION
89 | var $stWrapper = $('.surveyjs-form .st-wrapper'),
90 | activeIndex = $stWrapper.find('.st-center').index(),
91 | $invalidField = (function(){
92 | for( var f=0; f invalidIndex ? 'prev' : 'next' ),
105 | $btn = ( clickDirection === 'prev' ? $stWrapper.find('nav > span:first-child') : $stWrapper.find('nav > span:last-child') ),
106 | clicksLength = ( clickDirection === 'prev' ? activeIndex - invalidIndex : invalidIndex - activeIndex );
107 |
108 | for(var i=0; iGeneric error, please retry.
' );
151 | }
152 | }
153 | })
154 | .catch(function(error){
155 | console.log('catch', error);
156 | // PRINT THE ERROR MESSAGE AFTER THE FORM
157 | var surveyContEl = $form.closest('[data-surveyjs-wrapper]');
158 | surveyContEl.innerHTML = surveyContEl.innerHTML + 'Generic error, please retry.
';
159 | })
160 | .finally(function(){
161 | console.log('finally');
162 | $form.querySelector('button[type="submit"]').classList.remove('surveyjs-submit-sending');
163 | });
164 | });
165 |
166 | $form.addEventListener('sjs:init', function(event){
167 | console.log(event.type);
168 | event.detail
169 | .then(function( data ){
170 | console.log('Survey init then');
171 | console.log(data);
172 | onInitSuccess.call(mySurvey, data);
173 | })
174 | .catch(function( error ){
175 | console.log('Survey init catch');
176 | console.log(error);
177 | onInitError.call(mySurvey, error);
178 | });
179 | });
180 |
181 | var mySurvey = new Survey( $form, options );
182 |
--------------------------------------------------------------------------------
/js/demos/demo-stackslider-2.js:
--------------------------------------------------------------------------------
1 | var $surveyCont = $('[data-surveyjs-wrapper]'),
2 | $surveyForm = $surveyCont.find('[data-surveyjs-form]'),
3 | $surveyBtn = $surveyForm.find('.surveyjs-submit-btn');
4 |
5 | var $form = document.querySelector('[data-surveyjs-form]');
6 | var options = {
7 | url: '../json/survey.json',
8 | cssClasses: {
9 | select: 'custom-select'
10 | },
11 | templates: {
12 | wrapper: {
13 | field: ''+
14 | '{{fieldTemplate}}'+
15 | '{{labelTemplate}}'+
16 | '
',
17 |
18 | question: ''+
19 | '
'+
20 | '
{{questionText}}
'+
21 | '
'+
22 | '{{answersHTML}}'+
23 | '
'+
24 | '
'+
25 | '
',
26 |
27 | related: ''
36 | }
37 | },
38 | formOptions: {
39 | beforeSend: function beforeSend_doc( data ){
40 | console.log('Survey formOptions.beforeSend call...', data);
41 |
42 | if( !data.stopExecution ){
43 | $surveyBtn.addClass('surveyjs-submit-sending');
44 | $surveyCont.find('.alert').remove();
45 | }
46 |
47 | return data;
48 | }
49 | }
50 | };
51 |
52 | var onInitSuccess = function( ajaxData ){
53 | console.log('onInitSuccess', ajaxData);
54 |
55 | var $surveyForm = this.$form,
56 | surveyBody = $surveyForm.querySelector('.surveyjs-body'),
57 | initStatus = ajaxData.status;
58 |
59 | if( initStatus === 'success' ){
60 | $('.stackSlider').stackslider({ piles : false });
61 | } else {
62 | var elemToRemove = $surveyForm.querySelector('.surveyjs-footer');
63 | elemToRemove.parentNode.removeChild(elemToRemove);
64 | surveyBody.innerHTML = 'Loading Error. Please, reload the page.
';
65 | }
66 | },
67 | onInitError = function( error ){
68 | var $surveyForm = this.$form;
69 |
70 | console.log('onInitError', error);
71 | console.log('SURVEY init(\''+ $surveyForm.getAttribute('action') +'\') RETURNED AN ERROR:');
72 |
73 | $surveyForm.querySelector('.surveyjs-body').innerHTML = 'Loading Error. Please, reload the page.
';
74 | },
75 | onValidation = function( fields ){
76 | if( fields.length > 1 ){
77 | if( !$form.querySelector('[type="submit"]').disabled ){
78 | return;
79 | }
80 | // GO TO THE FIRST UNANSWERED QUESTION
81 | var $stWrapper = $('.surveyjs-form .st-wrapper'),
82 | activeIndex = $stWrapper.find('.st-center').index(),
83 | $invalidField = (function(){
84 | for( var f=0; f invalidIndex ? 'prev' : 'next' ),
97 | $btn = ( clickDirection === 'prev' ? $stWrapper.find('nav > span:first-child') : $stWrapper.find('nav > span:last-child') ),
98 | clicksLength = ( clickDirection === 'prev' ? activeIndex - invalidIndex : invalidIndex - activeIndex );
99 |
100 | for(var i=0; iGeneric error, please retry.
' );
143 | }
144 | }
145 | })
146 | .catch(function(error){
147 | console.log('catch', error);
148 | // PRINT THE ERROR MESSAGE AFTER THE FORM
149 | var surveyContEl = $form.closest('[data-surveyjs-wrapper]');
150 | surveyContEl.innerHTML = surveyContEl.innerHTML + 'Generic error, please retry.
';
151 | })
152 | .finally(function(){
153 | console.log('finally');
154 | $form.querySelector('button[type="submit"]').classList.remove('surveyjs-submit-sending');
155 | });
156 | });
157 |
158 | $form.addEventListener('sjs:init', function(event){
159 | console.log(event.type);
160 | event.detail
161 | .then(function( data ){
162 | console.log('Survey init then');
163 | console.log(data);
164 | onInitSuccess.call(mySurvey, data);
165 | })
166 | .catch(function( error ){
167 | console.log('Survey init catch');
168 | console.log(error);
169 | onInitError.call(mySurvey, error);
170 | });
171 | });
172 |
173 | var mySurvey = new Survey( $form, options );
174 |
--------------------------------------------------------------------------------
/js/demos/doc.js:
--------------------------------------------------------------------------------
1 |
2 | var $surveyCont = $('[data-surveyjs-wrapper]'),
3 | $surveyForm = $surveyCont.find('[data-surveyjs-form]'),
4 | $surveyBtn = $surveyForm.find('.surveyjs-submit-btn');
5 |
6 | var $form = document.querySelector('[data-surveyjs-form]');
7 | var options = {
8 | url: 'json/survey.json',
9 | cssClasses: {
10 | select: 'custom-select'
11 | },
12 | templates: {
13 | wrapper: {
14 | field: ''+
15 | '{{fieldTemplate}}'+
16 | '{{labelTemplate}}'+
17 | '
',
18 |
19 | question: ''+
20 | '
'+
21 | '
{{questionText}}
'+
22 | '
'+
23 | '{{answersHTML}}'+
24 | '
'+
25 | '
'+
26 | '
',
27 |
28 | related: ''
37 | }
38 | },
39 | formOptions: {
40 | beforeSend: function beforeSend_doc( data ){
41 | console.log('Survey formOptions.beforeSend call...', data);
42 |
43 | if( !data.stopExecution ){
44 | $surveyBtn.addClass('surveyjs-submit-sending');
45 | $surveyCont.find('.alert').remove();
46 | }
47 |
48 | return data;
49 | }
50 | }
51 | };
52 |
53 | var onInitSuccess = function( ajaxData ){
54 | if( ajaxData.status === 'success' ){
55 | console.log('init slider');
56 | $('.stackSlider').stackslider({ piles : false });
57 | } else {
58 | onInitError.call(this);
59 | }
60 | },
61 | onInitError = function( error ){
62 | var survey$form = this.$form;
63 | survey$form.querySelector('.surveyjs-body').innerHTML = 'Loading Error. Please, reload the page.
';
64 | },
65 | onValidation = function( fields ){
66 | console.log( 'onValidation', fields );
67 | if( fields.length > 1 ){
68 | if( !$form.querySelector('[type="submit"]').disabled ){
69 | return;
70 | }
71 | // GO TO THE FIRST UNANSWERED QUESTION
72 | var $stWrapper = $('.surveyjs-form .st-wrapper'),
73 | activeIndex = $stWrapper.find('.st-center').index(),
74 | $invalidField = (function(){
75 | for( var f=0; f invalidIndex ? 'prev' : 'next' ),
88 | $btn = ( clickDirection === 'prev' ? $stWrapper.find('nav > span:first-child') : $stWrapper.find('nav > span:last-child') ),
89 | clicksLength = ( clickDirection === 'prev' ? activeIndex - invalidIndex : invalidIndex - activeIndex );
90 |
91 | for(var i=0; iGeneric error, please retry.
' );
134 | }
135 | }
136 | })
137 | .catch(function(error){
138 | console.log('catch', error);
139 | // PRINT THE ERROR MESSAGE AFTER THE FORM
140 | $surveyForm.closest('.surveyjs-wrapper').append( 'Generic error, please retry.
' );
141 | })
142 | .finally(function(){
143 | console.log('finally');
144 | $surveyBtn.removeClass('surveyjs-submit-sending');
145 | });
146 | });
147 |
148 | $form.addEventListener('sjs:init', function(event){
149 | console.log(event.type);
150 | event.detail
151 | .then(function( data ){
152 | console.log('Survey init then');
153 | console.log(data);
154 | onInitSuccess.call(mySurvey, data);
155 | })
156 | .catch(function( error ){
157 | console.log('Survey init catch');
158 | console.log(error);
159 | onInitError.call(mySurvey, error);
160 | });
161 | });
162 |
163 | var mySurvey = new Survey( $form, options );
164 |
--------------------------------------------------------------------------------
/js/include.js:
--------------------------------------------------------------------------------
1 |
2 | function isPlainObject( object ){
3 | return Object.prototype.toString.call( object ) === '[object Object]';
4 | }
5 |
6 | function scrollToElement( element ){
7 | setTimeout(function(){
8 | element.scrollIntoView({ behavior: 'smooth' });
9 | }, 50);
10 | }
11 |
12 | var isLocalEnv = location.protocol.indexOf('http') === -1 || location.host.indexOf('127.0.0.1') > -1;
13 |
14 | document.addEventListener('click', function(e){
15 | var key = e.which || e.keyCode;
16 |
17 | if( key === 1 ){
18 | var elem = e.target,
19 | cardHeaderSelector = '.panel-collapsible .card-header',
20 | dropDownSelector = '[data-toggle="dropdown"]',
21 | checkElement = function( cssSelector ){
22 | return (elem.matches(cssSelector) ? elem : (elem.closest(cssSelector) || null));
23 | };
24 |
25 | // CLOSE ALL OPEN DROPDOWNS
26 | /* if(
27 | !checkElement(dropDownSelector) ||
28 | elem.matches(dropDownSelector+'[aria-expanded="false"]') ||
29 | elem.matches(dropDownSelector+':not([aria-expanded])')
30 | ){
31 | var dropdownsOpen = document.querySelectorAll(dropDownSelector);
32 | if( dropdownsOpen.length > 0 ){
33 | Array.from(dropdownsOpen).forEach(function(dropdownEl){
34 | dropdownEl.setAttribute('aria-expanded', false);
35 | dropdownEl.nextElementSibling.classList.remove('show');
36 | });
37 | }
38 | } */
39 |
40 | if( checkElement(cardHeaderSelector) ){
41 |
42 | // OPEN PANEL
43 | e.preventDefault();
44 |
45 | var cardHeader = checkElement(cardHeaderSelector),
46 | panelEl = elem.closest('.panel').querySelector('.card-body'),
47 | panelDisplay = panelEl.style.display;
48 |
49 | cardHeader.classList.toggle('active');
50 | panelEl.style.display = (panelDisplay === '' || panelDisplay === 'none' ? 'block' : 'none');
51 |
52 | } else if( checkElement(dropDownSelector) ){
53 |
54 | // OPEN DROPDOWN
55 | /* e.preventDefault();
56 |
57 | var dropDown = checkElement(dropDownSelector),
58 | dropDownList = dropDown.nextElementSibling,
59 | dropDownAriaExpanded = dropDown.getAttribute('aria-expanded'),
60 | ariaExpValue = ( !dropDownAriaExpanded || dropDownAriaExpanded === 'false' ? 'true' : 'false' );
61 |
62 | dropDown.setAttribute('aria-expanded', ariaExpValue);
63 | dropDownList.classList.toggle('show'); */
64 |
65 | }
66 | }
67 | }, false);
68 |
69 | document.addEventListener('DOMContentLoaded', function(){
70 | if( window.Survey ){
71 | var version = Survey.prototype.version;
72 | Array.from( document.querySelectorAll('[data-print-current-version]') ).forEach(function( elem ){
73 | elem.innerHTML = version;
74 | });
75 | }
76 | });
77 |
78 | if( document.querySelector('[data-panel="html"] .card-header') ){
79 | document.querySelector('[data-panel="html"] .card-header').click();
80 | }
81 |
82 | if( document.querySelector('[data-panel="js"] .card-header') ){
83 | document.querySelector('[data-panel="js"] .card-header').click();
84 | }
85 |
--------------------------------------------------------------------------------
/js/vendors/modernizr_custom_63321.js:
--------------------------------------------------------------------------------
1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD
2 | * Build: http://modernizr.com/download/#-csstransforms3d-csstransitions-shiv-cssclasses-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes-load
3 | */
4 | ;window.Modernizr=function(a,b,c){function z(a){j.cssText=a}function A(a,b){return z(m.join(a+";")+(b||""))}function B(a,b){return typeof a===b}function C(a,b){return!!~(""+a).indexOf(b)}function D(a,b){for(var d in a){var e=a[d];if(!C(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function E(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:B(f,"function")?f.bind(d||b):f}return!1}function F(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+o.join(d+" ")+d).split(" ");return B(b,"string")||B(b,"undefined")?D(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),E(e,b,c))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["",'"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},x={}.hasOwnProperty,y;!B(x,"undefined")&&!B(x.call,"undefined")?y=function(a,b){return x.call(a,b)}:y=function(a,b){return b in a&&B(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e}),q.csstransforms3d=function(){var a=!!F("perspective");return a&&"webkitPerspective"in g.style&&w("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},q.csstransitions=function(){return F("transition")};for(var G in q)y(q,G)&&(v=G.toLowerCase(),e[v]=q[G](),t.push((e[v]?"":"no-")+v));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)y(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},z(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.testProp=function(a){return D([a])},e.testAllProps=F,e.testStyles=w,e.prefixed=function(a,b,c){return b?F(a,b,c):F(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f 0 && !$form) ){
14 | throw new Error('First argument "$form" is missing or falsy!');
15 | }
16 | if( isNodeList($form) ){
17 | throw new Error('First argument "$form" must be a single DOM node or a form CSS selector, not a NodeList!');
18 | }
19 | if( !checkFormElem.result ){
20 | throw new Error('First argument "$form" is not a DOM node nor a form CSS selector!');
21 | }
22 | if( !optionsObj.url || typeof optionsObj.url !== 'string' ){
23 | throw new Error('"options.url" is missing or not a string!');
24 | }
25 |
26 | const self = this;
27 | self.$form = checkFormElem.element;
28 | self.options = mergeObjects( {}, Survey.prototype.options, optionsObj );
29 | $form = self.$form;
30 | optionsObj = self.options;
31 |
32 | $form.surveyjs = self;
33 | $form.querySelector('[data-surveyjs-body]').insertAdjacentHTML( 'beforebegin', optionsObj.templates.loading );
34 |
35 | // CREATE SURVEY
36 | const retrieveSurvey = ajaxCall(optionsObj.url, optionsObj.initAjaxOptions)
37 | .then(response => {
38 | if( response.status.toLowerCase() !== 'success' ){
39 | return Promise.reject(response);
40 | }
41 | if( response.data.questions && response.data.questions.length > 0 ){
42 | buildSurvey(response.data, $form, optionsObj);
43 | Object.defineProperty(self, 'data', {
44 | value: deepFreeze(response.data)
45 | });
46 | self.isInitialized = true;
47 | $form.closest('[data-surveyjs-wrapper]').classList.add('surveyjs-init-success');
48 | }
49 | return response;
50 | })
51 | .finally(() => {
52 | const $loadingBox = $form.querySelector('[data-surveyjs-loading]');
53 | if( $loadingBox ){
54 | $loadingBox.parentNode.removeChild($loadingBox);
55 | }
56 | });
57 |
58 | dispatchCustomEvent( $form, customEvents.init, { detail: retrieveSurvey } );
59 | }
60 |
61 | destroy(){
62 | delete this.$form.surveyjs;
63 | dispatchCustomEvent( this.$form, customEvents.destroy );
64 | }
65 |
66 | static setOptions( optionsObj ){
67 | Survey.prototype.options = mergeObjects({}, Survey.prototype.options, optionsObj);
68 | }
69 |
70 | }
71 |
72 | Survey.prototype.isInitialized = false;
73 | Survey.prototype.options = options;
74 | Survey.prototype.version = version;
75 |
76 | export default Survey;
77 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 |
2 | import { version } from '../package.json';
3 | import { ajaxCall, customEvents, deepFreeze, dispatchCustomEvent, mergeObjects, webStorage } from './modules/helpers';
4 | import { options } from './modules/options';
5 | import { internals } from './modules/internals';
6 | import { submit, validationEnd } from './modules/listenerCallbacks';
7 | import { buildSurvey } from './modules/buildSurvey/buildSurvey';
8 | import { populateAnswers } from './modules/buildSurvey/populateAnswers';
9 | import { destroy } from './modules/destroy';
10 |
11 | import Form from 'formjs-plugin';
12 |
13 | class Survey extends Form {
14 |
15 | constructor( form, optionsObj = {} ){
16 | if( !optionsObj.url || typeof optionsObj.url !== 'string' ){
17 | throw new Error('"options.url" is missing or not a string!');
18 | }
19 |
20 | optionsObj = mergeObjects( {}, Survey.prototype.options, optionsObj );
21 |
22 | if( !webStorage().isAvailable ){
23 | optionsObj.useWebStorage = false;
24 | }
25 |
26 | // CREATE FORM INSTANCE FOR SURVEY
27 | super( form, optionsObj );
28 | const self = this;
29 | self.internals = internals;
30 | const $form = self.$form;
31 | optionsObj = self.options;
32 | const selfInternals = self.internals;
33 |
34 | $form.surveyjs = self;
35 | $form.querySelector('[data-surveyjs-body]').insertAdjacentHTML( 'beforebegin', optionsObj.templates.loading );
36 |
37 | // CREATE SURVEY
38 | const retrieveSurvey = ajaxCall(optionsObj.url, optionsObj.initAjaxOptions)
39 | .then(response => {
40 | if( response.status.toLowerCase() !== 'success' ){
41 | return Promise.reject(response);
42 | }
43 |
44 | if( response.data.questions && response.data.questions.length > 0 ){
45 | // REPLACE SURVEY ID AND FORM NAME IN WEB STORAGE NAME
46 | selfInternals.storageName = selfInternals.storageName.replace( /{{surveyId}}/, response.data.id );
47 | selfInternals.storageName = selfInternals.storageName.replace( /{{surveyFormName}}/, ($form.getAttribute('name') || '') );
48 |
49 | buildSurvey(response.data, $form, optionsObj);
50 |
51 | if( optionsObj.useWebStorage ){
52 | populateAnswers($form, selfInternals);
53 | }
54 |
55 | Object.defineProperty(self, 'data', {
56 | value: deepFreeze(response.data)
57 | });
58 |
59 | $form.addEventListener('fjs.field:validation', validationEnd);
60 | $form.addEventListener('fjs.form:submit', submit);
61 |
62 | if( optionsObj.formOptions.onInitCheckFilled ){
63 | if( self._ && typeof self._.asyncInitEnd === 'function' ){
64 | return self._.asyncInitEnd()
65 | .then(() => {
66 | self.isInitialized = true;
67 | $form.closest('[data-surveyjs-wrapper]').classList.add('surveyjs-init-success');
68 | return response
69 | });
70 | }
71 |
72 | return super.validateFilledFields().then(() => {
73 | self.isInitialized = true;
74 | $form.closest('[data-surveyjs-wrapper]').classList.add('surveyjs-init-success');
75 | return response
76 | });
77 | }
78 |
79 | self.isInitialized = true;
80 | $form.closest('[data-surveyjs-wrapper]').classList.add('surveyjs-init-success');
81 | return response
82 | }
83 |
84 | return response;
85 | })
86 | .finally(() => {
87 | const $loadingBox = $form.querySelector('[data-surveyjs-loading]');
88 | if( $loadingBox ){
89 | $loadingBox.parentNode.removeChild($loadingBox);
90 | }
91 | });
92 |
93 | dispatchCustomEvent( $form, customEvents.init, { detail: retrieveSurvey } );
94 | }
95 |
96 | destroy(){
97 | super.destroy();
98 | destroy(this.$form);
99 | dispatchCustomEvent( this.$form, customEvents.destroy );
100 | }
101 |
102 | static setOptions( optionsObj ){
103 | Survey.prototype.options = mergeObjects({}, Survey.prototype.options, optionsObj);
104 | }
105 |
106 | }
107 |
108 | Survey.prototype.isInitialized = false;
109 | Survey.prototype.options = options;
110 | Survey.prototype.version = version;
111 |
112 | export default Survey;
113 |
--------------------------------------------------------------------------------
/src/modules-lite/options.js:
--------------------------------------------------------------------------------
1 |
2 | export const options = {
3 | cssClasses: {
4 | checkbox: 'form-check-input',
5 | field: 'form-control',
6 | file: 'form-control-file',
7 | label: 'form-check-label',
8 | radio: 'form-check-input',
9 | wrapper: {
10 | checkbox: 'form-check',
11 | field: '',
12 | radio: 'form-check'
13 | }
14 | },
15 | initAjaxOptions: {
16 | cache: 'no-store',
17 | credentials: 'same-origin',
18 | headers: {
19 | 'Content-Type': 'application/json',
20 | 'Accept': 'application/json'
21 | },
22 | method: 'GET',
23 | mode: 'same-origin',
24 | redirect: 'follow',
25 | timeout: 0
26 | },
27 | messages:{
28 | maxChoice: 'answers max',
29 | error: 'Answer is necessary.',
30 | errorMultiChoice: 'You must choose from {{checksMin}} to {{checksMax}} answers.'
31 | },
32 | showErrorMessage: true,
33 | templates: {
34 | error: '{{errorMessage}}
',
35 |
36 | input: ' ',
37 |
38 | label: '{{labelString}} ',
39 |
40 | loading: 'Loading...
',
41 |
42 | select: ''+
43 | '{{optionsHtml}}'+
44 | ' ',
45 |
46 | textarea: '',
47 |
48 | wrapper: {
49 | field: ''+
50 | '{{fieldTemplate}}'+
51 | '{{labelTemplate}}'+
52 | '
',
53 |
54 | nested: ''+
55 | '{{labelTemplate}}'+
56 | '
'+
57 | '{{nestedFieldsHTML}}'+
58 | '
'+
59 | '
',
60 |
61 | question: ''+
62 | '
{{questionText}}
'+
63 | '
'+
64 | '{{answersHTML}}'+
65 | '
'+
66 | '
{{errorTemplates}}
'+
67 | '
',
68 |
69 | related: ''
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/modules/buildSurvey/buildSurvey.js:
--------------------------------------------------------------------------------
1 |
2 | import { generateQAcode } from './generateQAcode';
3 |
4 | export const buildSurvey = ( data, $form, options ) => {
5 |
6 | const qaHtmlAll = generateQAcode( data.questions, data.id, options );
7 | $form.querySelector('[data-surveyjs-body]').insertAdjacentHTML( 'beforeend', qaHtmlAll );
8 |
9 | // MANAGE EXTERNAL QUESTION
10 | const extQuestions = data.questions.filter(obj => obj.external);
11 | if( extQuestions.length > 0 ){
12 | const $surveyWrapper = $form.closest('[data-surveyjs-wrapper]');
13 | extQuestions.forEach((question, qIndex) => {
14 |
15 | const $externalCont = $surveyWrapper.querySelector('[data-surveyjs-external="'+ (qIndex+1) +'"]');
16 |
17 | $externalCont.setAttribute('data-question-id', question.id);
18 |
19 | question.answers.forEach((answer, aIndex) => {
20 | const $externalField = $externalCont.querySelectorAll('[data-field]')[aIndex];
21 | const fieldProps = {
22 | id: `${answer.type}-${data.id}-${question.id}-${answer.id}`,
23 | type: answer.type,
24 | value: answer.value,
25 | required: !!question.required
26 | };
27 |
28 | Object.keys(fieldProps).forEach(name => {
29 | $externalField[name] = fieldProps[name];
30 | });
31 |
32 | const $answerCont = $externalField.closest('[data-answer]');
33 | $answerCont.querySelector('label').setAttribute('for', fieldProps.id);
34 | $answerCont.querySelector('[data-label]').innerHTML = answer.label;
35 | $externalCont.querySelector('[data-question]').innerHTML = question.question;
36 | });
37 |
38 | });
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/modules/buildSurvey/generateQAcode.js:
--------------------------------------------------------------------------------
1 |
2 | import { isPlainObject, replaceObjectKeysInString, sortList } from '../helpers';
3 | import { generateAnswers } from './generateQAcodeUtils/generateAnswers';
4 |
5 | export const generateQAcode = ( questions, surveyId, options ) => {
6 |
7 | return sortList( questions ).reduce((accCode, questionObj, index) => {
8 | if( questionObj.external ){ return accCode; }
9 |
10 | let questionHTML = options.templates.wrapper.question;
11 | const questionId = questionObj.id;
12 | const questionNumber = index + 1;
13 | const extraData = {
14 | surveyId,
15 | question: {
16 | id: questionId,
17 | index,
18 | isRequired: !!questionObj.required
19 | }
20 | };
21 |
22 | if( questionObj.checks ){
23 | extraData.question.checks = questionObj.checks;
24 | }
25 |
26 | const answersHTML = generateAnswers( questionObj.answers, extraData, options );
27 |
28 | const maxChoice = questionObj.checks ? JSON.parse(questionObj.checks) : '';
29 | const checksMin = maxChoice[0] || '';
30 | const checksMax = maxChoice[1] || '';
31 | const maxChoiceText = maxChoice && options.messages.maxChoice ? ' ('+ checksMax +' '+ options.messages.maxChoice +')' : '';
32 |
33 | const questionData = {
34 | questionId,
35 | questionNumber,
36 | questionText: questionObj.question + maxChoiceText,
37 | answersHTML
38 | };
39 | questionHTML = replaceObjectKeysInString(questionData, questionHTML);
40 |
41 | if( options.showErrorMessage ){
42 | let errorMessage = maxChoice !== '' ? options.messages.errorMultiChoice : (questionObj.errorMessage || options.messages.error);
43 |
44 | // CASE OF MULTIPLE ERROR MESSAGES FROM JSON DATA => DYNAMICALLY MANAGED VIA EVENT LISTENER IN CONSTRUCTOR
45 | if( isPlainObject(errorMessage) ){
46 | errorMessage = '';
47 | }
48 |
49 | questionHTML = questionHTML.replace( /{{errorTemplates}}/g, errorMessage );
50 | }
51 |
52 | return accCode += replaceObjectKeysInString({checksMin, checksMax}, questionHTML);
53 | }, '');
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/modules/buildSurvey/generateQAcodeUtils/generateAnswers.js:
--------------------------------------------------------------------------------
1 |
2 | import { mergeObjects, replaceObjectKeysInString, sortList } from '../../helpers';
3 | import { generateOptionTags } from './generateOptionTags';
4 | import { getAttributesStringHTML } from './getAttributesStringHTML';
5 | import { getTemplates } from './getTemplates';
6 |
7 | export const generateAnswers = ( answersList, extraData, options ) => {
8 |
9 | let allAnswersHTML = '';
10 | let previousType = '';
11 |
12 | sortList( answersList ).forEach((answer, index) => {
13 |
14 | let answerHTML = '';
15 |
16 | // COLLECT USEFUL DATA
17 | // answerType => checkbox, date, email, radio, select, text, textarea, etc...
18 | const answerType = answer.type === 'option' ? 'select' : answer.type;
19 |
20 | if( answerType === 'select' && previousType === answerType ){ return; }
21 |
22 | previousType = answerType;
23 |
24 | if( extraData.question.checks ){
25 | answer = mergeObjects({}, answer, {data:{checks:extraData.question.checks}});
26 | }
27 |
28 | const answerCode = `${answerType}-${extraData.surveyId}-${extraData.question.id}-${answerType === 'select' ? (index + 1) : answer.id}`;
29 | const answerData = {
30 | questionNumber: extraData.question.index + 1,
31 | wrapperClasses: options.cssClasses.wrapper[answerType] || options.cssClasses.wrapper.field,
32 | fieldAttributes: getAttributesStringHTML( answer, answerCode, extraData.question.isRequired ),
33 | fieldClasses: options.cssClasses[answerType] || options.cssClasses.field,
34 |
35 | answerType,
36 | answerCode,
37 | addMoreName: '',
38 |
39 | labelString: answer.label || '',
40 | labelClasses: options.cssClasses.label
41 | };
42 |
43 | let relatedFieldHTML = '';
44 | if( answer.related ){
45 | const relatedType = answer.related.type || 'select';
46 | const relatedIsSelect = relatedType === 'select';
47 | const relatedObj = relatedIsSelect ? mergeObjects({}, answer) : answer.related;
48 |
49 | relatedObj.type = relatedIsSelect ? 'option' : relatedType;
50 | relatedObj.id = '';
51 | relatedObj.data = mergeObjects({}, relatedObj.data, {requiredFrom:'#'+answerCode});
52 | delete relatedObj.related;
53 |
54 | const answerDataRelated = {
55 | fieldAttributes: getAttributesStringHTML(relatedObj, '', false),
56 | answerType: relatedType,
57 | addMoreName: '-more',
58 | fieldClasses: relatedIsSelect ? options.cssClasses.select : (options.cssClasses[relatedType] || options.cssClasses.field)
59 | };
60 |
61 | relatedFieldHTML = options.templates[relatedType] || options.templates.input;
62 | if( relatedIsSelect ){
63 | const optionsHtml = generateOptionTags( answer.related );
64 | relatedFieldHTML = relatedFieldHTML.replace('{{optionsHtml}}', optionsHtml);
65 | }
66 |
67 | relatedFieldHTML = replaceObjectKeysInString(answerDataRelated, relatedFieldHTML);
68 | }
69 |
70 | // TAKE RIGHT TEMPLATES ( wrapper, field and label ) AND PUT ALL TOGETHER
71 | // answerTypeForTemplate => related, input, nested, select, textarea, etc...
72 | const answerTypeForTemplate = answer.related ? 'related' : (answer.nested ? 'nested' : answerType);
73 | const templates = getTemplates( answerTypeForTemplate, options.templates );
74 |
75 | let nestedFieldsHTML = '';
76 | if( answer.nested ){
77 | nestedFieldsHTML = generateAnswers( answer.nested, extraData, options );
78 | }
79 |
80 | let optionsHtml = '';
81 | if( answerType === 'select' ){
82 | optionsHtml = generateOptionTags( answersList );
83 | }
84 |
85 | answerHTML = templates.wrapper
86 | .replace('{{relatedFieldHTML}}', relatedFieldHTML)
87 | .replace('{{fieldTemplate}}', templates.field)
88 | .replace('{{optionsHtml}}', optionsHtml)
89 | .replace('{{labelTemplate}}', templates.label)
90 | .replace('{{nestedFieldsHTML}}', nestedFieldsHTML);
91 | allAnswersHTML += replaceObjectKeysInString(answerData, answerHTML);
92 |
93 | });
94 |
95 | return allAnswersHTML;
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/modules/buildSurvey/generateQAcodeUtils/generateOptionTags.js:
--------------------------------------------------------------------------------
1 |
2 | import { sortList } from '../../helpers';
3 |
4 | export const generateOptionTags = ( optionsList = [] ) => {
5 |
6 | return sortList( optionsList ).reduce((optionsHTML, opt) => {
7 | return optionsHTML += `${opt.label} `;
8 | }, '');
9 |
10 | }
--------------------------------------------------------------------------------
/src/modules/buildSurvey/generateQAcodeUtils/getAttributesStringHTML.js:
--------------------------------------------------------------------------------
1 |
2 | import { toKebabCase } from '../../helpers';
3 |
4 | export const getAttributesStringHTML = ( answerObj, answerCode, isRequired ) => {
5 | const excludedAttrs = ['data', 'id', 'label', 'nested', 'related', 'sort'];
6 |
7 | if( /^(option|textarea)$/.test(answerObj.type) ){
8 | excludedAttrs.push('type', 'value');
9 | }
10 |
11 | let string = '';
12 |
13 | Object.keys(answerObj)
14 | .filter(name => excludedAttrs.indexOf(name) === -1)
15 | .forEach(name => {
16 | string += ` ${name}="${answerObj[name]}"`;
17 | });
18 |
19 | if( answerObj.data ){
20 | Object.keys(answerObj.data).forEach(name => {
21 | string += ` data-${toKebabCase(name)}="${answerObj.data[name]}"`;
22 | });
23 | }
24 |
25 | if( isRequired ){
26 | string += ' required';
27 | }
28 |
29 | if( answerObj.related ){
30 | string += ' data-require-more';
31 | }
32 |
33 | string += ` id="${answerCode}"`;
34 |
35 | return string.trim();
36 | }
37 |
--------------------------------------------------------------------------------
/src/modules/buildSurvey/generateQAcodeUtils/getTemplates.js:
--------------------------------------------------------------------------------
1 |
2 | export const getTemplates = ( answerType, templates ) => {
3 | return {
4 | field: templates[answerType] || templates.input,
5 | label: /^(checkbox|nested|radio|related)$/.test(answerType) ? templates.label : '',
6 | wrapper: templates.wrapper[answerType] || templates.wrapper.field
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/modules/buildSurvey/populateAnswers.js:
--------------------------------------------------------------------------------
1 |
2 | export const populateAnswers = ( $form, internals ) => {
3 |
4 | const WS = sessionStorage.getObject( internals.storageName );
5 | if( WS ){
6 | const $surveyCont = $form.closest('[data-surveyjs-wrapper]');
7 | WS.forEach(item => {
8 | const $fieldFirst = $surveyCont.querySelector( '[name="' + item.name + '"]' ),
9 | isRadioOrCheckbox = $fieldFirst.matches('[type="radio"], [type="checkbox"]'),
10 | $field = ( isRadioOrCheckbox ? $surveyCont.querySelector('[name="' + item.name + '"][value="' + item.value + '"]') : $fieldFirst );
11 |
12 | if( isRadioOrCheckbox ){
13 | $field.checked = true;
14 | } else {
15 | $field.value = item.value;
16 | }
17 | });
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/modules/destroy.js:
--------------------------------------------------------------------------------
1 |
2 | import { submit, validationEnd } from './listenerCallbacks';
3 |
4 | export const destroy = $form => {
5 |
6 | $form.removeEventListener('fjs.field:validation', validationEnd);
7 | $form.removeEventListener('fjs.form:submit', submit);
8 |
9 | delete $form.surveyjs;
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/modules/helpers.js:
--------------------------------------------------------------------------------
1 |
2 | export { ajaxCall } from './helpers/ajaxCall';
3 | export { arrayMove } from './helpers/arrayMove';
4 | export { checkFormEl } from './helpers/checkFormEl';
5 | export { customEvents } from './helpers/customEvents';
6 | export { deepFreeze } from './helpers/deepFreeze';
7 | export { dispatchCustomEvent } from './helpers/dispatchCustomEvent';
8 | export { fieldsStringSelectorSurvey } from './helpers/fieldsStringSelectorSurvey';
9 | export { getQuestionId } from './helpers/getQuestionId';
10 | export { isDOMNode } from './helpers/isDOMNode';
11 | export { isEmptyObject } from './helpers/isEmptyObject';
12 | export { isNodeList } from './helpers/isNodeList';
13 | export { isPlainObject } from './helpers/isPlainObject';
14 | export { mergeObjects } from './helpers/mergeObjects';
15 | export { replaceObjectKeysInString } from './helpers/replaceObjectKeysInString';
16 | export { sortList } from './helpers/sortList';
17 | export { toKebabCase } from './helpers/toKebabCase';
18 | export { webStorage } from './helpers/webStorage';
19 |
--------------------------------------------------------------------------------
/src/modules/helpers/ajaxCall.js:
--------------------------------------------------------------------------------
1 |
2 | export const ajaxCall = ( url = location.href, options = {} ) => {
3 |
4 | let timeoutTimer;
5 |
6 | options.headers = new Headers( options.headers );
7 |
8 | /* SET AbortController FOR timeout */
9 | if ( options.timeout > 0 ) {
10 | const controller = new AbortController();
11 | const signal = controller.signal;
12 |
13 | options.signal = signal;
14 |
15 | timeoutTimer = window.setTimeout(() => {
16 | controller.abort();
17 | }, options.timeout);
18 | }
19 |
20 | return fetch( url, options )
21 | .then(response => {
22 | if( !response.ok ){
23 | throw new Error(response.statusText);
24 | }
25 | return response.json();
26 | })
27 | .catch(error => {
28 | throw new Error(error.message);
29 | })
30 | .finally(() => {
31 | if( timeoutTimer ){
32 | window.clearTimeout( timeoutTimer );
33 | }
34 | });
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/modules/helpers/arrayMove.js:
--------------------------------------------------------------------------------
1 |
2 | export const arrayMove = (array, from, to) => {
3 | array.splice(to, 0, array.splice(from, 1)[0]);
4 | return array;
5 | }
6 |
--------------------------------------------------------------------------------
/src/modules/helpers/checkFormEl.js:
--------------------------------------------------------------------------------
1 |
2 | import { isDOMNode } from './isDOMNode';
3 |
4 | export const checkFormEl = formEl => {
5 |
6 | const isString = typeof formEl,
7 | isValidNodeSelector = isString === 'string' && isDOMNode(document.querySelector(formEl)),
8 | isFormSelector = isValidNodeSelector && document.querySelector(formEl).tagName.toLowerCase() === 'form',
9 | obj = {
10 | result: isDOMNode(formEl) || isFormSelector,
11 | element: (isString === 'string' ? document.querySelector(formEl) : formEl)
12 | };
13 |
14 | return obj;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/modules/helpers/customEvents.js:
--------------------------------------------------------------------------------
1 |
2 | export const customEvents = {
3 | destroy: 'sjs:destroy',
4 | init: 'sjs:init'
5 | }
6 |
--------------------------------------------------------------------------------
/src/modules/helpers/deepFreeze.js:
--------------------------------------------------------------------------------
1 |
2 | export const deepFreeze = obj => {
3 |
4 | Object.getOwnPropertyNames(obj).forEach(name => {
5 | const prop = obj[name];
6 | if( typeof prop === 'object' && prop !== null ){
7 | deepFreeze(prop);
8 | }
9 | });
10 | return Object.freeze(obj);
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/modules/helpers/dispatchCustomEvent.js:
--------------------------------------------------------------------------------
1 |
2 | import { mergeObjects } from './mergeObjects';
3 |
4 | export const dispatchCustomEvent = ( elem, eventName, eventOptions ) => {
5 | eventOptions = mergeObjects({}, { bubbles: true }, eventOptions);
6 | const eventObj = new CustomEvent(eventName, eventOptions);
7 | elem.dispatchEvent( eventObj );
8 | }
9 |
--------------------------------------------------------------------------------
/src/modules/helpers/fieldsStringSelectorSurvey.js:
--------------------------------------------------------------------------------
1 |
2 | export const fieldsStringSelectorSurvey = '[data-surveyjs-form] input:not([type="reset"]):not([type="submit"]):not([type="button"]), [data-surveyjs-form] select, [data-surveyjs-form] textarea, [data-surveyjs-external] [data-field]'
3 |
--------------------------------------------------------------------------------
/src/modules/helpers/getQuestionId.js:
--------------------------------------------------------------------------------
1 |
2 | export const getQuestionId = fieldEl => {
3 | const containerEl = fieldEl.closest('[data-question-id]');
4 | return (containerEl && containerEl.getAttribute('data-question-id')) || '';
5 | }
6 |
--------------------------------------------------------------------------------
/src/modules/helpers/isDOMNode.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-prototype-builtins */
2 |
3 | export const isDOMNode = node => {
4 | return Element.prototype.isPrototypeOf( node );
5 | }
6 |
--------------------------------------------------------------------------------
/src/modules/helpers/isEmptyObject.js:
--------------------------------------------------------------------------------
1 |
2 | import { isPlainObject } from './isPlainObject';
3 |
4 | export const isEmptyObject = object => {
5 | return isPlainObject(object) && Object.getOwnPropertyNames(object).length === 0;
6 | }
7 |
--------------------------------------------------------------------------------
/src/modules/helpers/isNodeList.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-prototype-builtins */
2 |
3 | export const isNodeList = nodeList => {
4 | return NodeList.prototype.isPrototypeOf( nodeList );
5 | }
6 |
--------------------------------------------------------------------------------
/src/modules/helpers/isPlainObject.js:
--------------------------------------------------------------------------------
1 |
2 | export const isPlainObject = object => {
3 | return Object.prototype.toString.call( object ) === '[object Object]';
4 | }
5 |
--------------------------------------------------------------------------------
/src/modules/helpers/mergeObjects.js:
--------------------------------------------------------------------------------
1 |
2 | import { isPlainObject } from './isPlainObject';
3 |
4 | export const mergeObjects = function( out = {} ){
5 | Array.from(arguments).slice(1).filter(arg => !!arg).forEach(arg => {
6 | Object.keys(arg).forEach(key => {
7 | if( Array.isArray(arg[key]) ){
8 | out[key] = (out[key] || []).concat( arg[key].slice(0) );
9 | } else if( isPlainObject(arg[key]) ){
10 | out[key] = mergeObjects((out[key] || {}), arg[key]);
11 | } else {
12 | // * STRING | NUMBER | BOOLEAN | FUNCTION
13 | if( Array.isArray(out[key]) ){
14 | // IF THIS IS ONE OF ABOVE (*) AND THE DESTINATION OBJECT IS AN ARRAY
15 | out[key].push(arg[key]);
16 | } else {
17 | out[key] = arg[key];
18 | }
19 | }
20 | });
21 | });
22 |
23 | return out;
24 | }
25 |
--------------------------------------------------------------------------------
/src/modules/helpers/replaceObjectKeysInString.js:
--------------------------------------------------------------------------------
1 |
2 | export const replaceObjectKeysInString = (obj, stringHTML) => {
3 | return Object.keys(obj).reduce((accString, name) => {
4 | const regexStr = new RegExp( '{{' + name + '}}', 'g' );
5 | return accString.replace(regexStr, obj[name]);
6 | }, stringHTML);
7 | }
8 |
--------------------------------------------------------------------------------
/src/modules/helpers/sortList.js:
--------------------------------------------------------------------------------
1 |
2 | export const sortList = ( list ) => {
3 | if( list[0]['sort'] ){
4 | list.sort((a, b) => a['sort'] > b['sort']);
5 | }
6 | return list;
7 | }
8 |
--------------------------------------------------------------------------------
/src/modules/helpers/toKebabCase.js:
--------------------------------------------------------------------------------
1 |
2 | export const toKebabCase = ( string = '', useAllCaps = false ) => {
3 | let newString = string.trim().replace(/(([_ ])([a-z]))|(([a-z])?([A-Z]))/g, (match, p1, p2, p3, p4, p5, p6) => {
4 | const concatGroup = p3 ? '-' + p3 : (p5 || '') + '-' + p6;
5 | return concatGroup.toLowerCase();
6 | } );
7 | return useAllCaps ? newString.toUpperCase() : newString;
8 | }
9 |
--------------------------------------------------------------------------------
/src/modules/helpers/webStorage.js:
--------------------------------------------------------------------------------
1 |
2 | export const webStorage = () => {
3 |
4 | const checkLocalStorage = () => {
5 | const mod = 'check_storage';
6 | try {
7 | localStorage.setItem(mod, mod);
8 | localStorage.removeItem(mod);
9 | return true;
10 | } catch(e) {
11 | return false;
12 | }
13 | };
14 |
15 | const isAvailable = checkLocalStorage();
16 |
17 | if( isAvailable ){
18 | // setObject METHOD FOR HTML STORAGE -> EG: localStorage.setObject( name, JSobj )
19 | // TO STORE A JS OBJECT ( AS JSON STRING ) INSIDE THE STORAGE
20 | Storage.prototype.setObject = function( key, value ) {
21 | this.setItem( key, JSON.stringify(value) );
22 | }
23 |
24 | // getObject METHOD FOR HTML STORAGE -> EG: localStorage.getObject( name )
25 | // RETURN THE DATA ( STORED AS JSON STRING ) AS JS OBJECT
26 | Storage.prototype.getObject = function( key ) {
27 | const value = this.getItem( key );
28 | return value && JSON.parse( value );
29 | }
30 | }
31 |
32 | return {
33 | isAvailable: isAvailable
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/modules/internals.js:
--------------------------------------------------------------------------------
1 |
2 | export const internals = {
3 | storageName: 'Survey_' + location.href + '_{{surveyFormName}}_surveyId[{{surveyId}}]'
4 | }
5 |
--------------------------------------------------------------------------------
/src/modules/listenerCallbacks.js:
--------------------------------------------------------------------------------
1 |
2 | export { submit } from './listenerCallbacks/submit';
3 | export { validationEnd } from './listenerCallbacks/validationEnd';
4 |
--------------------------------------------------------------------------------
/src/modules/listenerCallbacks/submit.js:
--------------------------------------------------------------------------------
1 |
2 | export function submit( event ){
3 | const self = event.target.surveyjs;
4 | event.detail.then(() => {
5 | if( self.options.useWebStorage ){
6 | sessionStorage.removeItem( self.internals.storageName );
7 | }
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/src/modules/listenerCallbacks/validationEnd.js:
--------------------------------------------------------------------------------
1 |
2 | import { arrayMove, getQuestionId, isEmptyObject, isPlainObject } from '../helpers';
3 | import { getQuestionObject } from '../utils/getQuestionObject';
4 | import { getAnswerIndex } from '../utils/getAnswerIndex';
5 |
6 | export function validationEnd( event ){
7 | const $field = event.detail.$field;
8 | const errors = event.detail.errors;
9 | const instance = $field.closest('form').surveyjs;
10 | const options = instance.options;
11 | const $errorsWrapper = $field.closest( options.fieldOptions.questionContainer ).querySelector('[data-surveyjs-errors]');
12 |
13 | const questionId = getQuestionId($field);
14 | const questionObj = getQuestionObject(instance.data.questions, questionId);
15 |
16 | // IF IT'S NOT A SURVEY QUESTION -> SKIP
17 | if( isEmptyObject(questionObj) ){ return true; }
18 |
19 | // MANAGE MULTIPLE ERROR MESSAGES
20 | if( $errorsWrapper && errors && isPlainObject(questionObj.errorMessage) ){
21 | let errorsList = Object.keys(errors);
22 | if( errors.rule ){
23 | // PUT ERROR "rule" AS FIRST, SO THAT A GENERIC ERROR IS SHOWN BEFORE ALL OTHERS
24 | const ruleIndex = errorsList.indexOf('rule');
25 | errorsList = arrayMove(errorsList, ruleIndex, 0);
26 | }
27 | const errorsHTML = errorsList.reduce((accHTML, name) => {
28 | const errorMessage = questionObj.errorMessage[name] || '';
29 | return accHTML += errorMessage ? options.templates.error.replace('{{errorMessage}}', errorMessage) : '';
30 | }, '');
31 |
32 | $errorsWrapper.innerHTML = errorsHTML;
33 | }
34 |
35 | // MANAGE ITEMS IN LOCAL STORAGE ( IF AVAILABLE AND ACTIVE )
36 | if( !event.detail.isCheckingForm && options.useWebStorage && !$field.matches('[data-exclude-storage]') ){
37 | const storageName = instance.internals.storageName;
38 | let storageArray = sessionStorage.getObject( storageName ) || [];
39 |
40 | const name = $field.name;
41 | const value = $field.value;
42 | const isRequiredFrom = $field.matches('[data-required-from]');
43 | const isMultiChoice = $field.matches('[data-checks]');
44 | const isRequireMore = $field.matches('[data-require-more]');
45 | const $reqMore = isRequiredFrom ? document.querySelector($field.getAttribute('data-required-from')) : null;
46 |
47 | const inArrayRequireMorePos = getAnswerIndex( storageArray, name + '-more' );
48 | if( !isRequireMore && !isRequiredFrom && inArrayRequireMorePos >= 0 ){
49 | // WHEN CHECKING A RADIO WITHOUT RELATED ANSWER ( IN A LIST OF RADIOS WITH ONE REQ-MORE ) => REMOVE RELATED ANSWER FROM STORAGE
50 | storageArray.splice(inArrayRequireMorePos, 1);
51 | }
52 |
53 | const inArrayPos = getAnswerIndex( storageArray, name, (isMultiChoice ? value : false) );
54 | if( inArrayPos >= 0 ){
55 | // REMOVE ITEM FROM LS
56 | storageArray.splice(inArrayPos, 1);
57 | if( (isMultiChoice && $field.checked) || (!isMultiChoice && value !== '') ){
58 | // ADD ITEM TO LS
59 | storageArray.push( { name, value } );
60 | }
61 | } else if( value !== '' ){
62 | if( isRequiredFrom ){
63 | const reqMorePos = getAnswerIndex( storageArray, $reqMore.name );
64 | if( reqMorePos >= 0 ){
65 | storageArray.splice(reqMorePos, 1);
66 | }
67 | storageArray.push( { name: $reqMore.name, value: $reqMore.value } );
68 | }
69 | storageArray.push( { name, value } );
70 | }
71 |
72 | sessionStorage.setObject( storageName, storageArray );
73 | }
74 |
75 | // BASED ON JSON DATA, FORCE REQUIRED FIELDS TO BE VALIDATED
76 | if( questionObj.required && !$field.required && !$field.matches('[data-required-from]') ){
77 | $field.required = true;
78 | instance.validateField($field);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/modules/options.js:
--------------------------------------------------------------------------------
1 |
2 | import { optionsUtils } from './optionsUtils';
3 |
4 | export const options = {
5 | cssClasses: {
6 | checkbox: 'form-check-input',
7 | field: 'form-control',
8 | file: 'form-control-file',
9 | label: 'form-check-label',
10 | radio: 'form-check-input',
11 | wrapper: {
12 | checkbox: 'form-check',
13 | field: '',
14 | radio: 'form-check'
15 | }
16 | },
17 | formOptions: {
18 | getFormData: optionsUtils.formOptions.getFormData
19 | },
20 | initAjaxOptions: {
21 | cache: 'no-store',
22 | credentials: 'same-origin',
23 | headers: {
24 | 'Content-Type': 'application/json',
25 | 'Accept': 'application/json'
26 | },
27 | method: 'GET',
28 | mode: 'same-origin',
29 | redirect: 'follow',
30 | timeout: 0
31 | },
32 | messages:{
33 | maxChoice: 'answers max',
34 | error: 'Answer is necessary.',
35 | errorMultiChoice: 'You must choose from {{checksMin}} to {{checksMax}} answers.'
36 | },
37 | showErrorMessage: true,
38 | templates: {
39 | error: '{{errorMessage}}
',
40 |
41 | input: ' ',
42 |
43 | label: '{{labelString}} ',
44 |
45 | loading: 'Loading...
',
46 |
47 | select: ''+
48 | '{{optionsHtml}}'+
49 | ' ',
50 |
51 | textarea: '',
52 |
53 | wrapper: {
54 | field: ''+
55 | '{{fieldTemplate}}'+
56 | '{{labelTemplate}}'+
57 | '
',
58 |
59 | nested: ''+
60 | '{{labelTemplate}}'+
61 | '
'+
62 | '{{nestedFieldsHTML}}'+
63 | '
'+
64 | '
',
65 |
66 | question: ''+
67 | '
{{questionText}}
'+
68 | '
'+
69 | '{{answersHTML}}'+
70 | '
'+
71 | '
{{errorTemplates}}
'+
72 | '
',
73 |
74 | related: ''
83 | }
84 | },
85 | useWebStorage: true
86 | }
87 |
--------------------------------------------------------------------------------
/src/modules/optionsUtils.js:
--------------------------------------------------------------------------------
1 |
2 | import { fieldsStringSelectorSurvey, getQuestionId, isEmptyObject } from './helpers';
3 | import { getQuestionObject } from './utils/getQuestionObject';
4 |
5 | export const optionsUtils = {
6 | formOptions: {
7 |
8 | getFormData: function getFormData_surveyDefault( $filteredFields, trimValues ){
9 | const instance = this;
10 | const $form = instance.$form;
11 | const fieldsList = Array.from( $form.closest('[data-surveyjs-wrapper]').querySelectorAll(fieldsStringSelectorSurvey) );
12 | const obj = {
13 | answers: [],
14 | id: instance.data.id
15 | };
16 |
17 | let fieldNameCheck = '';
18 | let fieldTypeCheck = '';
19 |
20 | fieldsList.forEach($field => {
21 | const type = $field.type;
22 | const name = $field.name;
23 |
24 | if( name === fieldNameCheck && type === fieldTypeCheck ){ return; }
25 |
26 | if( !$field.matches('[data-required-from]') ){
27 | fieldNameCheck = name;
28 | fieldTypeCheck = type;
29 | }
30 |
31 | // EACH QUESTION HAS ITS OWN OBJECT ( qaObj ) THAT CONTAINS THE RELATED DATA:
32 | // question: THE QUESTION ID ( undefined FOR QUESTIONS WITH ATTRIBUTE data-required-form - will be skipped later )
33 | // answer AN OBJECT THAT CONTAINS THE FOLLOWS:
34 | // value: THE ANSWER VALUE
35 | // related: IF THE ANSWER IS REQUIRED FROM ANOTHER ANSWER (SEE BELOW)
36 | const questionId = getQuestionId($field);
37 | const qaObj = {
38 | question: questionId,
39 | answer: {
40 | value: trimValues ? $field.value.trim() : ($field.value || '')
41 | }
42 | };
43 |
44 | // A FIELD WITH ATTRIBUTE 'data-required-from' IS MANAGED TOGETHER WITH ITS RELATED FIELD ( WHICH HAS ATTRIBUTE 'data-require-more' )
45 | // IF QUESTION ID IS EMPTY -> SKIP THE FIELD ( USEFUL FOR FORM FIELDS OUTSIDE THE SURVEY BODY )
46 | if(
47 | $field.matches('[data-required-from]') ||
48 | questionId === '' ||
49 | isEmptyObject( getQuestionObject(instance.data.questions, questionId) )
50 | ){ return; }
51 |
52 | if( type === 'radio' ){
53 | const $container = $field.closest('form') ? $form : $field.closest(instance.options.fieldOptions.questionContainer);
54 | const $checked = $container.querySelector('[name="'+ name +'"]:checked');
55 |
56 | qaObj.answer.value = ($checked && $checked.value) || '';
57 |
58 | // FOR RADIO THAT REQUIRE THE USER TO GIVE ONE MORE ANSWER
59 | if( $checked && $checked.matches('[data-require-more]') ){
60 | qaObj.answer.related = $form.querySelector('[data-required-from="#'+ $checked.id +'"]').value;
61 | }
62 | }
63 |
64 | if( type === 'checkbox' && $field.matches('[data-checks]') ){
65 | qaObj.answer.value = [];
66 | Array.from($form.querySelectorAll('[name="'+ name +'"]:checked')).forEach($el => {
67 | qaObj.answer.value.push( $el.value );
68 | });
69 | }
70 |
71 | obj.answers.push( qaObj );
72 | });
73 |
74 | return obj;
75 | }
76 |
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/modules/utils/getAnswerIndex.js:
--------------------------------------------------------------------------------
1 |
2 | export const getAnswerIndex = ( list, fieldName, multiChoiceValue = '' ) => {
3 |
4 | const listLength = list.length;
5 |
6 | for(let item = 0; item < listLength; item++){
7 | const lsItem = list[item];
8 | if( lsItem.name === fieldName ){
9 | if( multiChoiceValue ){
10 | if( lsItem.value !== multiChoiceValue ){
11 | continue;
12 | }
13 | }
14 | return item;
15 | }
16 | }
17 |
18 | return -1;
19 |
20 | }
--------------------------------------------------------------------------------
/src/modules/utils/getQuestionObject.js:
--------------------------------------------------------------------------------
1 |
2 | export const getQuestionObject = ( questions, questionId ) => {
3 |
4 | const qLength = questions.length;
5 |
6 | let obj = {};
7 |
8 | for(let q=0; q