Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Describe theme API and fix theme applying instructions #7102

Merged
merged 2 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 61 additions & 27 deletions docs/manage-default-themes-and-styles.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ SurveyJS Form Library is shipped with several predefined UI themes. You can see

![Themes in SurveyJS Form Library](images/survey-library-themes.png)

To use a theme, you need to reference a SurveyJS style sheet. Refer to the following sections of Get Started help topics for detailed instructions:
To use a theme, you need to reference a SurveyJS style sheet. Refer to the following sections of Get Started help topics for detailed instructions:

- [Configure Styles in Angular](https://surveyjs.io/form-library/documentation/get-started-angular#configure-styles)
- [Configure Styles in Vue](https://surveyjs.io/form-library/documentation/get-started-vue#configure-styles)
Expand All @@ -22,25 +22,73 @@ To use a theme, you need to reference a SurveyJS style sheet. Refer to the follo

## Apply a Predefined Theme

Predefined themes are distributed as JSON objects that specify CSS variables and other theme settings. You can find a full list of predefined themes and their variations on GitHub: [survey-core/themes](https://github.com/surveyjs/survey-library/tree/master/src/themes). To apply a predefined theme, import its module or reference its script _after_ `survey-core`. The following code shows how to apply the Layered Dark Panelless theme by importing a module:
Predefined themes are distributed as JSON objects that specify CSS variables and other theme settings. You can find a full list of predefined themes and their variations on GitHub: [survey-core/themes](https://github.com/surveyjs/survey-library/tree/master/src/themes).

To apply a predefined theme in modular applications, import the theme object from its module and pass the object to `SurveyModel`'s [`applyTheme(theme)`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#applyTheme) method. The following code shows how to apply the Layered Dark Panelless theme:

```js
import { Model } from "survey-core";
import "survey-core/themes/layered-dark-panelless";
/*
Don't forget to import or reference the Default V2 style sheet
as described in the Get Started with SurveyJS article for your framework
*/
import { LayeredDarkPanelless } "survey-core/themes/layered-dark-panelless";

const surveyJson = { ... };
const survey = new Model(surveyJson);
survey.applyTheme(LayeredDarkPanelless);
```

The code below applies the same theme by referencing a script:
In classic script applications, reference a theme script _after_ the `survey-core` script and style sheet. Pass the theme object to the `applyTheme(theme)` method, as shown below:

```html
<head>
<!-- ... -->
<link href="https://unpkg.com/survey-core/defaultV2.min.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/survey-core/survey.core.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/survey-core/layered-dark-panelless.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/survey-core/themes/layered-dark-panelless.min.js"></script>
<!-- ... -->
</head>
```

If you want to add more than one theme, refer to the [Switch Between Themes](#switch-between-themes) section for more information.
```js
const surveyJson = { ... };
const survey = new Survey.Model(surveyJson);
survey.applyTheme(SurveyTheme.LayeredDarkPanelless);
```

## Switch Between Themes

If you want to add more than one SurveyJS theme to your application, import them or reference their scripts and call `SurveyModel`'s [`applyTheme(theme)`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#applyTheme) method to specify an active theme. For example, the following code imports the Contrast Dark and Contrast Light themes and applies the latter:

```js
// In modular applications:
import { Model } from "survey-core";
import { ContrastDark } from "survey-core/themes/contrast-dark";
import { ContrastLight } from "survey-core/themes/contrast-light";

const surveyJson = { ... };
const survey = new Model(surveyJson);
survey.applyTheme(ContrastLight);
```

```html
<!-- In classic script applications: -->
<head>
<!-- ... -->
<link href="https://unpkg.com/survey-core/defaultV2.min.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/survey-core/survey.core.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/survey-core/themes/contrast-dark.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/survey-core/themes/contrast-light.min.js"></script>
<!-- ... -->
</head>
```

```js
const surveyJson = { ... };
const survey = new Survey.Model(surveyJson);
survey.applyTheme(SurveyTheme.ContrastLight);
```

## Create a Custom Theme

Expand All @@ -52,37 +100,23 @@ Theme Editor is integrated into Survey Creator. Open our [all-in-one demo](/crea

<img src="images/theme-export.png" alt="SurveyJS Theme Export">

To apply your custom theme, pass the downloaded JSON object to `SurveyModel`'s `applyTheme()` method:
To apply your custom theme, pass the downloaded JSON object to `SurveyModel`'s [`applyTheme(theme)`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#applyTheme) method:

```js
import { Model } from "survey-core";
const surveyJson = { ... };
const survey = new Model(surveyJson);

survey.applyTheme({
"cssVariables": {
// ...
},
"themeName": "double",
"colorPalette": "dark",
"isPanelless": true
"cssVariables": {
// ...
},
"themeName": "doubleborder",
"colorPalette": "dark",
"isPanelless": true
});
```

## Switch Between Themes

If you want to add more than one SurveyJS theme to your application, import them using named imports and call `SurveyModel`'s `applyTheme()` method to specify an active theme. For example, the following code imports the Contrast Dark and Contrast Light themes and applies the latter:

```js
import { Model } from "survey-core";
import { ContrastLight } from "survey-core/themes/contrast-light";
import { ContrastDark } from "survey-core/themes/contrast-dark";

const surveyJson = { ... };
const survey = new Model(surveyJson);
survey.applyTheme(ContrastLight)
```

## Apply Custom CSS Classes

You can apply individual custom CSS classes to all survey elements of a specific type. To do this, define a JavaScript object in which keys specify survey elements and values specify CSS classes. For information on the object structure, refer to the following file on GitHub: [defaultV2Css.ts](https://github.com/surveyjs/survey-library/blob/master/src/defaultCss/defaultV2Css.ts#L13). Assign this object to [`SurveyModel`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model)'s `css` property.
Expand Down
16 changes: 9 additions & 7 deletions docs/sidebar.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,18 +233,20 @@
"Title": "Panel Dynamic"
},
{
"Name": "settings",
"Title": "Global Settings"
"Name": "IAction",
"Title": "IAction"
},
{
"Name": "IAction",
"Title": "IAction",
"IsHidden": true
"Name": "ITheme",
"Title": "ITheme"
},
{
"Name": "ICustomQuestionTypeConfiguration",
"Title": "ICustomQuestionTypeConfiguration",
"IsHidden": true
"Title": "ICustomQuestionTypeConfiguration"
},
{
"Name": "settings",
"Title": "Global Settings"
}
]
}
Expand Down
23 changes: 17 additions & 6 deletions src/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ export class SurveyModel extends SurveyElementCore
private navigationBarValue: ActionContainer;

onThemeApplying: EventBase<SurveyModel> = new EventBase<SurveyModel>();
/**
* An event that is raised after a [theme](/form-library/documentation/manage-default-themes-and-styles) is [applied](#applyTheme) to the survey.
* @see applyTheme
*/
onThemeApplied: EventBase<SurveyModel> = new EventBase<SurveyModel>();

//#region Event declarations
Expand Down Expand Up @@ -3342,7 +3346,7 @@ export class SurveyModel extends SurveyElementCore
this.onCurrentPageChanged.fire(this, options);
}
private notifyQuestionsOnHidingContent(page: PageModel): void {
if(!page) return;
if (!page) return;
page.questions.forEach(q => q.onHidingContent());
}
private createPageChangeEventOptions(newValue: PageModel, oldValue: PageModel): any {
Expand Down Expand Up @@ -5685,7 +5689,7 @@ export class SurveyModel extends SurveyElementCore
}
}
private runQuestionsTriggers(name: string, value: any): void {
if(this.isDisplayMode || this.isDesignMode) return;
if (this.isDisplayMode || this.isDesignMode) return;
const questions = this.getAllQuestions();
questions.forEach(q => q.runTriggers(name, value));
}
Expand Down Expand Up @@ -7333,6 +7337,13 @@ export class SurveyModel extends SurveyElementCore
this.onPopupVisibleChanged.fire(this, { question, popup, visible });
}

/**
* Applies a specified theme to the survey.
*
* [Themes & Styles](/form-library/documentation/manage-default-themes-and-styles (linkStyle))
* @param theme An [`ITheme`](/form-library/documentation/api-reference/itheme) object with theme settings.
* @see onThemeApplied
*/
public applyTheme(theme: ITheme): void {
if (!theme) return;

Expand Down Expand Up @@ -7391,20 +7402,20 @@ export class SurveyModel extends SurveyElementCore
public addScrollEventListener(): void {
this.scrollHandler = () => { this.onScroll(); };
this.rootElement.addEventListener("scroll", this.scrollHandler);
if(!!this.rootElement.getElementsByTagName("form")[0]) {
if (!!this.rootElement.getElementsByTagName("form")[0]) {
this.rootElement.getElementsByTagName("form")[0].addEventListener("scroll", this.scrollHandler);
}
if(!!this.css.rootWrapper) {
if (!!this.css.rootWrapper) {
this.rootElement.getElementsByClassName(this.css.rootWrapper)[0]?.addEventListener("scroll", this.scrollHandler);
}
}
public removeScrollEventListener(): void {
if (!!this.rootElement && !!this.scrollHandler) {
this.rootElement.removeEventListener("scroll", this.scrollHandler);
if(!!this.rootElement.getElementsByTagName("form")[0]) {
if (!!this.rootElement.getElementsByTagName("form")[0]) {
this.rootElement.getElementsByTagName("form")[0].removeEventListener("scroll", this.scrollHandler);
}
if(!!this.css.rootWrapper) {
if (!!this.css.rootWrapper) {
this.rootElement.getElementsByClassName(this.css.rootWrapper)[0]?.removeEventListener("scroll", this.scrollHandler);
}
}
Expand Down
52 changes: 52 additions & 0 deletions src/themes.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,66 @@
export type ImageFit = "auto" | "contain" | "cover";
export type ImageAttachment = "fixed" | "scroll";

/**
* A theme configuration interface.
*
* `ITheme` objects are used to apply predefined themes or create custom themes. Refer to the following help topic for more information:
*
* [Themes & Styles](https://surveyjs.io/form-library/documentation/manage-default-themes-and-styles (linkStyle))
*/
export interface ITheme {
/**
* A theme name.
*/
themeName?: string;
/**
* A color palette.
*
* Possible values:
*
* - `"light"`
* - `"dark"`
*/
colorPalette?: string;
/**
* A Boolean value that specifies whether survey questions are displayed within panels (`false`) or without them (`true`).
*/
isPanelless?: boolean;
/**
* An image to display as survey background. This property accepts a hyperlink or a data URL.
*/
backgroundImage?: string;
/**
* A string value that specifies how to resize the [background image](#backgroundImage) to fit it into its container.
*
* Possible values:
*
* - `"auto"`
* - `"contain"`
* - `"cover"`
*
* Refer to the description of the [`background-size`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-size#values) CSS property values on MDN for detailed information on the possible values.
*/
backgroundImageFit?: ImageFit;
/**
* A string value that specifies whether the [background image](#backgroundImage) is fixed in its position or scrolled along with the survey.
*
* Possible values:
*
* - `"fixed"`
* - `"scroll"`
*/
backgroundImageAttachment?: ImageAttachment;
/**
* A value from 0 to 1 that specifies how transparent the [background image](#backgroundImage) should be: 0 makes the image completely transparent, and 1 makes it opaque.
*/
backgroundOpacity?: number;
/**
* An object with survey header settings.
*/
cover?: {[index: string]: any};
/**
* An object with CSS variables.
*/
cssVariables?: { [index: string]: string };
}
Loading