lodash#pullAt JavaScript Examples

The following examples show how to use lodash#pullAt. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: edit.js    From gutenberg-forms with GNU General Public License v2.0 4 votes vote down vote up
function edit(props) {
	let {
		options,
		isRequired,
		label,
		id,
		field_name,
		requiredLabel,
		messages,
		messages: { empty },
		condition,
		enableCondition,
		fieldStyle,
		bulkAdd,
		adminId,
		hint,
		showHint,
	} = props.attributes;

	const [checkboxes, setCheckboxes] = useState([]);
	const [focus, setFocus] = useState({
		f: false,
		index: null,
	});

	let checkboxContainer = useRef();

	const getRootData = () => {
		if (field_name === "" || detect_similar_forms(props.clientId)) {
			const newFieldName = getFieldName("checkbox", props.clientId);

			props.setAttributes({
				field_name: newFieldName,
				adminId: {
					value: extract_admin_id(newFieldName, "checkbox"),
					default: extract_admin_id(newFieldName, "checkbox"),
				},
			});

			props.setAttributes({
				id:
					props.clientId +
					"__" +
					getEncodedData(
						"checkbox",
						props.clientId,
						isRequired,
						get_admin_id(adminId)
					) +
					"[]",
			});
		} else if (field_name !== "") {
			props.setAttributes({
				id:
					extract_id(field_name) +
					"__" +
					getEncodedData(
						"checkbox",
						extract_id(field_name),
						isRequired,
						get_admin_id(adminId)
					) +
					"[]",
			});
		}
	};

	useEffect(() => {
		let { options } = props.attributes;

		setCheckboxes(options);
		getRootData();
	}, []);

	useEffect(() => getRootData(), [props]);

	const setMessages = (type, m) => {
		let newMessages = clone(messages);

		set(newMessages, type, m);

		props.setAttributes({ messages: newMessages });
	};

	useEffect(() => {
		if (bulkAdd) return;

		let boxes = checkboxContainer.current.querySelectorAll(
			'.cwp-checkbox-option input[type="text"]'
		);

		if (focus.f) {
			if (focus.index === null) {
				boxes[boxes.length - 1].focus();
			} else {
				boxes[focus.index].focus();
			}

			setFocus({ f: false, index: null });
		}
	}, [checkboxes, focus]); //subscribing to any further changes...

	const handleRequired = () => {
		const { isRequired } = props.attributes;

		props.setAttributes({ isRequired: !isRequired });
	};

	const addCheckbox = () => {
		let newOption = {
			label: "Option " + (checkboxes.length + 1),
			checked: false,
		};

		let new_options = clone(checkboxes);

		new_options.push(newOption);

		props.setAttributes({ options: new_options });
		setCheckboxes(new_options);
	};

	const handleDelete = (index) => {
		let new_options = clone(options);

		let deleted_options = pullAt(new_options, [index]); //dosen't matter :-D

		props.setAttributes({ options: new_options });
		setCheckboxes(new_options);
	};

	const handleLabel = (label) => {
		props.setAttributes({ label });
	};

	const handleChange = (e, index) => {
		let new_options = clone(options);

		new_options[index] = {
			...new_options[index],
			label: e.target.value,
		};

		setCheckboxes(new_options);
		props.setAttributes({ options: new_options });
	};

	const handleCheck = (v, index) => {
		let new_options = clone(options);

		new_options[index].checked = v;
		setCheckboxes(new_options);
		props.setAttributes({ options: new_options });
	};

	const handleImage = (img, index, action) => {
		let new_options = clone(options);

		if (action === "add") {
			new_options[index] = {
				...new_options[index],
				image: img,
			};
		}

		if (action === "remove") {
			const checkboxToRemove = new_options[index];
			new_options[index] = {
				label: checkboxToRemove.label,
			};
		}

		setCheckboxes(new_options);
		props.setAttributes({ options: new_options });
	};

	let handleDuplicate = (index) => {
		let new_options = clone(options);

		new_options.splice(index, 0, new_options[index]);

		setCheckboxes(new_options);
		props.setAttributes({ options: new_options });
	};

	let handleEnter = (index) => {
		let new_options = clone(options);

		new_options.splice(index + 1, 0, { label: "" });

		setCheckboxes(new_options);
		props.setAttributes({ options: new_options });
		setFocus({ f: true, index: index + 1 });
	};

	let handleBackspace = (index) => {
		if (checkboxes[index].label === "") {
			handleDelete(index);

			if (checkboxes[index - 1]) {
				setFocus({ f: true, index: index - 1 });
			}
		}
	};

	let clearAll = () => {
		const reset = [
			{
				label: "Option 1",
			},
		];

		setCheckboxes(reset);
		props.setAttributes({
			options: reset,
		});
	};

	const handleAdminId = (id) => {
		props.setAttributes({
			adminId: {
				...adminId,
				value: id.replace(/\s|-/g, "_"),
			},
		});
	};

	return [
		<InspectorControls>
			<PanelBody
				title={__("Field Settings", "cwp-gutenberg-forms")}
				initialOpen={true}
			>
				<div className="cwp-option">
					<TextControl
						placeholder={adminId.default}
						label={__("Field ID", "cwp-gutenberg-forms")}
						value={adminId.value}
						onChange={handleAdminId}
					/>
				</div>

				{!enableCondition ? (
					<PanelRow>
						<h3 className="cwp-heading">
							{__("Required", "cwp-gutenberg-forms")}
						</h3>
						<FormToggle
							label="Required"
							checked={isRequired}
							onChange={handleRequired}
						/>
					</PanelRow>
				) : (
					<div className="cwp-option">
						<p>
							<Icon icon="info" />{" "}
							{__(
								"You cannot set a conditional field required!",
								"cwp-gutenberg-forms"
							)}
						</p>
					</div>
				)}
				{isRequired && (
					<div className="cwp-option">
						<h3 className="cwp-heading">
							{__("Required Text", "cwp-gutenberg-forms")}
						</h3>
						<TextControl
							onChange={(label) =>
								props.setAttributes({ requiredLabel: label })
							}
							value={requiredLabel}
						/>
					</div>
				)}
				<div className="cwp-option">
					<SelectControl
						label={__("Layout", "cwp-gutenberg-forms")}
						value={fieldStyle}
						options={[
							{ label: __("Block", "cwp-gutenberg-forms"), value: "block" },
							{ label: __("Inline", "cwp-gutenberg-forms"), value: "inline" },
						]}
						onChange={(s) => {
							props.setAttributes({ fieldStyle: s });
						}}
					/>
				</div>
			</PanelBody>
			{isRequired && (
				<PanelBody title="Messages">
					<div className="cwp-option">
						<h3 className="cwp-heading">
							{__("Required Error", "cwp-gutenberg-forms")}
						</h3>
						<TextControl
							onChange={(label) => setMessages("empty", label)}
							value={messages.empty}
						/>
					</div>
				</PanelBody>
			)}
			<PanelBody title={__("Condition", "cwp-gutenberg-forms")}>
				<ConditionalLogic
					condition={condition}
					set={props.setAttributes}
					clientId={props.clientId}
					useCondition={props.attributes.enableCondition}
				/>
			</PanelBody>
			<PanelBody title={__("Show Hint", "cwp-gutenberg-forms")}>
				<div className="cwp-option">
					<FormToggle
						label="Show Hint"
						checked={showHint}
						onChange={() => props.setAttributes({ showHint: !showHint })}
					/>
					{showHint && (
						<Fragment>
							<TextControl
								label={__("Hint Text", "cwp-gutenberg-forms")}
								onChange={(hint) => props.setAttributes({ hint })}
								value={hint}
							/>
						</Fragment>
					)}
				</div>
			</PanelBody>
		</InspectorControls>,
		null,
		<div
			className={`cwp-checkbox cwp-field ${props.className} is-style-${fieldStyle}`}
		>
			{bulkAdd ? (
				<Bulk_Add onChange={(c) => setCheckboxes(c)} data={props} />
			) : (
				<Fragment>
					{!!props.isSelected && !enableCondition && (
						<div className="cwp-required">
							<h3>{__("Required", "cwp-gutenberg-forms")}</h3>
							<FormToggle checked={isRequired} onChange={handleRequired} />
						</div>
					)}

					<div
						ref={checkboxContainer}
						className={`cwp-checkbox-set-backend cwp-checkbox-set ${
							!props.isSelected ? "cwp-checkbox-set-preview" : ""
						}`}
					>
						<div className="cwp-label-wrap">
							<RichText
								placeholder={__("Add a label", "cwp-gutenberg-forms")}
								tag="label"
								value={label}
								onChange={handleLabel}
							/>

							{!props.isSelected && isRequired && !enableCondition && (
								<div className="cwp-required cwp-noticed">
									<h3>{requiredLabel}</h3>
								</div>
							)}
						</div>
						{checkboxes.map((checkbox, index) => {
							const hasImage = has(checkbox, "image"),
								image = hasImage ? checkbox.image.url : "";

							return (
								<Fragment>
									<div className="cwp-checkbox-option">
										<input
											id={id.concat(index.toString())}
											checked={checkbox.checked}
											type="checkbox"
											onClick={() => handleCheck(!checkbox.checked, index)}
										/>
										{!!props.isSelected && (
											<label
												style={{ width: "auto" }}
												for={id.concat(index.toString())}
												onClick={() => handleCheck(!checkbox.checked, index)}
											></label>
										)}
										{!!props.isSelected ? (
											<input
												onChange={(e) => handleChange(e, index)}
												onKeyDown={(e) => {
													e.key === "Enter" && handleEnter(index);
													e.key === "Backspace" && handleBackspace(index);
												}}
												type="text"
												value={checkbox.label}
											/>
										) : (
											<label>
												{checkbox.label}{" "}
												{hasImage && (
													<ImagePreview
														onEdit={(img) => handleImage(img, index, "add")}
														onRemove={() => handleImage(null, index, "remove")}
														isSelected={props.isSelected}
														image={checkbox.image}
													/>
												)}
											</label>
										)}
										{!!props.isSelected && (
											<Fragment>
												<ImageUpload
													icon="format-image"
													value={image}
													onSelect={(img) => handleImage(img, index, "add")}
												/>
												<Button
													isDefault
													onClick={() => handleDuplicate(index)}
												>
													<Icon icon="admin-page" />
												</Button>
												<Button isDefault onClick={() => handleDelete(index)}>
													<Icon icon="no-alt" />
												</Button>
											</Fragment>
										)}
									</div>
									{hasImage && props.isSelected && (
										<ImagePreview
											onEdit={(img) => handleImage(img, index, "add")}
											onRemove={() => handleImage(null, index, "remove")}
											isSelected={props.isSelected}
											image={checkbox.image}
										/>
									)}
								</Fragment>
							);
						})}
						{!!props.isSelected && (
							<div className="cwp-checkbox-controls">
								<div>
									<Button isDefault onClick={addCheckbox}>
										{__("Add Option", "cwp-gutenberg-forms")}
									</Button>
									<Button
										isDefault
										onClick={() => props.setAttributes({ bulkAdd: true })}
									>
										{__("Bulk Add", "cwp-gutenberg-forms")}
									</Button>
								</div>
								<div>
									<Button onClick={clearAll}>
										{__("Clear All", "cwp-gutenberg-forms")}
									</Button>
								</div>
							</div>
						)}
					</div>
				</Fragment>
			)}
			{showHint && <p className="cwp-hint">{hint}</p>}
		</div>,
	];
}
Example #2
Source File: edit.js    From gutenberg-forms with GNU General Public License v2.0 4 votes vote down vote up
function edit(props) {
	let {
		options,
		isRequired,
		label,
		id,
		field_name,
		requiredLabel,
		messages: { empty },
		messages,
		condition,
		enableCondition,
		fieldStyle,
		bulkAdd,
		adminId,
		hint,
		showHint,
	} = props.attributes;

	const radiosContainer = useRef();

	const [radios, setRadios] = useState([]);

	const [focus, setFocus] = useState({
		f: false,
		index: null,
	});

	const getRootData = () => {
		if (field_name === "" || detect_similar_forms(props.clientId)) {
			const newFieldName = getFieldName("radio", props.clientId);

			props.setAttributes({
				field_name: newFieldName,
				adminId: {
					value: extract_admin_id(newFieldName, "radio"),
					default: extract_admin_id(newFieldName, "radio"),
				},
			});
			props.setAttributes({
				id:
					props.clientId +
					"__" +
					getEncodedData(
						"radio",
						props.clientId,
						isRequired,
						get_admin_id(adminId)
					),
			});
		} else if (field_name !== "") {
			props.setAttributes({
				id:
					extract_id(field_name) +
					"__" +
					getEncodedData(
						"radio",
						extract_id(field_name),
						isRequired,
						get_admin_id(adminId)
					),
			});
		}
	};

	useEffect(() => {
		let rootMessages = getRootMessages(props.clientId, "radio");

		if (rootMessages) {
			const newMessages = clone(messages);

			assign(newMessages, rootMessages);

			props.setAttributes({ messages: newMessages });
		}

		let { options } = props.attributes;

		const checked = options.find((c) => c.checked);

		if (checked) {
			let opt = clone(options);

			let remove_extra_checked = opt.map((v) => {
				if (!isEqual(v, checked)) {
					return {
						...v,
						checked: false,
					};
				} else return v;
			});
			setRadios(remove_extra_checked);
		} else {
			setRadios(options);
		}

		getRootData();
	}, []);

	useEffect(() => getRootData(), [props]);

	useEffect(() => {
		if (bulkAdd) return;

		let boxes = radiosContainer.current.querySelectorAll(
			'.cwp-radios-option input[type="text"]'
		);

		if (focus.f) {
			if (focus.index === null) {
				boxes[boxes.length - 1].focus();
			} else {
				boxes[focus.index].focus();
			}

			setFocus({ f: false, index: null });
		}
	}, [radios, focus]); //subscribing to any further changes...

	const handleRequired = () => {
		const { isRequired } = props.attributes;

		props.setAttributes({ isRequired: !isRequired });
	};

	const addRadio = () => {
		let newOption = {
			label: "Option " + (radios.length + 1),
			checked: false,
		};

		let new_options = clone(radios);

		new_options.push(newOption);

		props.setAttributes({ options: new_options });
		setRadios(new_options);
	};

	const handleDelete = (index) => {
		let new_options = clone(options);

		let deleted_options = pullAt(new_options, [index]); //dosen't matter :-D

		props.setAttributes({ options: new_options });
		setRadios(new_options);
	};

	const handleLabel = (label) => {
		props.setAttributes({ label });
	};

	const handleChange = (e, index) => {
		let new_options = clone(options);

		new_options[index] = {
			...new_options[index],
			label: e.target.value,
		};

		setRadios(new_options);
		props.setAttributes({ options: new_options });
	};

	const handleCheck = (c, index) => {
		let new_options = clone(options);

		new_options.forEach((v) => (v.checked = false));

		new_options[index].checked = c;

		setRadios(new_options);
		props.setAttributes({ options: new_options });
	};

	const handleImage = (img, index, action) => {
		let new_options = clone(options);

		if (action === "add") {
			new_options[index] = {
				...new_options[index],
				image: img,
			};
		}

		if (action === "remove") {
			const RadioToRemove = new_options[index];
			new_options[index] = {
				label: RadioToRemove.label,
			};
		}

		setRadios(new_options);
		props.setAttributes({ options: new_options });
	};

	let handleDuplicate = (index) => {
		let new_options = clone(options);

		new_options.splice(index, 0, new_options[index]);

		setRadios(new_options);
		props.setAttributes({ options: new_options });
	};

	let handleEnter = (index) => {
		let new_options = clone(options);

		new_options.splice(index + 1, 0, { label: "" });

		setRadios(new_options);
		props.setAttributes({ options: new_options });
		setFocus({ f: true, index: index + 1 });
	};

	let handleBackspace = (index) => {
		if (radios[index].label === "") {
			handleDelete(index);

			if (radios[index - 1]) {
				setFocus({ f: true, index: index - 1 });
			}
		}
	};

	const setMessages = (type, m) => {
		let newMessages = clone(messages);

		set(newMessages, type, m);

		props.setAttributes({ messages: newMessages });
	};

	let clearAll = () => {
		const reset = [
			{
				label: "Option 1",
			},
		];

		setRadios(reset);
		props.setAttributes({
			options: reset,
		});
	};

	const handleAdminId = (id) => {
		props.setAttributes({
			adminId: {
				...adminId,
				value: id.replace(/\s|-/g, "_"),
			},
		});
	};

	return [
		<InspectorControls>
			<PanelBody title="Field Settings" initialOpen={true}>
				<div className="cwp-option">
					<TextControl
						placeholder={adminId.default}
						label={__("Field ID", "cwp-gutenberg-forms")}
						value={adminId.value}
						onChange={handleAdminId}
					/>
				</div>

				{!enableCondition ? (
					<PanelRow>
						<h3 className="cwp-heading">
							{__("Required", "cwp-gutenberg-forms")}
						</h3>
						<FormToggle
							label="Required"
							checked={isRequired}
							onChange={handleRequired}
						/>
					</PanelRow>
				) : (
					<div className="cwp-option">
						<p>
							<Icon icon="info" />{" "}
							{__(
								"You cannot set a conditional field required!",
								"cwp-gutenberg-forms"
							)}
						</p>
					</div>
				)}
				{isRequired && (
					<div className="cwp-option">
						<h3 className="cwp-heading">
							{__("Required Text", "cwp-gutenberg-forms")}
						</h3>
						<TextControl
							onChange={(label) =>
								props.setAttributes({ requiredLabel: label })
							}
							value={requiredLabel}
						/>
					</div>
				)}
				<div className="cwp-option">
					<SelectControl
						label={__("Layout", "cwp-gutenberg-forms")}
						value={fieldStyle}
						options={[
							{ label: __("Block", "cwp-gutenberg-forms"), value: "block" },
							{ label: __("Inline", "cwp-gutenberg-forms"), value: "inline" },
						]}
						onChange={(s) => {
							props.setAttributes({ fieldStyle: s });
						}}
					/>
				</div>
			</PanelBody>
			<PanelBody title={__("Show Hint", "cwp-gutenberg-forms")}>
				<div className="cwp-option">
					<FormToggle
						label="Show Hint"
						checked={showHint}
						onChange={() => props.setAttributes({ showHint: !showHint })}
					/>
					{showHint && (
						<Fragment>
							<TextControl
								label={__("Hint Text", "cwp-gutenberg-forms")}
								onChange={(hint) => props.setAttributes({ hint })}
								value={hint}
							/>
						</Fragment>
					)}
				</div>
			</PanelBody>
			<PanelBody title="Condition">
				<ConditionalLogic
					condition={condition}
					set={props.setAttributes}
					clientId={props.clientId}
					useCondition={props.attributes.enableCondition}
				/>
			</PanelBody>

			{isRequired && (
				<PanelBody title={__("Messages", "cwp-gutenberg-forms")}>
					<div className="cwp-option">
						<h3 className="cwp-heading">
							{__("Required Error", "cwp-gutenberg-forms")}
						</h3>
						<TextControl
							onChange={(label) => setMessages("empty", label)}
							value={empty}
						/>
					</div>
				</PanelBody>
			)}
		</InspectorControls>,
		null,
		<div
			className={`cwp-radios cwp-field ${props.className} is-style-${fieldStyle}`}
		>
			{bulkAdd ? (
				<Bulk_Add onChange={(c) => setRadios(c)} data={props} />
			) : (
				<Fragment>
					{!!props.isSelected && !enableCondition && (
						<div className="cwp-required">
							<h3>{__("Required", "cwp-gutenberg-forms")}</h3>
							<FormToggle checked={isRequired} onChange={handleRequired} />
						</div>
					)}

					<div
						ref={radiosContainer}
						className={`cwp-radios-set ${
							!props.isSelected ? "cwp-radio-set-preview" : ""
						}`}
					>
						<div className="cwp-label-wrap">
							<RichText
								placeholder={__("Add a label", "cwp-gutenberg-forms")}
								tag="label"
								value={label}
								onChange={handleLabel}
							/>
							{!props.isSelected && isRequired && !enableCondition && (
								<div className="cwp-required cwp-noticed">
									<h3>{requiredLabel}</h3>
								</div>
							)}
						</div>
						{radios.map((radio, index) => {
							const hasImage = has(radio, "image"),
								image = hasImage ? radio.image.url : "";

							return (
								<Fragment>
									<div className="cwp-radios-option">
										<input
											id={id.concat(index.toString())}
											checked={radio.checked}
											onClick={() => handleCheck(!radio.checked, index)}
											type="radio"
										/>
										{!!props.isSelected && (
											<label
												style={{ width: "auto" }}
												onClick={() => handleCheck(!radio.checked, index)}
												for={id.concat(index.toString())}
											></label>
										)}
										{!!props.isSelected ? (
											<input
												onKeyDown={(e) => {
													e.key === "Enter" && handleEnter(index);
													e.key === "Backspace" && handleBackspace(index);
												}}
												onChange={(e) => handleChange(e, index)}
												type="text"
												value={radio.label}
											/>
										) : (
											<label>
												{radio.label}{" "}
												{hasImage && !props.isSelected && (
													<ImagePreview
														onEdit={(img) => handleImage(img, index, "add")}
														onRemove={() => handleImage(null, index, "remove")}
														isSelected={props.isSelected}
														image={radio.image}
													/>
												)}
											</label>
										)}
										{!!props.isSelected && (
											<Fragment>
												<ImageUpload
													icon="format-image"
													value={image}
													onSelect={(img) => handleImage(img, index, "add")}
												/>
												<Button
													isDefault
													onClick={() => handleDuplicate(index)}
												>
													<Icon icon="admin-page" />
												</Button>
												<Button isDefault onClick={() => handleDelete(index)}>
													<Icon icon="no-alt" />
												</Button>
											</Fragment>
										)}
									</div>
									{hasImage && !!props.isSelected && (
										<ImagePreview
											onEdit={(img) => handleImage(img, index, "add")}
											onRemove={() => handleImage(null, index, "remove")}
											isSelected={props.isSelected}
											image={radio.image}
										/>
									)}
								</Fragment>
							);
						})}
						{!!props.isSelected && (
							<div className="cwp-radios-controls">
								<div>
									<Button isDefault onClick={addRadio}>
										{__("Add Option", "cwp-gutenberg-forms")}
									</Button>
									<Button
										isDefault
										onClick={() => props.setAttributes({ bulkAdd: true })}
									>
										{__("Bulk Add", "cwp-gutenberg-forms")}
									</Button>
								</div>
								<div>
									<Button onClick={clearAll}>
										{__("Clear All", "cwp-gutenberg-forms")}
									</Button>
								</div>
							</div>
						)}
					</div>
				</Fragment>
			)}
			{showHint && (
                <p className="cwp-hint">{hint}</p>
            )}
		</div>,
	];
}
Example #3
Source File: edit.js    From gutenberg-forms with GNU General Public License v2.0 4 votes vote down vote up
function edit(props) {
	let {
		options,
		isRequired,
		label,
		id,
		field_name,
		requiredLabel,
		messages: { empty },
		messages,
		condition,
		enableCondition,
		bulkAdd,
		adminId,
	} = props.attributes;

	const [select, setSelect] = useState([]);

	const [focus, setFocus] = useState({
		f: false,
		index: null,
	});

	const selectContainer = useRef();

	const getRootData = () => {
		if (field_name === "" || detect_similar_forms(props.clientId)) {
			const newFieldName = getFieldName("select", props.clientId);

			props.setAttributes({
				field_name: newFieldName,
				adminId: {
					value: extract_admin_id(newFieldName, "select"),
					default: extract_admin_id(newFieldName, "select"),
				},
			});
			props.setAttributes({
				id:
					props.clientId +
					"__" +
					getEncodedData(
						"select",
						props.clientId,
						isRequired,
						get_admin_id(adminId)
					),
			});
		} else if (field_name !== "") {
			props.setAttributes({
				id:
					extract_id(field_name) +
					"__" +
					getEncodedData(
						"select",
						extract_id(field_name),
						isRequired,
						get_admin_id(adminId)
					),
			});
		}
	};

	useEffect(() => {
		let rootMessages = getRootMessages(props.clientId, "select");

		if (rootMessages) {
			const newMessages = clone(messages);

			assign(newMessages, rootMessages);

			props.setAttributes({ messages: newMessages });
		}

		let { options } = props.attributes;

		setSelect(options);

		getRootData();
	}, []);

	useEffect(() => getRootData(), [props]);

	useEffect(() => {
		if (bulkAdd) return;

		let boxes = selectContainer.current.querySelectorAll(
			'.cwp-select-option input[type="text"]'
		);

		if (focus.f) {
			if (focus.index === null) {
				boxes[boxes.length - 1].focus();
			} else {
				boxes[focus.index].focus();
			}

			setFocus({ f: false, index: null });
		}
	}, [select, focus]); //subscribing to any further changes...

	const handleRequired = () => {
		const { isRequired } = props.attributes;

		props.setAttributes({ isRequired: !isRequired });
	};

	const addSelect = () => {
		let newOption = {
			label: "Option " + (select.length + 1),
		};

		let new_options = clone(select);

		new_options.push(newOption);

		props.setAttributes({ options: new_options });
		setSelect(new_options);
	};

	const handleDelete = (index) => {
		let new_options = clone(options);

		let deleted_options = pullAt(new_options, [index]); //dosen't matter :-D

		props.setAttributes({ options: new_options });
		setSelect(new_options);
	};

	const handleLabel = (label) => {
		props.setAttributes({ label });
	};

	const handleChange = (e, index) => {
		let new_options = clone(options);

		new_options[index] = {
			...new_options[index],
			label: e.target.value,
		};

		setSelect(new_options);
		props.setAttributes({ options: new_options });
	};

	let handleDuplicate = (index) => {
		let new_options = clone(options);

		new_options.splice(index, 0, new_options[index]);

		setSelect(new_options);
		props.setAttributes({ options: new_options });
	};

	let handleEnter = (index) => {
		let new_options = clone(options);

		new_options.splice(index + 1, 0, { label: "" });

		setSelect(new_options);
		props.setAttributes({ options: new_options });
		setFocus({ f: true, index: index + 1 });
	};

	let handleBackspace = (index) => {
		if (select[index].label === "") {
			handleDelete(index);

			if (select[index - 1]) {
				setFocus({ f: true, index: index - 1 });
			}
		}
	};

	const setMessages = (type, m) => {
		let newMessages = clone(messages);

		set(newMessages, type, m);

		props.setAttributes({ messages: newMessages });
	};

	let clearAll = () => {
		const reset = [
			{
				label: "Option 1",
			},
		];

		setSelect(reset);
		props.setAttributes({
			options: reset,
		});
	};

	const handleAdminId = (id) => {
		props.setAttributes({
			adminId: {
				...adminId,
				value: id.replace(/\s|-/g, "_"),
			},
		});
	};

	const editView = select.map((s, index) => {
		return (
			<div className="cwp-select-option">
				<input
					aria-label={strip_tags(label)}
					onChange={(e) => handleChange(e, index)}
					type="text"
					value={s.label}
					onKeyDown={(e) => {
						e.key === "Enter" && handleEnter(index);
						e.key === "Backspace" && handleBackspace(index);
					}}
				/>
				<Button isDefault onClick={() => handleDuplicate(index)}>
					<Icon icon="admin-page" />
				</Button>
				<Button isDefault onClick={() => handleDelete(index)}>
					<Icon icon="no-alt" />
				</Button>
			</div>
		);
	});

	const SelectView = () => {
		return (
			<select data-cwp-field>
				<option value="" disabled selected>
					Select your option
				</option>
				{select.map((s, index) => {
					return <option value={s.label}>{s.label}</option>;
				})}
			</select>
		);
	};

	return [
		<InspectorControls>
			<PanelBody title={__("Field Settings", "cwp-gutenberg-forms")} initialOpen={true}>
				<div className="cwp-option">
					<TextControl
						placeholder={adminId.default}
						label={__("Field ID", "cwp-gutenberg-forms")}
						value={adminId.value}
						onChange={handleAdminId}
					/>
				</div>

				{!enableCondition ? (
					<PanelRow>
						<h3 className="cwp-heading">{__("Required", "cwp-gutenberg-forms")}</h3>
						<FormToggle
							label={__("Required", "cwp-gutenberg-forms")}
							checked={isRequired}
							onChange={handleRequired}
						/>
					</PanelRow>
				) : (
					<div className="cwp-option">
						<p>
							<Icon icon="info" />{" "}
							{__("You cannot set a conditional field required!", "cwp-gutenberg-forms")}
						</p>
					</div>
				)}
				{isRequired && (
					<div className="cwp-option">
						<h3 className="cwp-heading">{__("Required Text", "cwp-gutenberg-forms")}</h3>
						<TextControl
							onChange={(label) =>
								props.setAttributes({ requiredLabel: label })
							}
							value={requiredLabel}
						/>
					</div>
				)}
			</PanelBody>
			<PanelBody title={__("Condition", "cwp-gutenberg-forms")}>
				<ConditionalLogic
					condition={condition}
					set={props.setAttributes}
					clientId={props.clientId}
					useCondition={props.attributes.enableCondition}
				/>
			</PanelBody>
			{isRequired && (
				<PanelBody title={__("Messages", "cwp-gutenberg-forms")}>
					<div className="cwp-option">
						<h3 className="cwp-heading">{__("Required Error", "cwp-gutenberg-forms")}</h3>
						<TextControl
							onChange={(label) => setMessages("empty", label)}
							value={empty}
						/>
					</div>
				</PanelBody>
			)}
		</InspectorControls>,
		null,
		<div
			className={`cwp-select cwp-field ${
				!props.isSelected ? props.className : ""
			}`}
		>
			{bulkAdd ? (
				<Bulk_Add onChange={(c) => setSelect(c)} data={props} />
			) : (
				<Fragment>
					{!!props.isSelected && !enableCondition && (
						<div className="cwp-required">
							<h3>{__("Required", "cwp-gutenberg-forms")}</h3>
							<FormToggle checked={isRequired} onChange={handleRequired} />
						</div>
					)}

					<div className="cwp-select-set" ref={selectContainer}>
						<div className="cwp-label-wrap">
							<RichText
								placeholder={__("Add a label", "cwp-gutenberg-forms")}
								tag="label"
								value={label}
								onChange={handleLabel}
							/>
							{!props.isSelected && isRequired && !enableCondition && (
								<div className="cwp-required cwp-noticed">
									<h3>{requiredLabel}</h3>
								</div>
							)}
						</div>
						{!!props.isSelected ? editView : <SelectView />}
						{!!props.isSelected && (
							<div className="cwp-select-controls">
								<div>
									<Button isDefault onClick={addSelect}>
										{__("Add Option", "cwp-gutenberg-forms")}
									</Button>
									<Button
										isDefault
										onClick={() => props.setAttributes({ bulkAdd: true })}
									>
										{__("Bulk Add", "cwp-gutenberg-forms")}
									</Button>
								</div>
								<div>
									<Button onClick={clearAll}>
										{__("Clear All", "cwp-gutenberg-forms")}
									</Button>
								</div>
							</div>
						)}
					</div>
				</Fragment>
			)}
		</div>,
	];
}
Example #4
Source File: edit.js    From gutenberg-forms with GNU General Public License v2.0 4 votes vote down vote up
function edit(props) {
	let {
		options,
		isRequired,
		label,
		id,
		field_name,
		requiredLabel,
		messages: { empty },
		messages,
		condition,
		enableCondition,
		bulkAdd,
		adminId,
		hint,
		showHint
	} = props.attributes;

	const [select, setSelect] = useState([]);

	const [focus, setFocus] = useState({
		f: false,
		index: null,
	});

	const selectContainer = useRef();

	const getRootData = () => {
		if (field_name === "" || detect_similar_forms(props.clientId)) {
			const newFieldName = getFieldName("select", props.clientId);

			props.setAttributes({
				field_name: newFieldName,
				adminId: {
					value: extract_admin_id(newFieldName, "select"),
					default: extract_admin_id(newFieldName, "select"),
				},
			});
			props.setAttributes({
				id:
					props.clientId +
					"__" +
					getEncodedData(
						"select",
						props.clientId,
						isRequired,
						get_admin_id(adminId)
					),
			});
		} else if (field_name !== "") {
			props.setAttributes({
				id:
					extract_id(field_name) +
					"__" +
					getEncodedData(
						"select",
						extract_id(field_name),
						isRequired,
						get_admin_id(adminId)
					),
			});
		}
	};

	useEffect(() => {
		let rootMessages = getRootMessages(props.clientId, "select");

		if (rootMessages) {
			const newMessages = clone(messages);

			assign(newMessages, rootMessages);

			props.setAttributes({ messages: newMessages });
		}

		let { options } = props.attributes;

		setSelect(options);

		getRootData();
	}, []);

	useEffect(() => getRootData(), [props]);

	useEffect(() => {
		if (bulkAdd) return;

		let boxes = selectContainer.current.querySelectorAll(
			'.cwp-select-option input[type="text"]'
		);

		if (focus.f) {
			if (focus.index === null) {
				boxes[boxes.length - 1].focus();
			} else {
				boxes[focus.index].focus();
			}

			setFocus({ f: false, index: null });
		}
	}, [select, focus]); //subscribing to any further changes...

	const handleRequired = () => {
		const { isRequired } = props.attributes;

		props.setAttributes({ isRequired: !isRequired });
	};

	const addSelect = () => {
		let newOption = {
			label: "Option " + (select.length + 1),
		};

		let new_options = clone(select);

		new_options.push(newOption);

		props.setAttributes({ options: new_options });
		setSelect(new_options);
	};

	const handleDelete = (index) => {
		let new_options = clone(options);

		let deleted_options = pullAt(new_options, [index]); //dosen't matter :-D

		props.setAttributes({ options: new_options });
		setSelect(new_options);
	};

	const handleLabel = (label) => {
		props.setAttributes({ label });
	};

	const handleChange = (e, index) => {
		let new_options = clone(options);

		new_options[index] = {
			...new_options[index],
			label: e.target.value,
		};

		setSelect(new_options);
		props.setAttributes({ options: new_options });
	};

	let handleDuplicate = (index) => {
		let new_options = clone(options);

		new_options.splice(index, 0, new_options[index]);

		setSelect(new_options);
		props.setAttributes({ options: new_options });
	};

	let handleEnter = (index) => {
		let new_options = clone(options);

		new_options.splice(index + 1, 0, { label: "" });

		setSelect(new_options);
		props.setAttributes({ options: new_options });
		setFocus({ f: true, index: index + 1 });
	};

	let handleBackspace = (index) => {
		if (select[index].label === "") {
			handleDelete(index);

			if (select[index - 1]) {
				setFocus({ f: true, index: index - 1 });
			}
		}
	};

	const setMessages = (type, m) => {
		let newMessages = clone(messages);

		set(newMessages, type, m);

		props.setAttributes({ messages: newMessages });
	};

	let clearAll = () => {
		const reset = [
			{
				label: "Option 1",
			},
		];

		setSelect(reset);
		props.setAttributes({
			options: reset,
		});
	};

	const handleAdminId = (id) => {
		props.setAttributes({
			adminId: {
				...adminId,
				value: id.replace(/\s|-/g, "_"),
			},
		});
	};

	const editView = select.map((s, index) => {
		return (
			<div className="cwp-select-option">
				<input
					aria-label={strip_tags(label)}
					onChange={(e) => handleChange(e, index)}
					type="text"
					value={s.label}
					onKeyDown={(e) => {
						e.key === "Enter" && handleEnter(index);
						e.key === "Backspace" && handleBackspace(index);
					}}
				/>
				<Button isDefault onClick={() => handleDuplicate(index)}>
					<Icon icon="admin-page" />
				</Button>
				<Button isDefault onClick={() => handleDelete(index)}>
					<Icon icon="no-alt" />
				</Button>
			</div>
		);
	});

	const SelectView = () => {
		return (
			<select data-cwp-field>
				{select.map((s, index) => {
					return <option value={s.label}>{s.label}</option>;
				})}
			</select>
		);
	};

	return [
		<InspectorControls>
			<PanelBody title={__("Field Settings", "cwp-gutenberg-forms")} initialOpen={true}>
				<div className="cwp-option">
					<TextControl
						placeholder={adminId.default}
						label={__("Field ID", "cwp-gutenberg-forms")}
						value={adminId.value}
						onChange={handleAdminId}
					/>
				</div>

				{!enableCondition ? (
					<PanelRow>
						<h3 className="cwp-heading">{__("Required", "cwp-gutenberg-forms")}</h3>
						<FormToggle
							label={__("Required", "cwp-gutenberg-forms")}
							checked={isRequired}
							onChange={handleRequired}
						/>
					</PanelRow>
				) : (
					<div className="cwp-option">
						<p>
							<Icon icon="info" />{" "}
							{__("You cannot set a conditional field required!", "cwp-gutenberg-forms")}
						</p>
					</div>
				)}
				{isRequired && (
					<div className="cwp-option">
						<h3 className="cwp-heading">{__("Required Text", "cwp-gutenberg-forms")}</h3>
						<TextControl
							onChange={(label) =>
								props.setAttributes({ requiredLabel: label })
							}
							value={requiredLabel}
						/>
					</div>
				)}
			</PanelBody>
			<PanelBody title={__("Show Hint", "cwp-gutenberg-forms")}>
				<div className="cwp-option">
					<FormToggle
						label="Show Hint"
						checked={showHint}
						onChange={() => props.setAttributes({ showHint: !showHint })}
					/>
					{showHint && (
						<Fragment>
							<TextControl
								label={__("Hint Text", "cwp-gutenberg-forms")}
								onChange={(hint) => props.setAttributes({ hint })}
								value={hint}
							/>
						</Fragment>
					)}
				</div>
			</PanelBody>
			<PanelBody title={__("Condition", "cwp-gutenberg-forms")}>
				<ConditionalLogic
					condition={condition}
					set={props.setAttributes}
					clientId={props.clientId}
					useCondition={props.attributes.enableCondition}
				/>
			</PanelBody>
			{isRequired && (
				<PanelBody title={__("Messages", "cwp-gutenberg-forms")}>
					<div className="cwp-option">
						<h3 className="cwp-heading">{__("Required Error", "cwp-gutenberg-forms")}</h3>
						<TextControl
							onChange={(label) => setMessages("empty", label)}
							value={empty}
						/>
					</div>
				</PanelBody>
			)}
		</InspectorControls>,
		null,
		<div
			className={`cwp-select cwp-field ${
				!props.isSelected ? props.className : ""
			}`}
		>
			{bulkAdd ? (
				<Bulk_Add onChange={(c) => setSelect(c)} data={props} />
			) : (
				<Fragment>
					{!!props.isSelected && !enableCondition && (
						<div className="cwp-required">
							<h3>{__("Required", "cwp-gutenberg-forms")}</h3>
							<FormToggle checked={isRequired} onChange={handleRequired} />
						</div>
					)}

					<div className="cwp-select-set" ref={selectContainer}>
						<div className="cwp-label-wrap">
							<RichText
								placeholder={__("Add a label", "cwp-gutenberg-forms")}
								tag="label"
								value={label}
								onChange={handleLabel}
							/>
							{!props.isSelected && isRequired && !enableCondition && (
								<div className="cwp-required cwp-noticed">
									<h3>{requiredLabel}</h3>
								</div>
							)}
						</div>
						{!!props.isSelected ? editView : <SelectView />}
						{!!props.isSelected && (
							<div className="cwp-select-controls">
								<div>
									<Button isDefault onClick={addSelect}>
										{__("Add Option", "cwp-gutenberg-forms")}
									</Button>
									<Button
										isDefault
										onClick={() => props.setAttributes({ bulkAdd: true })}
									>
										{__("Bulk Add", "cwp-gutenberg-forms")}
									</Button>
								</div>
								<div>
									<Button onClick={clearAll}>
										{__("Clear All", "cwp-gutenberg-forms")}
									</Button>
								</div>
							</div>
						)}
					</div>
				</Fragment>
			)}
			{showHint && (
                <p className="cwp-hint">{hint}</p>
            )}
		</div>,
	];
}