import {
consoleInfo,
getNode,
objectToAttributes,
spacerClasses,
trigger,
uniqueId,
} from '@gravityforms/utils';
/**
* @function inputTemplate
* @description Generates the markup for a input in the admin.
*
* @since 1.1.16
*
* @param {object} options The options for the component template.
* @param {object} options.customAttributes Any custom attributes.
* @param {Array} options.customClasses An array of additional classes for the toggle.
* @param {string} options.id Id for the input, auto generated if not passed.
* @param {string} options.inputPrefix The prefix for the input.
* @param {string} options.inputSuffix The suffix for the input.
* @param {string} options.label For radio or checkboxes, the label text.
* @param {string} options.labelAttributes Any other arbitrary attributes to add to the label.
* @param {string} options.labelClasses Space separated string of classes to add to the label.
* @param {string} options.placeholder Input placeholder text.
* @param options.actionButton
* @param options.actionButtonIcon
* @param {string|number|Array|object} options.spacing The spacing for the component, string, number, object or array.
* @param {string} options.theme Theme for the toggle, primary or cosmos.
* @param {string} options.type Input type: `text`, `email`, `tel`, `url`, `checkbox` or `radio`.
* @param {string} options.value The value for the input.
*
* @return {string}
* @example
* import { inputTemplate } from '@gravityforms/components/html/admin/elements/Input';
*
* function Example() {
* const inputTemplateHTML = inputTemplateTemplate( options );
* document.body.insertAdjacentHTML( 'beforeend', inputTemplateHTML );
* }
*
*/
export const inputTemplate = ( {
actionButton = false,
actionButtonIcon = 'eye',
customAttributes = {},
customClasses = [],
id = uniqueId( 'input' ),
inputPrefix = '',
inputSuffix = '',
label = '',
labelAttributes = '',
labelClasses = '',
placeholder = '',
spacing = '',
theme = 'primary',
type = 'text',
value = '',
} ) => {
let labelHtml = '';
const placeholderAttr = placeholder && ( type !== 'radio' || type !== 'checkbox' ) ? ` placeholder="${ placeholder }"` : '';
const inputWrapperClasses = `${ inputPrefix ? 'gform-input-add-on-wrapper--prefix' : '' } ${ inputSuffix ? 'gform-input-add-on-wrapper--suffix' : '' } ${ actionButton ? 'gform-input-add-on-wrapper--action-button' : '' }`;
const inputWrapperOpen = inputPrefix || inputSuffix || actionButton ? `<div class="gform-input-add-on-wrapper ${ inputWrapperClasses }">` : '';
const inputWrapperClose = inputPrefix || inputSuffix || actionButton ? `</div>` : '';
const inputPrefixContent = inputPrefix ? `<div class="gform-input__add-on gform-input__add-on--prefix">${ inputPrefix }</div>` : '';
const inputSuffixContent = inputSuffix ? `<div class="gform-input__add-on gform-input__add-on--suffix">${ inputSuffix }</div>` : '';
let actionButtonContent = '';
if ( actionButton ) {
actionButtonContent = `
<button class="gform-button gform-button--size-sm gform-button--secondary gform-button--icon-leading gform-input__add-on gform-input__add-on--action-button">
<i class="gform-button__icon gform-common-icon gform-common-icon--${ actionButtonIcon }" data-js="button-icon"></i>
</button>
`;
}
if ( label && ( type === 'radio' || type === 'checkbox' ) ) {
const forAttr = id ? ` for="${ id }"` : '';
labelHtml = `
<label
${ forAttr }
class="gform-label gform-input__label gform-input__label--${ type } ${ labelClasses }"
${ labelAttributes }
>
${ label }
</label>
`;
}
const componentAttrs = objectToAttributes( {
...customAttributes,
id,
type,
value,
class: [
'gform-input',
`gform-input--theme-${ theme }`,
( type !== 'radio' && type !== 'checkbox' ) && `gform-input`,
( type !== 'radio' && type !== 'checkbox' ) && `gform-input--text`,
( type === 'radio' || type === 'checkbox' ) && `gform-input--${ type }`,
...Object.keys( spacerClasses( spacing ) ),
...customClasses,
],
} );
return `
${ inputWrapperOpen }
${ inputPrefixContent }
<input
${ placeholderAttr }
${ componentAttrs }
/>
${ inputSuffixContent }
${ actionButtonContent }
${ inputWrapperClose }
${ labelHtml }
`;
};
/**
* @class Input
* @description A input component .
*
* @since 1.1.16
*
* @borrows inputTemplate as inputTemplate
*
* @param {object} options The options for the component.
* @param {object} options.customAttributes Any custom attributes for the component.
* @param {Array} options.customClasses An array of additional classes for the component.
* @param {string} options.id Id for the component, auto generated if not passed.
* @param {string} options.inputPrefix The prefix for the input.
* @param {string} options.inputSuffix The suffix for the input.
* @param {string} options.label For radio or checkboxes, the label text.
* @param {string} options.labelAttributes Any other arbitrary attributes to add to the label.
* @param {string} options.labelClasses Space separated string of classes to add to the label.
* @param {string} options.placeholder Input placeholder text.
* @param {string} options.rendered Is the component already rendered in the dom, eg by php?
* @param {string} options.renderOnInit Render the component on init of the class?
* @param {string} options.spacing Spacing for the component.
* @param {string} options.target The target to render to. Any valid css selector string.
* @param {string} options.targetPosition The insert position for the component relative to the target.
* @param {string} options.theme Theme for the component, primary or cosmos.
* @param {string} options.type Input type: `text`, `email`, `tel`, `url`, `checkbox` or `radio`.
* @param {string} options.value The value for the input.
*
* @return {Class} The class instance.
* @example
* import Input from '@gravityforms/components/html/admin/elements/Input';
*
* function Example() {
* const inputInstance = new Input( {
* id: 'example-input',
* renderOnInit: false,
* target: '#example-target',
* targetPosition: 'beforeend',
* theme: 'cosmos',
* } );
*
* // Some time later we can render it. This is only done if we set renderOnInit to false.
* // If true it will render on initialization.
* inputInstance.init();
* }
*
*/
export default class Input {
constructor( options = {} ) {
this.options = {};
Object.assign(
this.options,
{
actionButton: false,
actionButtonIcon: 'eye',
customAttributes: {},
customClasses: [],
id: '',
inputPrefix: '',
inputSuffix: '',
label: '',
labelAttributes: '',
labelClasses: '',
placeholder: '',
rendered: false,
renderOnInit: true,
spacing: '',
target: '',
targetPosition: 'afterbegin',
theme: 'cosmos',
type: 'text',
value: '',
},
options
);
/**
* @event gform/input/pre_init
* @type {object}
* @description Fired before the component has started any internal init functions. A great chance to augment the options.
*
* @since 1.1.16
*
* @property {object} instance The Component class instance.
*/
trigger( { event: 'gform/input/pre_init', native: false, data: { instance: this } } );
this.options.id = this.options.id || uniqueId( 'toggle' );
this.elements = {};
if ( this.options.renderOnInit ) {
this.init();
}
}
/**
* @memberof Input
* @description Renders the component into the dom.
*
* @since 1.1.16
*
* @return {void}
*/
render() {
const { rendered, target, targetPosition } = this.options;
if ( ! rendered ) {
const renderTarget = getNode( target, document, true );
renderTarget.insertAdjacentHTML(
targetPosition,
inputTemplate( this.options )
);
}
this.elements.input = getNode( `#${ this.options.id }`, document, true );
}
/**
* @memberof Input
* @description Initialize the component.
*
* @fires gform/input/post_render
*
* @since 1.1.16
*
* @return {void}
*/
init() {
this.render();
/**
* @event gform/input/post_render
* @type {object}
* @description Fired when the component has completed rendering and all class init functions have completed.
*
* @since 1.1.16
*
* @property {object} instance The Component class instance.
*/
trigger( { event: 'gform/input/post_render', native: false, data: { instance: this } } );
consoleInfo( `Gravity Forms Admin: Initialized input component.` );
}
}