Advertisement
Guest User

Untitled

a guest
Mar 30th, 2020
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React = require("react");
  2. import Promise = require("bluebird");
  3. import {FormEvent, HTMLProps, FocusEvent, CSSProperties} from "react";
  4. import {IEventTargetInput} from "../../interfaces/IEventTargetInput";
  5. import {json_merge_recursive} from "../../../utils/utils";
  6. import {IOptionsAttribute} from "../../../data/AttributeGroup";
  7. import {OptionBool} from "../../controlPanel/controlOfPanel/OptionBool";
  8. import {OptionNumber} from "../../controlPanel/controlOfPanel/OptionNumber";
  9. import {IGenericControlProps} from "../../controls/GenericControlProps";
  10. import {autobind} from "core-decorators";
  11. import * as autosize from "autosize";
  12. import {If} from "../../utils/If";
  13. import {ObservableComponent} from "../../../utils/mobx/ObservableComponent";
  14. import {observable} from "mobx";
  15. import {lazyInject} from "../../../core/dependency-container/decorators";
  16. import {SettingsServiceIdentifier} from "../../../core/dependency-container/identifiers";
  17. import {SettingsServiceInterface} from "../../../services/settings/SettingsServiceInterface";
  18.  
  19. const styles = require("./TextAreaControl.less");
  20.  
  21. export interface ITextAreaControlProps extends IGenericControlProps {
  22.   value?: string;
  23.   placeholder?: string;
  24.   onChange?: (value: string) => Promise<any>;
  25.   errorMessage?: string;
  26.   disableResize?: boolean;
  27.   realtime?: boolean;
  28.   style?: CSSProperties;
  29.   showLabel?: boolean;
  30.   maxSize?: number;
  31. }
  32.  
  33. export interface ITextAreaControlState {
  34. }
  35.  
  36. export class TextAreaControl<P extends ITextAreaControlProps = ITextAreaControlProps, S extends ITextAreaControlState = ITextAreaControlState> extends ObservableComponent<P, S> {
  37.  
  38.   @observable
  39.   private valueSize: number = 0;
  40.  
  41.   @observable
  42.   private showCountIndicatorSetting: boolean = false;
  43.  
  44.   @lazyInject(SettingsServiceIdentifier)
  45.   private settingService: SettingsServiceInterface;
  46.  
  47.   componentWillReceiveProps(props: Readonly<P>) {
  48.     if (this.props.value !== props.value) {
  49.       this.valueSize = (props.value || "").length;
  50.       this.setValue(props.value);
  51.     }
  52.   }
  53.  
  54.   private getTextArea(): HTMLTextAreaElement {
  55.     return this.refs["textarea"] as HTMLTextAreaElement;
  56.   }
  57.  
  58.   private get$TextArea(): JQuery {
  59.     return $(this.getTextArea());
  60.   }
  61.  
  62.   @autobind
  63.   protected handleBlur(event: FocusEvent<HTMLTextAreaElement> | FormEvent<HTMLTextAreaElement>) {
  64.     const target: IEventTargetInput = event.target;
  65.     let value = target.value;
  66.     if (value === "") {
  67.       value = null;
  68.     }
  69.     if (this.props.onChange && this.props.value !== value) {
  70.       this.props.onChange(value);
  71.     }
  72.   }
  73.  
  74.   protected get visible(): boolean {
  75.     return true;
  76.   }
  77.  
  78.   protected get header(): JSX.Element {
  79.     if (!this.props.showLabel) {
  80.       return null;
  81.     }
  82.  
  83.     let headerContent = this.props.labelContent;
  84.     if (typeof headerContent === "string") {
  85.       return <span>{headerContent}</span>;
  86.     } else if (React.isValidElement(headerContent)) {
  87.       return headerContent;
  88.     } else {
  89.       return null;
  90.     }
  91.   }
  92.  
  93.   protected get value() {
  94.     return (this.props.value != null) ? this.props.value : "";
  95.   }
  96.  
  97.   protected get errorMessage(): string {
  98.     return this.props.errorMessage;
  99.   }
  100.  
  101.   public static get defaultOptions(): IOptionsAttribute {
  102.     return {
  103.       visualSettingsButtons: {
  104.         reSize: {
  105.           component: OptionBool,
  106.           value: false,
  107.           content: "glyphicon glyphicon-pushpin",
  108.           tooltip: "Разрешить изменение размера поля",
  109.           ident: "reSize"
  110.         },
  111.         ColRow: {
  112.           component: OptionNumber,
  113.           value: 5,
  114.           content: "glyphicon glyphicon-resize-vertical",
  115.           tooltip: "Количество строк в текстовом поле",
  116.           ident: "ColRow"
  117.         },
  118.         AutoHeight: {
  119.           component: OptionBool,
  120.           value: true,
  121.           content: "glyphicon glyphicon-sort-by-attributes",
  122.           tooltip: "Автоподбор высоты по содержимому",
  123.           ident: "AutoHeight"
  124.         },
  125.         countIndicator: {
  126.           component: OptionBool,
  127.           value: false,
  128.           content: "glyphicon glyphicon-font",
  129.           tooltip: "Индикация количества символов в многострочных полях",
  130.           ident: "countIndicator"
  131.         }
  132.       }
  133.     };
  134.   }
  135.  
  136.   protected get options() {
  137.     if (!this.props.options) {
  138.       return TextAreaControl.defaultOptions;
  139.     } else {
  140.       const jsonDef = TextAreaControl.defaultOptions;
  141.       const jsonOpt = this.props.options;
  142.       return json_merge_recursive(jsonOpt, jsonDef);
  143.     }
  144.   }
  145.  
  146.   protected get placeholder() {
  147.     return (this.props.placeholder) ? this.props.placeholder : "";
  148.   }
  149.  
  150.   protected get readonly() {
  151.     return (this.props.readonly !== undefined) ? this.props.readonly : false;
  152.   }
  153.  
  154.   setValue(value: string) {
  155.     this.get$TextArea().val(value);
  156.     autosize.update(this.getTextArea());
  157.   }
  158.  
  159.   private get styles(): CSSProperties {
  160.     const options = this.options;
  161.     let styles: CSSProperties = {};
  162.     let resizeStyle = options.visualSettingsButtons.reSize.value ? "vertical" : "none";
  163.     if (this.props.disableResize === true) {
  164.       resizeStyle = "none";
  165.     }
  166.     if (this.readonly) {
  167.       styles.backgroundColor = "#eee";
  168.       styles.cursor = "not-allowed";
  169.     }
  170.     const inputFieldSettingsStyles = options.OptionsOfAttr && options.OptionsOfAttr.inputFieldSettings || {};
  171.     return $.extend({resize: resizeStyle}, inputFieldSettingsStyles, this.props.style, {...styles});
  172.   }
  173.  
  174.   @autobind
  175.   protected onBlur(event: FocusEvent<HTMLTextAreaElement> | FormEvent<HTMLTextAreaElement>) {
  176.     if (this.props.onBlur) {
  177.       this.props.onBlur();
  178.     }
  179.     this.handleBlur(event);
  180.   }
  181.  
  182.   @autobind
  183.   protected onFocus() {
  184.     if (this.props.onFocus) {
  185.       this.props.onFocus();
  186.     }
  187.   }
  188.  
  189.   onDidMount(): void {
  190.     this.settingService.showCountIndicator().then(res => {
  191.       this.showCountIndicatorSetting = res;
  192.     });
  193.     this.valueSize = (this.props.value || "").length;
  194.     if (this.options.visualSettingsButtons.AutoHeight.value) {
  195.       autosize(this.getTextArea());
  196.     }
  197.   }
  198.  
  199.   onWillUnmount(): void {
  200.     autosize.destroy(this.getTextArea());
  201.   }
  202.  
  203.   private get size() {
  204.     return this.props.maxSize || this.props.typeAttr && this.props.typeAttr.size;
  205.   }
  206.  
  207.   private get showCountIndicator() {
  208.     const visualSettingsButtons = this.options && this.options.visualSettingsButtons;
  209.     const optionsIndicatorValue = visualSettingsButtons && visualSettingsButtons.countIndicator.value;
  210.     return this.showCountIndicatorSetting || optionsIndicatorValue;
  211.   }
  212.  
  213.   @autobind
  214.   private valueChange(event) {
  215.     let value = event.target.value;
  216.     this.valueSize = value.length;
  217.     this.props.realtime && this.handleBlur(event);
  218.   }
  219.  
  220.   render() {
  221.     const value = this.value || "";
  222.     const placeholder: string = this.placeholder;
  223.     const readonly: boolean = this.readonly;
  224.     const tabIndex: number = readonly ? -1 : null;
  225.     const error: string = this.errorMessage;
  226.     const options = this.options;
  227.     let textAriaControl: HTMLProps<HTMLTextAreaElement>;
  228.  
  229.     if (this.props.realtime) {
  230.       textAriaControl = {
  231.         value: value
  232.       };
  233.     } else {
  234.       textAriaControl = {
  235.         defaultValue: value
  236.       };
  237.     }
  238.  
  239.     let containerStyles: CSSProperties = {
  240.       display: this.visible ? "block" : "none"
  241.     };
  242.  
  243.     if (this.props.style && this.props.style.height) {
  244.       containerStyles.height = this.props.style.height;
  245.     }
  246.  
  247.  
  248.     return (
  249.       <span style={containerStyles} title={error ? error : "текстовое поле"}
  250.             className={error ? "error" : ""}>
  251.         {this.header}
  252.         <textarea ref="textarea"
  253.                   className={"form-control " + (this.props.errorHighlight ? " text-control-error" : " text-control") + (this.props.className || "")}
  254.                   rows={options.visualSettingsButtons.ColRow.value}
  255.                   placeholder={placeholder}
  256.                   readOnly={readonly}
  257.                   tabIndex={tabIndex}
  258.                   style={this.styles} {...textAriaControl}
  259.                   onFocus={this.onFocus}
  260.                   onBlur={this.onBlur}
  261.                   maxLength={this.size}
  262.                   onChange={this.valueChange}/>
  263.         <If cond={this.showCountIndicator && this.size != null}>
  264.           <div className={styles["countIndicator"]}><span>{this.valueSize}/{this.size}</span></div>
  265.         </If>
  266.       </span>
  267.     );
  268.   }
  269. }
  270.  
  271. export {TextAreaControl as Control};
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement