diff --git a/build-scripts/survey-jquery-ui/tsconfig.plugins.themes.typing.json b/build-scripts/survey-jquery-ui/tsconfig.plugins.themes.typing.json
deleted file mode 100644
index 02c6c25c28..0000000000
--- a/build-scripts/survey-jquery-ui/tsconfig.plugins.themes.typing.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "extends": "../tsconfig.json",
- "compilerOptions": {
- "baseUrl": ".",
- "paths": {
- "survey-core": [
- "../../build/survey-core"
- ]
- },
- "declaration": true,
- "emitDeclarationOnly": true,
- "outDir": "../../build/survey-jquery-ui/themes/typings/"
- },
- "include": [
- "../../src/themes/index.ts"
- ]
-}
\ No newline at end of file
diff --git a/build-scripts/survey-jquery-ui/webpack.config.js b/build-scripts/survey-jquery-ui/webpack.config.js
index 4fafc7a437..16bb91cb79 100644
--- a/build-scripts/survey-jquery-ui/webpack.config.js
+++ b/build-scripts/survey-jquery-ui/webpack.config.js
@@ -7,11 +7,6 @@ var packageJson = require("./package.json");
var path = require("path");
const config = {
- entry: {
- survey: path.resolve(__dirname, "../../src/main.scss"),
- modern: path.resolve(__dirname, "../../src/modern.scss"),
- defaultV2: path.resolve(__dirname, "../../src/defaultV2-theme/defaultV2.scss")
- },
resolve: {
alias: {
"react": "preact/compat",
diff --git a/build-scripts/survey-jquery-ui/webpack.themes.config.js b/build-scripts/survey-jquery-ui/webpack.themes.config.js
deleted file mode 100644
index ecd7caf8fd..0000000000
--- a/build-scripts/survey-jquery-ui/webpack.themes.config.js
+++ /dev/null
@@ -1,77 +0,0 @@
-"use strict";
-
-const webpackCommonConfigCreator = require("../webpack.common");
-const { merge } = require("webpack-merge");
-var FixStyleOnlyEntriesPlugin = require("webpack-fix-style-only-entries");
-const DtsGeneratorPlugin = require("../webpack-dts-generator");
-var path = require("path");
-
-const config = {
- entry: {
- "default-light": path.resolve(__dirname, "../../src/themes/default-light.ts"),
- "default-dark": path.resolve(__dirname, "../../src/themes/default-dark.ts"),
- "default-light-panelless": path.resolve(__dirname, "../../src/themes/default-light-panelless.ts"),
- "default-dark-panelless": path.resolve(__dirname, "../../src/themes/default-dark-panelless.ts"),
- "sharp-light": path.resolve(__dirname, "../../src/themes/sharp-light.ts"),
- "sharp-dark": path.resolve(__dirname, "../../src/themes/sharp-dark.ts"),
- "sharp-light-panelless": path.resolve(__dirname, "../../src/themes/sharp-light-panelless.ts"),
- "sharp-dark-panelless": path.resolve(__dirname, "../../src/themes/sharp-dark-panelless.ts"),
- "borderless-light": path.resolve(__dirname, "../../src/themes/borderless-light.ts"),
- "borderless-dark": path.resolve(__dirname, "../../src/themes/borderless-dark.ts"),
- "borderless-light-panelless.": path.resolve(__dirname, "../../src/themes/borderless-light-panelless.ts"),
- "borderless-dark-panelless": path.resolve(__dirname, "../../src/themes/borderless-dark-panelless.ts"),
- "flat-light": path.resolve(__dirname, "../../src/themes/flat-light.ts"),
- "flat-dark": path.resolve(__dirname, "../../src/themes/flat-dark.ts"),
- "flat-light-panelless": path.resolve(__dirname, "../../src/themes/flat-light-panelless.ts"),
- "flat-dark-panelless": path.resolve(__dirname, "../../src/themes/flat-dark-panelless.ts"),
- "plain-light": path.resolve(__dirname, "../../src/themes/plain-light.ts"),
- "plain-dark": path.resolve(__dirname, "../../src/themes/plain-dark.ts"),
- "plain-light-panelless": path.resolve(__dirname, "../../src/themes/plain-light-panelless.ts"),
- "plain-dark-panelless": path.resolve(__dirname, "../../src/themes/plain-dark-panelless.ts"),
- "doubleborder-light": path.resolve(__dirname, "../../src/themes/doubleborder-light.ts"),
- "doubleborder-dark": path.resolve(__dirname, "../../src/themes/doubleborder-dark.ts"),
- "doubleborder-light-panelles": path.resolve(__dirname, "../../src/themes/doubleborder-light-panelless.ts"),
- "doubleborder-dark-panelless": path.resolve(__dirname, "../../src/themes/doubleborder-dark-panelless.ts"),
- "layered-light": path.resolve(__dirname, "../../src/themes/layered-light.ts"),
- "layered-dark": path.resolve(__dirname, "../../src/themes/layered-dark.ts"),
- "layered-light-panelless": path.resolve(__dirname, "../../src/themes/layered-light-panelless.ts"),
- "layered-dark-panelless": path.resolve(__dirname, "../../src/themes/layered-dark-panelless.ts"),
- "solid-light": path.resolve(__dirname, "../../src/themes/solid-light.ts"),
- "solid-dark": path.resolve(__dirname, "../../src/themes/solid-dark.ts"),
- "solid-light-panelless": path.resolve(__dirname, "../../src/themes/solid-light-panelless.ts"),
- "solid-dark-panelless": path.resolve(__dirname, "../../src/themes/solid-dark-panelless.ts"),
- "three-dimensional-light": path.resolve(__dirname, "../../src/themes/threedimensional-light.ts"),
- "three-dimensional-dark": path.resolve(__dirname, "../../src/themes/threedimensional-dark.ts"),
- "three-dimensional-light-panelless": path.resolve(__dirname, "../../src/themes/threedimensional-light-panelless.ts"),
- "three-dimensional-dark-panelless": path.resolve(__dirname, "../../src/themes/threedimensional-dark-panelless.ts"),
- "contrast-light": path.resolve(__dirname, "../../src/themes/contrast-light.ts"),
- "contrast-dark": path.resolve(__dirname, "../../src/themes/contrast-dark.ts"),
- "contrast-light-panelless": path.resolve(__dirname, "../../src/themes/contrast-light-panelless.ts"),
- "contrast-dark-panelless": path.resolve(__dirname, "../../src/themes/contrast-dark-panelless.ts"),
- "index": path.resolve(__dirname, "../../src/themes/index.ts"),
- },
- plugins: [new FixStyleOnlyEntriesPlugin()],
- externals: {
- "survey-core": {
- root: "Survey",
- commonjs2: "survey-core",
- commonjs: "survey-core",
- amd: "survey-core"
- }
- }
-};
-
-module.exports = function (options) {
- options.platform = "";
- options.libraryName = "SurveyTheme";
- if (options.buildType !== "prod") {
- config.plugins.push(new DtsGeneratorPlugin({
- tsConfigPath: "./build-scripts/survey-jquery-ui/tsconfig.plugins.themes.typing.json",
- filePath: "build/survey-jquery-ui/themes/index.d.ts",
- moduleName: "survey-jquery-ui/themes",
- importName: "index"
- }));
- }
-
- return merge(webpackCommonConfigCreator(options, { "name": "survey-themes" }, "survey.themes", "survey-jquery-ui/themes"), config);
-};
diff --git a/build-scripts/survey-ui/tsconfig.plugins.themes.typing.json b/build-scripts/survey-ui/tsconfig.plugins.themes.typing.json
deleted file mode 100644
index 60ea9eb327..0000000000
--- a/build-scripts/survey-ui/tsconfig.plugins.themes.typing.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "extends": "../tsconfig.json",
- "compilerOptions": {
- "baseUrl": ".",
- "paths": {
- "survey-core": [
- "../../build/survey-core"
- ]
- },
- "declaration": true,
- "emitDeclarationOnly": true,
- "outDir": "../../build/survey-ui/themes/typings/"
- },
- "include": [
- "../../src/themes/index.ts"
- ]
-}
\ No newline at end of file
diff --git a/build-scripts/survey-ui/webpack.config.js b/build-scripts/survey-ui/webpack.config.js
index b6d330942b..036e3ff120 100644
--- a/build-scripts/survey-ui/webpack.config.js
+++ b/build-scripts/survey-ui/webpack.config.js
@@ -7,11 +7,6 @@ var packageJson = require("./package.json");
var path = require("path");
const config = {
- entry: {
- survey: path.resolve(__dirname, "../../src/main.scss"),
- modern: path.resolve(__dirname, "../../src/modern.scss"),
- defaultV2: path.resolve(__dirname, "../../src/defaultV2-theme/defaultV2.scss")
- },
resolve: {
alias: {
"react": "preact/compat",
diff --git a/build-scripts/survey-ui/webpack.themes.config.js b/build-scripts/survey-ui/webpack.themes.config.js
deleted file mode 100644
index 7d82e26707..0000000000
--- a/build-scripts/survey-ui/webpack.themes.config.js
+++ /dev/null
@@ -1,77 +0,0 @@
-"use strict";
-
-const webpackCommonConfigCreator = require("../webpack.common");
-const { merge } = require("webpack-merge");
-var FixStyleOnlyEntriesPlugin = require("webpack-fix-style-only-entries");
-const DtsGeneratorPlugin = require("../webpack-dts-generator");
-var path = require("path");
-
-const config = {
- entry: {
- "default-light": path.resolve(__dirname, "../../src/themes/default-light.ts"),
- "default-dark": path.resolve(__dirname, "../../src/themes/default-dark.ts"),
- "default-light-panelless": path.resolve(__dirname, "../../src/themes/default-light-panelless.ts"),
- "default-dark-panelless": path.resolve(__dirname, "../../src/themes/default-dark-panelless.ts"),
- "sharp-light": path.resolve(__dirname, "../../src/themes/sharp-light.ts"),
- "sharp-dark": path.resolve(__dirname, "../../src/themes/sharp-dark.ts"),
- "sharp-light-panelless": path.resolve(__dirname, "../../src/themes/sharp-light-panelless.ts"),
- "sharp-dark-panelless": path.resolve(__dirname, "../../src/themes/sharp-dark-panelless.ts"),
- "borderless-light": path.resolve(__dirname, "../../src/themes/borderless-light.ts"),
- "borderless-dark": path.resolve(__dirname, "../../src/themes/borderless-dark.ts"),
- "borderless-light-panelless.": path.resolve(__dirname, "../../src/themes/borderless-light-panelless.ts"),
- "borderless-dark-panelless": path.resolve(__dirname, "../../src/themes/borderless-dark-panelless.ts"),
- "flat-light": path.resolve(__dirname, "../../src/themes/flat-light.ts"),
- "flat-dark": path.resolve(__dirname, "../../src/themes/flat-dark.ts"),
- "flat-light-panelless": path.resolve(__dirname, "../../src/themes/flat-light-panelless.ts"),
- "flat-dark-panelless": path.resolve(__dirname, "../../src/themes/flat-dark-panelless.ts"),
- "plain-light": path.resolve(__dirname, "../../src/themes/plain-light.ts"),
- "plain-dark": path.resolve(__dirname, "../../src/themes/plain-dark.ts"),
- "plain-light-panelless": path.resolve(__dirname, "../../src/themes/plain-light-panelless.ts"),
- "plain-dark-panelless": path.resolve(__dirname, "../../src/themes/plain-dark-panelless.ts"),
- "doubleborder-light": path.resolve(__dirname, "../../src/themes/doubleborder-light.ts"),
- "doubleborder-dark": path.resolve(__dirname, "../../src/themes/doubleborder-dark.ts"),
- "doubleborder-light-panelles": path.resolve(__dirname, "../../src/themes/doubleborder-light-panelless.ts"),
- "doubleborder-dark-panelless": path.resolve(__dirname, "../../src/themes/doubleborder-dark-panelless.ts"),
- "layered-light": path.resolve(__dirname, "../../src/themes/layered-light.ts"),
- "layered-dark": path.resolve(__dirname, "../../src/themes/layered-dark.ts"),
- "layered-light-panelless": path.resolve(__dirname, "../../src/themes/layered-light-panelless.ts"),
- "layered-dark-panelless": path.resolve(__dirname, "../../src/themes/layered-dark-panelless.ts"),
- "solid-light": path.resolve(__dirname, "../../src/themes/solid-light.ts"),
- "solid-dark": path.resolve(__dirname, "../../src/themes/solid-dark.ts"),
- "solid-light-panelless": path.resolve(__dirname, "../../src/themes/solid-light-panelless.ts"),
- "solid-dark-panelless": path.resolve(__dirname, "../../src/themes/solid-dark-panelless.ts"),
- "three-dimensional-light": path.resolve(__dirname, "../../src/themes/threedimensional-light.ts"),
- "three-dimensional-dark": path.resolve(__dirname, "../../src/themes/threedimensional-dark.ts"),
- "three-dimensional-light-panelless": path.resolve(__dirname, "../../src/themes/threedimensional-light-panelless.ts"),
- "three-dimensional-dark-panelless": path.resolve(__dirname, "../../src/themes/threedimensional-dark-panelless.ts"),
- "contrast-light": path.resolve(__dirname, "../../src/themes/contrast-light.ts"),
- "contrast-dark": path.resolve(__dirname, "../../src/themes/contrast-dark.ts"),
- "contrast-light-panelless": path.resolve(__dirname, "../../src/themes/contrast-light-panelless.ts"),
- "contrast-dark-panelless": path.resolve(__dirname, "../../src/themes/contrast-dark-panelless.ts"),
- "index": path.resolve(__dirname, "../../src/themes/index.ts"),
- },
- plugins: [new FixStyleOnlyEntriesPlugin()],
- externals: {
- "survey-core": {
- root: "Survey",
- commonjs2: "survey-core",
- commonjs: "survey-core",
- amd: "survey-core"
- }
- }
-};
-
-module.exports = function (options) {
- options.platform = "";
- options.libraryName = "SurveyTheme";
- if (options.buildType !== "prod") {
- config.plugins.push(new DtsGeneratorPlugin({
- tsConfigPath: "./build-scripts/survey-ui/tsconfig.plugins.themes.typing.json",
- filePath: "build/survey-ui/themes/index.d.ts",
- moduleName: "survey-ui/themes",
- importName: "index"
- }));
- }
-
- return merge(webpackCommonConfigCreator(options, { "name": "survey-themes" }, "survey.themes", "survey-ui/themes"), config);
-};
diff --git a/devops-pull-requests-parallel-jobs.yml b/devops-pull-requests-parallel-jobs.yml
index 633ddb235d..dbef502747 100644
--- a/devops-pull-requests-parallel-jobs.yml
+++ b/devops-pull-requests-parallel-jobs.yml
@@ -391,9 +391,8 @@ jobs:
- script: |
npm run build_ui_prod
- displayName: "Build jquery-ui"
+ displayName: "Build survey-ui"
- script: |
npm run testcafe:survey-ui:ci
displayName: "run functional tests"
-
diff --git a/examples/jquery-ui/index.html b/examples/jquery-ui/index.html
index 3de1f29e76..d9c32ed14a 100644
--- a/examples/jquery-ui/index.html
+++ b/examples/jquery-ui/index.html
@@ -8,9 +8,9 @@
-
-
-
+
+
+
diff --git a/examples/survey-ui/index.html b/examples/survey-ui/index.html
new file mode 100644
index 0000000000..de0c43d1ff
--- /dev/null
+++ b/examples/survey-ui/index.html
@@ -0,0 +1,23 @@
+
+
+
+ Welcome to JQuery
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/survey-ui/index.js b/examples/survey-ui/index.js
new file mode 100644
index 0000000000..eff43bd3ef
--- /dev/null
+++ b/examples/survey-ui/index.js
@@ -0,0 +1,984 @@
+function init() {
+ //Add the price property into choices
+ Survey.Serializer.addProperty("itemvalue", "price:number");
+
+ var getItemPrice = function (params) {
+ //this.row property available in cells of dropdown and dynamic matrices questions
+ var question = !!this.row
+ ? this.row.getQuestionByColumnName(params[0])
+ : null;
+ //if we can't find a question inside the cell (by row and column name) then return
+ if (!question) return 0;
+
+ //get the selected item/choice
+ var selItem = question.selectedItem;
+ //return 0 if a user did not select the item yet.
+ return !!selItem ? selItem.price : 0;
+ };
+ //Register the custom function
+ Survey.FunctionFactory.Instance.register("getItemPrice", getItemPrice);
+
+ var json = {
+ showProgressBar: "both",
+ title: "Survey New Design Test",
+ logo: "https://surveyjs.io/Content/Images/examples/image-picker/lion.jpg",
+ logoPosition: "left",
+ questions: [
+ {
+ name: "signature",
+ type: "signaturepad",
+ title: "Sign here",
+ isRequired: true
+ },
+ {
+ name: "name",
+ type: "text",
+ title: "Text",
+ placeHolder: "Jon Snow",
+ isRequired: true
+ },
+ {
+ name: "birthdate",
+ type: "text",
+ inputType: "date",
+ title: "Text Date",
+ isRequired: true
+ },
+ {
+ name: "color",
+ type: "text",
+ inputType: "color",
+ title: "Text Color"
+ },
+ {
+ name: "email",
+ type: "text",
+ inputType: "email",
+ title: "Text Email",
+ placeHolder: "jon.snow@nightwatch.org",
+ isRequired: true,
+ validators: [
+ {
+ type: "email"
+ }
+ ]
+ },
+ {
+ type: "dropdown",
+ name: "cars",
+ title: "Dropdown",
+ isRequired: true,
+ showNoneItem: true,
+ colCount: 4,
+ choices: [
+ "Ford",
+ "Vauxhall",
+ "Volkswagen",
+ "Nissan",
+ "Audi",
+ "Mercedes-Benz",
+ "BMW",
+ "Peugeot",
+ "Toyota",
+ "Citroen"
+ ]
+ },
+ {
+ type: "checkbox",
+ name: "car",
+ title: "Checkbox",
+ isRequired: true,
+ showSelectAllItem: true,
+ showNoneItem: true,
+ colCount: 4,
+ choices: [
+ "Ford",
+ "Vauxhall",
+ "Volkswagen",
+ "Nissan",
+ "Audi",
+ "Mercedes-Benz",
+ "BMW",
+ "Peugeot",
+ "Toyota",
+ "Citroen"
+ ]
+ },
+ {
+ type: "radiogroup",
+ name: "carss",
+ title: "Radiogroup",
+ isRequired: true,
+ colCount: 4,
+ choices: [
+ "None",
+ "Ford",
+ "Vauxhall",
+ "Volkswagen",
+ "Nissan",
+ "Audi",
+ "Mercedes-Benz",
+ "BMW",
+ "Peugeot",
+ "Toyota",
+ "Citroen"
+ ]
+ },
+ {
+ type: "image",
+ name: "banner",
+ imageHeight: "300px",
+ imageWidth: "450px",
+ imageLink:
+ "https://surveyjs.io/Content/Images/examples/image-picker/lion.jpg"
+ },
+ {
+ type: "imagepicker",
+ name: "choosepicture",
+ title: "Imagepicker",
+ imageHeight: "150px",
+ imageWidth: "225px",
+ choices: [
+ {
+ value: "lion",
+ imageLink:
+ "https://surveyjs.io/Content/Images/examples/image-picker/lion.jpg"
+ },
+ {
+ value: "giraffe",
+ imageLink:
+ "https://surveyjs.io/Content/Images/examples/image-picker/giraffe.jpg"
+ },
+ {
+ value: "panda",
+ imageLink:
+ "https://surveyjs.io/Content/Images/examples/image-picker/panda.jpg"
+ },
+ {
+ value: "camel",
+ imageLink:
+ "https://surveyjs.io/Content/Images/examples/image-picker/camel.jpg"
+ }
+ ]
+ },
+ {
+ type: "boolean",
+ name: "bool",
+ title: "Boolean",
+ label: "Are you 21 or older?",
+ isRequired: true
+ },
+ {
+ type: "matrix",
+ name: "Quality",
+ title: "Matrix",
+ columns: [
+ {
+ value: 1,
+ text: "Strongly Disagree"
+ },
+ {
+ value: 2,
+ text: "Disagree"
+ },
+ {
+ value: 3,
+ text: "Neutral"
+ },
+ {
+ value: 4,
+ text: "Agree"
+ },
+ {
+ value: 5,
+ text: "Strongly Agree"
+ }
+ ],
+ rows: [
+ {
+ value: "affordable",
+ text: "Product is affordable"
+ },
+ {
+ value: "does what it claims",
+ text: "Product does what it claims"
+ },
+ {
+ value: "better than others",
+ text: "Product is better than other products on the market"
+ },
+ {
+ value: "easy to use",
+ text: "Product is easy to use"
+ }
+ ]
+ },
+ {
+ type: "matrix",
+ name: "planningPerformance",
+ title: "Matrix Rubric",
+ columns: [
+ "Ineffective",
+ "Improvement Necessary",
+ "Effective",
+ "Highly Effective"
+ ],
+ rows: [
+ {
+ value: "dataToPlan",
+ text: "Utilizes Assessment Data to Plan"
+ },
+ {
+ value: "ambitiousGoals",
+ text: "Ambitious and Measurable Achievement Goal"
+ },
+ {
+ value: "developsStandards",
+ text:
+ "Develops Standards.
Based Unit Plans and Assessments.
Evaluation Values."
+ },
+ {
+ value: "createsObjective",
+ text: "Creates Objective - Driven Lesson Plans and Assessments"
+ }
+ ],
+ cells: {
+ dataToPlan: {
+ Ineffective:
+ "Teacher rarely or never uses formal and informal assessment data when planning",
+ "Improvement Necessary":
+ "Teacher uses formal and informal assessment data to formulate
- Achievement goals, unit plans, or lesson plans, but not all of these",
+ Effective:
+ "Teacher uses formal and informal assessment data to formulate
- Achievement goals, unit plans, and lesson plans",
+ "Highly Effective":
+ "Teacher uses formal and informal assessment data to formulate achievement goals, unit plans, and lesson plans
- Incorporates differentiated instructional strategies in planning to reach every student at his/her level of understanding"
+ },
+ ambitiousGoals: {
+ Ineffective:
+ "Teacher rarely or never develops achievement goals for the class, or goals are developed but are too general to be helpful for planning purposes",
+ "Improvement Necessary":
+ "Teacher develops an annual student achievement goalthat lacks one or more of these traits:
- Measurable
- Aligned to content standards
- Includes benchmarks to help monitor learning and inform interventions throughout the year",
+ Effective:
+ "Teacher develops an annual student achievement goal that
- Is measurable
- Is aligned to content standards
- Includes benchmarks to help monitor learning and inform interventions throughout the year",
+ "Highly Effective":
+ "Teacher develops an annual student achievement goal that
- Is measurable
- Is aligned to content standards where applicable
- Includes benchmarks to help monitor learning and informinterventions throughout the year"
+ },
+ developsStandards: {
+ Ineffective:
+ "Teacher rarely or never plans by identifying content standards that students will master in each unit, or there is little to no evidence that teacher plans units at all",
+ "Improvement Necessary":
+ "Based on achievement goals, teacher plans units but omits one or more of these steps:
- Identifying content standards that students will master in each unit
- Creating assessments before planning units
- Allocating an instructionally appropriate amount of time for each unit",
+ Effective:
+ "Based on achievement goals, teacher plans units by
- Identifying content standards that students will master in each unit
- Creating assessments before each unit begins for backwards planning
- Allocating an instructionally appropriate amount of time for each unit",
+ "Highly Effective":
+ "Based on achievement goals, teacher plans units by
- Identifying content standards that students will master in each unit
- Creating assessments before each unit begins for backwards planning
- Allocating an instructionally appropriate amount of time for each unit"
+ },
+ createsObjective: {
+ Ineffective:
+ "Teacher rarely or never uses a system to track student assessment/progress data and/or has an ineffective grading system",
+ "Improvement Necessary":
+ "Teacher uses a data tracking system to record student assessment / progress data and maintain a grading system but fails in one or more of the following steps
- Use data to analyze student progress toward mastery or to plan future lessons / units
- Have a grading system that appropriately aligns with student learning goals",
+ Effective:
+ "Teacher uses an effective data tracking system for
- Recording student assessment / progress data
- Analyzing student progress towards mastery and planning future lessons/units accordingly
- Maintaining a grading system aligned to student learning goals",
+ "Highly Effective":
+ "Teacher uses an effective data tracking system that
- Records student assessment / progress data
- Analyzes student progress toward mastery and plans future lessons/units accordingly
- Maintains a grading system aligned to student learning goals"
+ }
+ }
+ },
+ {
+ type: "matrix Dropdown",
+ name: "frameworksRate",
+ title: "Matrixdropdown",
+ choices: ["Excelent", "Good", "Average", "Fair", "Poor"],
+ columns: [
+ {
+ name: "using",
+ title: "Do you use it?",
+ choices: ["Yes", "No"],
+ cellType: "radiogroup"
+ },
+ {
+ name: "experience",
+ title: "How long do you use it?",
+ choices: [
+ {
+ value: 5,
+ text: "3-5 years"
+ },
+ {
+ value: 2,
+ text: "1-2 years"
+ },
+ {
+ value: 1,
+ text: "less than a year"
+ }
+ ]
+ },
+ {
+ name: "strength",
+ title: "What is main strength?",
+ choices: ["Easy", "Compact", "Fast", "Powerfull"],
+ cellType: "checkbox"
+ },
+ {
+ name: "knowledge",
+ title: "Please describe your experience",
+ cellType: "text"
+ },
+ {
+ name: "rate",
+ title: "Please rate the framework itself"
+ }
+ ],
+ rows: [
+ {
+ value: "angularv1",
+ text: "angularjs v1.x"
+ },
+ {
+ value: "angularv2",
+ text: "angularjs v2"
+ },
+ {
+ value: "knockoutjs"
+ },
+ {
+ value: "reactjs"
+ }
+ ]
+ },
+ {
+ type: "matrixdynamic",
+ name: "teachersRate",
+ title: "Matrix Dynamic",
+ addRowText: "Add Subject",
+ horizontalScroll: true,
+ columnMinWidth: "130px",
+ columnColCount: 1,
+ cellType: "radiogroup",
+ choices: [
+ {
+ value: 1,
+ text: "Yes"
+ },
+ {
+ value: 0,
+ text: "Sometimes"
+ },
+ {
+ value: -1,
+ text: "No"
+ }
+ ],
+ columns: [
+ {
+ name: "subject",
+ cellType: "dropdown",
+ title: "Select a subject",
+ isRequired: true,
+ minWidth: "300px",
+ choices: [
+ "English: American Literature",
+ "English: British and World Literature",
+ "Math: Consumer Math",
+ "Math: Practical Math",
+ "Math: Developmental Algebra",
+ "Math: Continuing Algebra",
+ "Math: Pre-Algebra",
+ "Math: Algebra",
+ "Math: Geometry",
+ "Math: Integrated Mathematics",
+ "Science: Physical Science",
+ "Science: Earth Science",
+ "Science: Biology",
+ "Science: Chemistry",
+ "History: World History",
+ "History: Modern World Studies",
+ "History: U.S. History",
+ "History: Modern U.S. History",
+ "Social Sciences: U.S. Government and Politics",
+ "Social Sciences: U.S. and Global Economics",
+ "World Languages: Spanish",
+ "World Languages: French",
+ "World Languages: German",
+ "World Languages: Latin",
+ "World Languages: Chinese",
+ "World Languages: Japanese"
+ ]
+ },
+ {
+ name: "explains",
+ title: "Clearly explains the objectives"
+ },
+ {
+ name: "interesting",
+ title: "Makes class interesting"
+ },
+ {
+ name: "effective",
+ title: "Uses class time effectively"
+ },
+ {
+ name: "knowledge",
+ title: "Knows the subject matter"
+ },
+ {
+ name: "recognition",
+ title: "Recognizes and acknowledges effort"
+ },
+ {
+ name: "inform",
+ title: "Keeps me informed of my progress"
+ },
+ {
+ name: "opinion",
+ title: "Encourages and accepts different opinions"
+ },
+ {
+ name: "respect",
+ title: "Has the respect of the student"
+ },
+ {
+ name: "cooperation",
+ title: "Encourages cooperation and participation"
+ },
+ {
+ name: "parents",
+ title: "Communicates with my parents"
+ },
+ {
+ name: "selfthinking",
+ title: "Encourages me to think for myself"
+ },
+ {
+ name: "frusturation",
+ cellType: "comment",
+ title: "Is there anything about this class that frustrates you?",
+ minWidth: "250px"
+ },
+ {
+ name: "likeTheBest",
+ cellType: "comment",
+ title: "What do you like best about this class and/or teacher?",
+ minWidth: "250px"
+ },
+ {
+ name: "improvements",
+ cellType: "comment",
+ title:
+ "What do you wish this teacher would do differently that would improve this class?",
+ minWidth: "250px"
+ }
+ ],
+ rowCount: 2
+ },
+ {
+ type: "matrixdynamic",
+ name: "Current Level of Function",
+ title: "Matrix Dynamic (vertical columns)",
+ columnLayout: "vertical",
+ minRowCount: 1,
+ maxRowCount: 5,
+ columns: [
+ {
+ name: "Date",
+ title: "Date",
+ cellType: "text",
+ inputType: "date"
+ },
+ {
+ name: "AmbDistance",
+ title: "Amb Distance",
+ cellType: "text"
+ },
+ {
+ name: "Amb Assistance",
+ cellType: "dropdown",
+ choices: ["D", "MAX", "MOD", "MIN"]
+ },
+ {
+ name: "Standing Tolerance",
+ cellType: "text"
+ },
+ {
+ name: "UE Strength",
+ cellType: "text"
+ },
+ {
+ name: "Cognitive Function",
+ cellType: "comment"
+ }
+ ],
+ choices: [1],
+ cellType: "comment",
+ confirmDelete: true,
+ addRowText: "Add Date +",
+ removeRowText: "Remove"
+ },
+ {
+ type: "matrixdynamic",
+ name: "orderList",
+ rowCount: 1,
+ minRowCount: 1,
+ title: "Matrix Dynamic (totals)",
+ addRowText: "Add new item",
+ columns: [
+ {
+ name: "id",
+ title: "Id",
+ cellType: "expression",
+ expression: "{rowIndex}"
+ },
+ {
+ name: "phone_model",
+ title: "Phone model",
+ isRequired: true,
+ totalType: "count",
+ totalFormat: "Items count: {0}",
+ choices: [
+ {
+ value: "iPhone7-32",
+ text: "iPhone 7, 32GB",
+ price: 449
+ },
+ {
+ value: "iPhone7-128",
+ text: "iPhone 7, 128GB",
+ price: 549
+ },
+ {
+ value: "iPhone7Plus-32",
+ text: "iPhone 7 Plus, 32GB",
+ price: 569
+ },
+ {
+ value: "iPhone7Plus-128",
+ text: "iPhone 7 Plus, 128GB",
+ price: 669
+ },
+ {
+ value: "iPhone8-64",
+ text: "iPhone 8, 64GB",
+ price: 599
+ },
+ {
+ value: "iPhone8-256",
+ text: "iPhone 8, 256GB",
+ price: 749
+ },
+ {
+ value: "iPhone8Plus-64",
+ text: "iPhone 8 Plus, 64GB",
+ price: 699
+ },
+ {
+ value: "iPhone8Plus-256",
+ text: "iPhone 8 Plus, 256GB",
+ price: 849
+ },
+ {
+ value: "iPhoneXR-64",
+ text: "iPhone XR, 64GB",
+ price: 749
+ },
+ {
+ value: "iPhoneXR-128",
+ text: "iPhone XR, 128GB",
+ price: 799
+ },
+ {
+ value: "iPhoneXR-256",
+ text: "iPhone XR, 256GB",
+ price: 899
+ },
+ {
+ value: "iPhoneXS-64",
+ text: "iPhone XS, 64GB",
+ price: 999
+ },
+ {
+ value: "iPhoneXS-256",
+ text: "iPhone XS, 256GB",
+ price: 1149
+ },
+ {
+ value: "iPhoneXS-512",
+ text: "iPhone XS, 512GB",
+ price: 1349
+ },
+ {
+ value: "iPhoneXSMAX-64",
+ text: "iPhone XS Max, 64GB",
+ price: 1099
+ },
+ {
+ value: "iPhoneXSMAX-256",
+ text: "iPhone XS Max, 256GB",
+ price: 1249
+ },
+ {
+ value: "iPhoneXSMAX-512",
+ text: "iPhone XS, 512GB",
+ price: 1449
+ }
+ ]
+ },
+ {
+ name: "price",
+ title: "Price",
+ cellType: "expression",
+ expression: "getItemPrice('phone_model')",
+ displayStyle: "currency"
+ },
+ {
+ name: "quantity",
+ title: "Quantity",
+ isRequired: true,
+ cellType: "text",
+ inputType: "number",
+ totalType: "sum",
+ totalFormat: "Total phones: {0}",
+ validators: [
+ {
+ type: "numeric",
+ minValue: 1,
+ maxValue: 100
+ }
+ ]
+ },
+ {
+ name: "total",
+ title: "Total",
+ cellType: "expression",
+ expression: "{row.quantity} * {row.price}",
+ displayStyle: "currency",
+ totalType: "sum",
+ totalDisplayStyle: "currency",
+ totalFormat: "Total: {0}"
+ }
+ ]
+ },
+ {
+ name: "vatProcents",
+ type: "text",
+ title: "VAT (in %)",
+ defaultValue: 20,
+ inputType: "number",
+ validators: [
+ {
+ type: "numeric",
+ minValue: 0,
+ maxValue: 40
+ }
+ ]
+ },
+ {
+ name: "vatTotal",
+ type: "expression",
+ title: "VAT",
+ expression: "{orderList-total.total} * {vatProcents} / 100",
+ displayStyle: "currency",
+ startWithNewLine: false
+ },
+ {
+ name: "total",
+ type: "expression",
+ title: "Total",
+ expression: "{orderList-total.total} + {vatTotal}",
+ displayStyle: "currency",
+ startWithNewLine: false
+ },
+ {
+ type: "multipletext",
+ name: "pricelimit",
+ title: "Multipletext",
+ colCount: 2,
+ items: [
+ {
+ name: "mostamount",
+ title: "Most amount you would every pay for a product like ours"
+ },
+ {
+ name: "leastamount",
+ title: "The least amount you would feel comfortable paying"
+ }
+ ]
+ },
+ {
+ type: "rating",
+ name: "satisfaction",
+ title: "Rating",
+ minRateDescription: "Not Satisfied",
+ maxRateDescription: "Completely satisfied"
+ },
+ {
+ type: "comment",
+ name: "suggestions",
+ title: "Comment"
+ },
+ {
+ type: "file",
+ title: "File",
+ name: "image",
+ storeDataAsText: false,
+ showPreview: true,
+ imageWidth: 150,
+ maxSize: 102400
+ },
+ {
+ type: "panel",
+ title: "Panel",
+ innerIndent: 1,
+ elements: [
+ {
+ type: "checkbox",
+ choices: [
+ {
+ value: "1",
+ text: "Customer relationship"
+ },
+ {
+ value: "2",
+ text: "Service quality"
+ },
+ {
+ value: "3",
+ text: "Support response time"
+ }
+ ],
+ name: "What should be improved?"
+ },
+ {
+ type: "comment",
+ name: "suggestions",
+ title: "What would make you more satisfied with the Product?"
+ }
+ ]
+ },
+ {
+ type: "paneldynamic",
+ name: "relatives",
+ title: "Panel Dynamic",
+ renderMode: "progressTop",
+ templateTitle: "Information about: {panel.relativeType}",
+ templateElements: [
+ {
+ name: "relativeType",
+ type: "dropdown",
+ title: "Relative",
+ choices: [
+ "father",
+ "mother",
+ "brother",
+ "sister",
+ "son",
+ "daughter"
+ ],
+ isRequired: true
+ },
+ {
+ name: "isalive",
+ type: "radiogroup",
+ title: "Alive?",
+ startWithNewLine: false,
+ isRequired: true,
+ colCount: 0,
+ choices: ["Yes", "No"]
+ },
+ {
+ name: "liveage",
+ type: "dropdown",
+ title: "Age",
+ isRequired: true,
+ startWithNewLine: false,
+ visibleIf: "{panel.isalive} = 'Yes'",
+ choicesMin: 1,
+ choicesMax: 115
+ },
+ {
+ name: "deceasedage",
+ type: "dropdown",
+ title: "Deceased Age",
+ isRequired: true,
+ startWithNewLine: false,
+ visibleIf: "{panel.isalive} = 'No'",
+ choices: [
+ {
+ value: -1,
+ text: "Unknown"
+ }
+ ],
+ choicesMin: 1,
+ choicesMax: 115
+ },
+ {
+ name: "causeofdeathknown",
+ type: "radiogroup",
+ title: "Cause of Death Known?",
+ isRequired: true,
+ colCount: 0,
+ startWithNewLine: false,
+ visibleIf: "{panel.isalive} = 'No'",
+ choices: ["Yes", "No"]
+ },
+ {
+ name: "causeofdeath",
+ type: "text",
+ title: "Cause of Death",
+ isRequired: true,
+ startWithNewLine: false,
+ visibleIf:
+ "{panel.isalive} = 'No' and {panel.causeofdeathknown} = 'Yes'"
+ },
+ {
+ type: "panel",
+ name: "moreInfo",
+ state: "expanded",
+ title: "Detail Information about: {panel.relativeType}",
+ elements: [
+ {
+ type: "matrixdynamic",
+ name: "relativeillness",
+ title: "Describe the illness or condition.",
+ rowCount: 0,
+ columns: [
+ {
+ name: "illness",
+ cellType: "dropdown",
+ title: "Illness/Condition",
+ choices: [
+ "Cancer",
+ "Heart Disease",
+ "Diabetes",
+ "Stroke/TIA",
+ "High Blood Pressure",
+ "High Cholesterol or Triglycerides",
+ "Liver Disease",
+ "Alcohol or Drug Abuse",
+ "Anxiety, Depression or Psychiatric Illness",
+ "Tuberculosis",
+ "Anesthesia Complications",
+ "Genetic Disorder",
+ "Other – describe"
+ ],
+ isRequired: true
+ },
+ {
+ name: "description",
+ cellType: "text",
+ title: "Describe",
+ isRequired: true
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ panelCount: 2,
+ panelAddText: "Add a blood relative",
+ panelRemoveText: "Remove the relative"
+ },
+ {
+ type: "panel",
+ title: "Expression Example Panel",
+ innerIndent: 1,
+ elements: [
+ {
+ type: "paneldynamic",
+ name: "items",
+ title: "Items",
+ keyName: "name",
+ showQuestionNumbers: "none",
+ templateTitle: "item #{panelIndex}",
+ templateElements: [
+ {
+ type: "text",
+ name: "name",
+ title: "Name:",
+ isRequired: true
+ },
+ {
+ type: "text",
+ name: "cost",
+ inputType: "number",
+ title: "Item Cost:",
+ isRequired: true,
+ startWithNewLine: false
+ },
+ {
+ type: "text",
+ name: "vendor",
+ title: "Vendor:",
+ isRequired: true
+ },
+ {
+ type: "text",
+ name: "quantity",
+ inputType: "number",
+ title: "Quantity:",
+ isRequired: true,
+ startWithNewLine: false
+ },
+ {
+ type: "text",
+ name: "link",
+ title: "Link:",
+ isRequired: true
+ },
+ {
+ type: "expression",
+ name: "total",
+ title: "Total Item Cost:",
+ expression: "{panel.cost} * {panel.quantity}",
+ displayStyle: "currency",
+ currency: "EUR",
+ startWithNewLine: false
+ }
+ ],
+ minPanelCount: 1,
+ panelAddText: "Add another item",
+ panelRemoveText: "Remove item"
+ },
+ {
+ type: "panel",
+ title: "Totals",
+ elements: [
+ {
+ type: "expression",
+ name: "totalQuantity",
+ title: "Total Quantity:",
+ expression: "sumInArray({items}, 'quantity'"
+ },
+ {
+ type: "expression",
+ name: "totalCost",
+ title: "Total Cost:",
+ expression: "sumInArray({items}, 'total'",
+ displayStyle: "currency",
+ currency: "EUR",
+ startWithNewLine: false
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ };
+
+ //Survey.StylesManager.applyTheme("default");
+ //Survey.StylesManager.applyTheme("modern");
+ Survey.StylesManager.applyTheme("defaultV2");
+
+ window.survey = new Survey.Model(json);
+ survey.onComplete.add(function (result) {
+ document.querySelector("#surveyResultElement").innerHTML =
+ "result: " + JSON.stringify(result.data);
+ });
+
+ SurveyUI.renderSurvey(survey, document.getElementById("surveyElement"));
+}
+
+if (!window["%hammerhead%"]) {
+ init();
+}
\ No newline at end of file
diff --git a/examples_test/bootstrap/jquery-ui.html b/examples_test/bootstrap/jquery-ui.html
index c06b598d1b..24f34d61fa 100644
--- a/examples_test/bootstrap/jquery-ui.html
+++ b/examples_test/bootstrap/jquery-ui.html
@@ -9,6 +9,7 @@
+
diff --git a/examples_test/bootstrap/survey-ui.html b/examples_test/bootstrap/survey-ui.html
new file mode 100644
index 0000000000..c6d420f053
--- /dev/null
+++ b/examples_test/bootstrap/survey-ui.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples_test/customWidget/jquery-ui.html b/examples_test/customWidget/jquery-ui.html
index 0a92b2302b..3f4ee3b706 100644
--- a/examples_test/customWidget/jquery-ui.html
+++ b/examples_test/customWidget/jquery-ui.html
@@ -9,9 +9,10 @@
-
+
+
diff --git a/examples_test/customWidget/survey-ui.html b/examples_test/customWidget/survey-ui.html
new file mode 100644
index 0000000000..9e621d3d31
--- /dev/null
+++ b/examples_test/customWidget/survey-ui.html
@@ -0,0 +1,61 @@
+
+
+
+
+ Welcome to Jquery UI
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples_test/default/jquery-ui.html b/examples_test/default/jquery-ui.html
index 05255b3132..5039a2f901 100644
--- a/examples_test/default/jquery-ui.html
+++ b/examples_test/default/jquery-ui.html
@@ -6,9 +6,10 @@
-
+
+
diff --git a/examples_test/default/survey-ui.html b/examples_test/default/survey-ui.html
new file mode 100644
index 0000000000..a36af41a56
--- /dev/null
+++ b/examples_test/default/survey-ui.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples_test/defaultV2/jquery-ui.html b/examples_test/defaultV2/jquery-ui.html
index dd688158cd..f36a38580c 100644
--- a/examples_test/defaultV2/jquery-ui.html
+++ b/examples_test/defaultV2/jquery-ui.html
@@ -6,9 +6,10 @@
-
+
+
diff --git a/examples_test/defaultV2/survey-ui.html b/examples_test/defaultV2/survey-ui.html
new file mode 100644
index 0000000000..9def346062
--- /dev/null
+++ b/examples_test/defaultV2/survey-ui.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples_test/modern/jquery-ui.html b/examples_test/modern/jquery-ui.html
index 002adb957c..493d353137 100644
--- a/examples_test/modern/jquery-ui.html
+++ b/examples_test/modern/jquery-ui.html
@@ -6,9 +6,10 @@
-
+
+
diff --git a/examples_test/modern/survey-ui.html b/examples_test/modern/survey-ui.html
new file mode 100644
index 0000000000..cf47b46301
--- /dev/null
+++ b/examples_test/modern/survey-ui.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
index f5fadfeaa4..2d967b4ebd 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,10 @@
"testcafe:ko": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=knockout",
"testcafe:jquery-ui": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome testCafe/ --app \"http-server --silent\" --env=jquery-ui",
"testcafe:jquery-ui:ci": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=jquery-ui",
+ "testcafe:survey-ui": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome testCafe/ --app \"http-server --silent\" --env=survey-ui",
+ "testcafe:survey-ui:ci": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=survey-ui",
"vrt:jquery-ui:ci": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=jquery-ui",
+ "vrt:survey-ui:ci": "testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless ./visualRegressionTests/ --app \"http-server\" --screenshots ./ --selector-timeout 1500 --reporter minimal --env=survey-ui",
"testcafe:react": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=react",
"testcafe:vue": "http-server --silent & testcafe -c 4 -q attemptLimit=5,successThreshold=1 chrome:headless testCafe/ --reporter minimal --env=vue",
"release": "commit-and-tag-version --message \"Release: %s [azurepipelines skip]\" ",
@@ -25,10 +28,10 @@
"build_vue_prod": "webpack --config ./build-scripts/survey-vue/webpack.config.js --env.buildType prod && webpack --config ./build-scripts/survey-vue/webpack.themes.config.js --env.buildType prod",
"build_jquery_dev": "webpack --config ./build-scripts/survey-jquery/webpack.config.js --env.buildType dev && webpack --config ./build-scripts/survey-jquery/webpack.themes.config.js --env.buildType dev",
"build_jquery_prod": "webpack --config ./build-scripts/survey-jquery/webpack.config.js --env.buildType prod && webpack --config ./build-scripts/survey-jquery/webpack.themes.config.js --env.buildType prod",
- "build_jquery_ui_dev": "webpack --config ./build-scripts/survey-jquery-ui/webpack.config.js --env.buildType dev && webpack --config ./build-scripts/survey-jquery-ui/webpack.themes.config.js --env.buildType dev",
- "build_jquery_ui_prod": "webpack --config ./build-scripts/survey-jquery-ui/webpack.config.js --env.buildType prod && webpack --config ./build-scripts/survey-jquery-ui/webpack.themes.config.js --env.buildType prod",
- "build_ui_dev": "webpack --config ./build-scripts/survey-ui/webpack.config.js --env.buildType dev && webpack --config ./build-scripts/survey-ui/webpack.themes.config.js --env.buildType dev",
- "build_ui_prod": "webpack --config ./build-scripts/survey-ui/webpack.config.js --env.buildType prod && webpack --config ./build-scripts/survey-ui/webpack.themes.config.js --env.buildType prod",
+ "build_jquery_ui_dev": "webpack --config ./build-scripts/survey-jquery-ui/webpack.config.js --env.buildType dev",
+ "build_jquery_ui_prod": "webpack --config ./build-scripts/survey-jquery-ui/webpack.config.js --env.buildType prod",
+ "build_ui_dev": "webpack --config ./build-scripts/survey-ui/webpack.config.js --env.buildType dev",
+ "build_ui_prod": "webpack --config ./build-scripts/survey-ui/webpack.config.js --env.buildType prod",
"build_angular_dev": "webpack --config ./build-scripts/survey-angular/webpack.config.js --env.buildType dev",
"build_angular_prod": "webpack --config ./build-scripts/survey-angular/webpack.config.js --env.buildType prod",
"build_i18n_dev": "webpack --config ./build-scripts/survey-core/webpack.i18n.js --env.buildType dev",
diff --git a/src/base-interfaces.ts b/src/base-interfaces.ts
index 35298377f7..9eb49e958c 100644
--- a/src/base-interfaces.ts
+++ b/src/base-interfaces.ts
@@ -150,6 +150,8 @@ export interface ISurvey extends ITextProcessor, ISurveyErrorOwner {
maxOthersLength: number;
clearValueOnDisableItems: boolean;
+ maxTimeToFinishPage: number;
+
uploadFiles(
question: IQuestion,
name: string,
@@ -331,6 +333,7 @@ export interface IPanel extends ISurveyElement, IParentElement {
elements: Array;
ensureRowsVisibility(): void;
validateContainerOnly(): void;
+ onQuestionValueChanged(el: IElement): void;
}
export interface IPage extends IPanel, IConditionRunner {
isStartPage: boolean;
diff --git a/src/base.ts b/src/base.ts
index 061ad8ac9d..9f2e0be6e2 100644
--- a/src/base.ts
+++ b/src/base.ts
@@ -500,6 +500,7 @@ export class Base {
const prop = this.getPropertyByName(name);
if(!prop || prop.isCustom && this.isCreating) return undefined;
const dValue = prop.defaultValue;
+ if (!!prop.defaultValueFunc) return dValue;
if (!this.isPropertyEmpty(dValue) && !Array.isArray(dValue)) return dValue;
const locStr = this.localizableStrings ? this.localizableStrings[name] : undefined;
if(locStr && locStr.localizationName) return this.getLocalizationString(locStr.localizationName);
diff --git a/src/defaultV2-theme/blocks/sd-title.scss b/src/defaultV2-theme/blocks/sd-title.scss
index c3a099fd44..643bace6f9 100644
--- a/src/defaultV2-theme/blocks/sd-title.scss
+++ b/src/defaultV2-theme/blocks/sd-title.scss
@@ -96,6 +96,10 @@
}
}
+.sd-root--compact .sd-title .sv-title-actions {
+ width: 100%;
+}
+
.sd-action-title-bar {
flex: 1 9 auto;
min-width: calcSize(6);
diff --git a/src/entries/jquery-ui.ts b/src/entries/jquery-ui.ts
index e1a20dc0ba..04e79b11a2 100644
--- a/src/entries/jquery-ui.ts
+++ b/src/entries/jquery-ui.ts
@@ -3,10 +3,8 @@ import * as ReactDOM from "react-dom";
import jQuery from "jquery";
import { Survey, PopupSurvey } from "./jquery-ui-model";
-// localization
-import "./chunks/localization";
-import { SurveyModel } from "./core";
+import { SurveyModel, checkLibraryVersion } from "survey-core";
jQuery["fn"].extend({
Survey: function (props: any) {
@@ -24,25 +22,6 @@ function doPopupSurvey(props: any): void {
var model: Survey = props.model;
const survey = React.createElement(PopupSurvey, { ...props });
ReactDOM.render(survey, this);
-
- // var popupSurvey = props.popupModel || new PopupSurvey(model);
-
- // if (props.expanded !== undefined) {
- // popupSurvey.isExpanded = props.expanded;
- // }
- // if (props.isExpanded !== undefined) {
- // popupSurvey.isExpanded = props.isExpanded;
- // }
- // if (props.allowClose !== undefined) {
- // popupSurvey.allowClose = props.allowClose;
- // }
- // if (props.allowFullScreen !== undefined) {
- // popupSurvey.allowFullScreen = props.allowFullScreen;
- // }
- // if (props.closeOnCompleteTimeout !== undefined) {
- // popupSurvey.closeOnCompleteTimeout = props.closeOnCompleteTimeout;
- // }
- // popupSurvey.show();
});
}
@@ -55,9 +34,4 @@ export * from "./core-export";
export { SurveyModel as Model } from "survey-core";
-export * from "../utils/responsivity-manager";
-export { unwrap } from "../utils/utils";
-
-import { checkLibraryVersion } from "survey-core";
-
checkLibraryVersion(`${process.env.VERSION}`, "survey-jquery-ui");
\ No newline at end of file
diff --git a/src/entries/ui.ts b/src/entries/ui.ts
index e6b57b1758..6a1fbe3c92 100644
--- a/src/entries/ui.ts
+++ b/src/entries/ui.ts
@@ -7,19 +7,19 @@ import { SurveyModel } from "survey-core";
const jQuery = window["jQuery"] || window["$"];
-export function renderSurvey(model: SurveyModel, element: HTMLElement) {
- const survey = React.createElement(Survey, { model });
+export function renderSurvey(model: SurveyModel, element: HTMLElement, props: any = {}) {
+ const survey = React.createElement(Survey, { model, ...props });
ReactDOM.render(survey, element);
}
-export function renderPopupSurvey(model: SurveyModel, element: HTMLElement) {
- const survey = React.createElement(PopupSurvey, { model });
+export function renderPopupSurvey(model: SurveyModel, element: HTMLElement, props: any = {}) {
+ const survey = React.createElement(PopupSurvey, { model, ...props });
ReactDOM.render(survey, element);
}
function doPopupSurvey(props: any): void {
return this.each(function () {
- renderPopupSurvey(props.model, this);
+ renderPopupSurvey(props.model, this, props);
});
}
@@ -27,7 +27,7 @@ if (!!jQuery) {
jQuery["fn"].extend({
Survey: function (props: any) {
return this.each(function () {
- renderSurvey(props.model, this);
+ renderSurvey(props.model, this, props);
} as any);
},
PopupSurvey: doPopupSurvey,
diff --git a/src/jsonobject.ts b/src/jsonobject.ts
index 550718cfec..61171c1a99 100644
--- a/src/jsonobject.ts
+++ b/src/jsonobject.ts
@@ -410,7 +410,7 @@ export class JsonObjectProperty implements IObject, IJsonPropertyInfo {
}
if(this.isLocalizable) return value === null || value === undefined;
return (
- (value === false && (this.type == "boolean" || this.type == "switch")) ||
+ (value === false && (this.type == "boolean" || this.type == "switch") && !this.defaultValueFunc) ||
value === "" || Helpers.isValueEmpty(value)
);
}
diff --git a/src/page.ts b/src/page.ts
index 61fadf8935..caa8f22d10 100644
--- a/src/page.ts
+++ b/src/page.ts
@@ -256,6 +256,11 @@ export class PageModel extends PanelModelBase implements IPage {
public set maxTimeToFinish(val: number) {
this.setPropertyValue("maxTimeToFinish", val);
}
+ public getMaxTimeToFinish(): number {
+ if(this.maxTimeToFinish !== 0) return this.maxTimeToFinish;
+ const res = !!this.survey ? this.survey.maxTimeToFinishPage : 0;
+ return res > 0 ? res : 0;
+ }
protected onNumChanged(value: number) { }
protected onVisibleChanged() {
if (this.isRandomizing) return;
diff --git a/src/panel.ts b/src/panel.ts
index 39edfae42e..fc94461214 100644
--- a/src/panel.ts
+++ b/src/panel.ts
@@ -880,6 +880,21 @@ export class PanelModelBase extends SurveyElement
this.parent.validateContainerOnly();
}
}
+ onQuestionValueChanged(el: IElement): void {
+ const index = this.questions.indexOf(el);
+ if(index < 0) return;
+ const dif = 5;
+ const max = this.questions.length - 1;
+ const start = index - dif > 0 ? index - dif : 0;
+ const end = index + dif < max ? index + dif : max;
+ for(let i = start; i <= end; i ++) {
+ if(i === index) continue;
+ const q = this.questions[i];
+ if(q.errors.length > 0 && q.validate(false)) {
+ q.validate(true);
+ }
+ }
+ }
private hasErrorsInPanels(rec: any): void {
var errors = >[];
this.hasRequiredError(rec, errors);
diff --git a/src/question.ts b/src/question.ts
index acefde8a35..969edf4a33 100644
--- a/src/question.ts
+++ b/src/question.ts
@@ -1542,10 +1542,19 @@ export class Question extends SurveyElement
public getFilteredValue(): any { return this.value; }
public getFilteredName(): any { return this.getValueName(); }
public get valueForSurvey(): any {
+ return this.valueForSurveyCore(this.value);
+ }
+ protected valueForSurveyCore(val: any): any {
if (!!this.valueToDataCallback) {
- return this.valueToDataCallback(this.value);
+ return this.valueToDataCallback(val);
}
- return this.value;
+ return val;
+ }
+ protected valueFromDataCore(val: any): any {
+ if (!!this.valueFromDataCallback) {
+ return this.valueFromDataCallback(val);
+ }
+ return val;
}
/**
* Sets the question's `value` and `comment` properties to `undefined`.
@@ -2253,6 +2262,9 @@ export class Question extends SurveyElement
this.updateQuestionCss();
}
this.isOldAnswered = undefined;
+ if(this.parent) {
+ this.parent.onQuestionValueChanged(this);
+ }
}
private checkIsValueCorrect(val: any): boolean {
const res = this.isValueEmpty(val, !this.allowSpaceAsAnswer) || this.isNewValueCorrect(val);
@@ -2337,9 +2349,7 @@ export class Question extends SurveyElement
//IQuestion
updateValueFromSurvey(newValue: any, clearData: boolean = false): void {
newValue = this.getUnbindValue(newValue);
- if (!!this.valueFromDataCallback) {
- newValue = this.valueFromDataCallback(newValue);
- }
+ newValue = this.valueFromDataCore(newValue);
if (!this.checkIsValueCorrect(newValue)) return;
const isEmpty = this.isValueEmpty(newValue);
if(!isEmpty && this.defaultValueExpression) {
diff --git a/src/question_comment.ts b/src/question_comment.ts
index 7dfdc0ec79..f3ab230ea4 100644
--- a/src/question_comment.ts
+++ b/src/question_comment.ts
@@ -1,7 +1,5 @@
-import { Question } from "./question";
import { Serializer } from "./jsonobject";
import { QuestionFactory } from "./questionfactory";
-import { LocalizableString } from "./localizablestring";
import { QuestionTextBase } from "./question_textbase";
import { increaseHeightByContent } from "./utils/utils";
import { settings } from "./settings";
@@ -47,26 +45,31 @@ export class QuestionCommentModel extends QuestionTextBase {
* Default value: `false` (inherited from `SurveyModel`'s [`autoGrowComment`](https://surveyjs.io/form-library/documentation/surveymodel#autoGrowComment) property)
* @see allowResize
*/
- public get autoGrow(): boolean {
- return this.getPropertyValue("autoGrow") || (this.survey && this.survey.autoGrowComment);
+ public get autoGrow(): boolean | undefined {
+ return this.getPropertyValue("autoGrow");
}
- public set autoGrow(val: boolean) {
+ public set autoGrow(val: boolean | undefined) {
this.setPropertyValue("autoGrow", val);
}
+ public get renderedAutoGrow(): boolean {
+ const autoGrow = this.autoGrow;
+ return autoGrow === undefined && this.survey ? this.survey.autoGrowComment : !!autoGrow;
+ }
/**
- * Specifies whether to display a resize handle for the comment area.
*
* Default value: `true` (inherited from `SurveyModel`'s [`allowResizeComment`](https://surveyjs.io/form-library/documentation/surveymodel#allowResizeComment) property)
* @see autoGrow
*/
- public get allowResize(): boolean {
+ public get allowResize(): boolean | undefined {
return this.getPropertyValue("allowResize");
}
- public set allowResize(val: boolean) {
+ public set allowResize(val: boolean | undefined) {
this.setPropertyValue("allowResize", val);
}
public get renderedAllowResize(): boolean {
- return this.allowResize && (this.survey && this.survey.allowResizeComment) && !this.isPreviewStyle && !this.isReadOnlyStyle;
+ const res = this.allowResize;
+ const allowResize = res === undefined && this.survey ? this.survey.allowResizeComment : !!res;
+ return allowResize && !this.isPreviewStyle && !this.isReadOnlyStyle;
}
public get resizeStyle() {
return this.renderedAllowResize ? "both" : "none";
@@ -81,7 +84,7 @@ export class QuestionCommentModel extends QuestionTextBase {
super.afterRenderQuestionElement(el);
}
public updateElement(): void {
- if (this.element && this.autoGrow) {
+ if (this.element && this.renderedAutoGrow) {
setTimeout(() => increaseHeightByContent(this.element), 1);
}
}
@@ -138,8 +141,8 @@ Serializer.addClass(
default: "default",
choices: ["default", "onBlur", "onTyping"],
},
- { name: "autoGrow:boolean" },
- { name: "allowResize:boolean", default: true },
+ { name: "autoGrow:boolean", defaultFunc: () => undefined },
+ { name: "allowResize:boolean", defaultFunc: () => undefined },
{ name: "acceptCarriageReturn:boolean", default: true, visible: false }
],
function () {
diff --git a/src/question_custom.ts b/src/question_custom.ts
index c800c867f7..3f331731af 100644
--- a/src/question_custom.ts
+++ b/src/question_custom.ts
@@ -759,6 +759,9 @@ export abstract class QuestionCustomModelBase extends Question
validateContainerOnly(): void {
// do nothing
}
+ onQuestionValueChanged(el: IElement): void {
+ // do nothing
+ }
getQuestionErrorLocation(): string {
return this.getErrorLocation();
}
diff --git a/src/question_matrixdropdownbase.ts b/src/question_matrixdropdownbase.ts
index e7238c9950..5352fe8b93 100644
--- a/src/question_matrixdropdownbase.ts
+++ b/src/question_matrixdropdownbase.ts
@@ -1925,9 +1925,10 @@ export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel,
isOnValueChanged: boolean
@@ -431,7 +448,10 @@ export class QuestionTextModel extends QuestionTextBase {
);
}
private get isDateInputType(): boolean {
- return this.inputType === "date" || this.inputType === "datetime-local";
+ return this.inputType === "date" || this.isDateTimeLocaleType();
+ }
+ private isDateTimeLocaleType(): boolean {
+ return this.inputType === "datetime-local";
}
private getCalculatedMinMax(minMax: any): any {
if (this.isValueEmpty(minMax)) return minMax;
@@ -488,11 +508,10 @@ export class QuestionTextModel extends QuestionTextBase {
return this.maskTypeIsEmpty ? super.getIsInputTextUpdate() : false;
}
supportGoNextPageAutomatic(): boolean {
- return !this.getIsInputTextUpdate() &&
- ["date", "datetime-local"].indexOf(this.inputType) < 0;
+ return !this.getIsInputTextUpdate() && !this.isDateInputType;
}
public supportGoNextPageError(): boolean {
- return ["date", "datetime-local"].indexOf(this.inputType) < 0;
+ return !this.isDateInputType;
}
/**
* An array of predefined options from which users can select. This property configures an HTML [`