Tworzenie własnych elementów.
Każdy element kreatora DXPR to obiekt JavaScript wepchnięty na
window.dxprBuilder.dxpr_elements. Edytor zamienia każdy obiekt
w klasę elementu z dołączonymi kartami Style i Animation. Ta strona pokazuje,
jak zdefiniowane są dostarczone elementy w
dxpr_builder/dxpr_elements.js, jak moduł dodaje własną
definicję do edytora i jak wygląda wynikowy HTML.
Nie ma szablonów Twig po stronie serwera dla elementu; elementy
renderują się w przeglądarce.
Jak edytor rejestruje elementy
Edytor wczytuje sześć skryptów w tej kolejności, zdefiniowanych w
dxpr_builder_library_info_build() w dxpr_builder.module jako biblioteka
dxpr_builder/editor.builder:
dxpr_templates.js: szablony twig.js po stronie klienta skompilowane zdxpr_builder/templates/.dxpr_global.js: współdzielone helpery i integracja CKEditor 5.dxpr_events.jsdxpr_param_types.js: wpycha jeden obiekt na typ wejścia nawindow.dxprBuilder.dxpr_param_types.dxpr_elements.js: tworzy tablicęwindow.dxprBuilder.dxpr_elementsi wpycha jedną definicję na element.dxpr_builder.js: edytor. Gdy ten plik się wykona, wywołujecreate_dxpr_elements(), które przechodzi pętląwindow.dxprBuilder.dxpr_elementsi dla każdej definicji:- wywołuje
register_animated_element(base, is_container, Class), więc klasa rozszerzaAnimatedElement(karta Style, karta Animation, HTML ID, klasy HTML i parametry umiejscowienia); - dołącza odziedziczone parametry do
paramsdefinicji; - konwertuje każdy parametr przez
make_param_type(), które dopasowujeparam.typedo zarejestrowanych typów parametrów; - wmiesza właściwości definicji do prototypu klasy.
- wywołuje
Definicja musi więc znaleźć się na tablicy po wykonaniu
dxpr_elements.js i przed wykonaniem dxpr_builder.js. Wszystkie
sześć plików ładuje się z atrybutem defer, więc kolejność dokumentów
tagów script jest kolejnością wykonania.
Definicja elementu
Tak wygląda element Alert z dxpr_builder/dxpr_elements.js
(źródło: dxpr_builder/build/dxpr-elements/elements/az_alert.js),
przycięty do właściwości potrzebnych każdemu elementowi. Oryginał
ustawia też el_class, handler onCancel i listener focusout.
window.dxprBuilder.dxpr_elements.push({
base: "az_alert",
name: Drupal.t("Alert"),
nameEn: "Alert",
icon: "az-custom-icon az-alert-icon",
largeSettingsWindow: true,
hidden: false,
params: [
{
type: "textarea",
heading: Drupal.t("Message"),
param_name: "content",
value: Drupal.t(
"This is a placeholder text. Your actual content will go here. Edit this to include your own information.",
),
},
{
type: "dropdown",
heading: Drupal.t("Type"),
param_name: "type",
description: Drupal.t("Select message type."),
getText: (opt) => opt.text,
getValue: (opt) => opt.value,
getDefault: (param) => param.value["alert-success"].value,
value: {
"alert-success": { text: Drupal.t("Success"), value: "alert-success" },
"alert-info": { text: Drupal.t("Info"), value: "alert-info" },
"alert-warning": { text: Drupal.t("Warning"), value: "alert-warning" },
"alert-danger": { text: Drupal.t("Danger"), value: "alert-danger" },
},
passthrough: true,
},
],
show_settings_on_create: true,
has_content: true,
render(...args) {
const state = {
class: `az-element az-alert alert ${this.attrs.type} ${this.get_el_classes()} ${this.get_content_classes()}`,
style: this.attrs.style,
message: this.attrs.content,
};
this.dom_element = this.baseclass.prototype.render_template(
"elements/alert/alert",
state,
);
this.baseclass.prototype.render.apply(this, args);
},
save_history() {
const container = this.get_my_container();
container.save_container_history(Drupal.t("Edit alert"));
},
});
| Właściwość | Przeznaczenie |
|---|---|
base |
Nazwa maszynowa. Zapisywana jest do zapisanego HTML jako data-azb="az_alert" i służy do znalezienia klasy, gdy strona jest ponownie parsowana. Zachowaj prefiks az_. |
name, nameEn |
Etykieta w wybieraku elementów i jej nieprzetłumaczona forma. |
icon |
Klasy CSS ikony wybieraka. Dostarczone ikony zdefiniowane są w dxpr_builder/sass/dxpr-builder-backend/components/_custom-icons.scss; własny element potrzebuje własnego CSS dla klasy ikony. |
category |
Karta wybieraka. Elementy układu używają Drupal.t("Layout"); bloki i widoki używają "CMS". Pomiń dla domyślnej karty treści. |
is_container |
true, gdy element zawiera inne elementy. |
largeSettingsWindow |
Otwiera okno ustawień w większym rozmiarze. |
hidden |
Ukrywa element przed wybierakiem, zachowując jego renderowalność. |
params |
Ustawienia pokazywane w oknie. Zobacz poniżej. |
show_settings_on_create |
Otwiera okno ustawień, gdy tylko element zostanie upuszczony. |
has_content |
Element ma edytowalny obszar treści (dom_content_element). |
render(...args) |
Buduje this.dom_element z this.attrs, potem wywołuje bazowe render. |
save_history() |
Wpycha wpis cofania z etykietą. |
parse_attrs_from_dom(element) |
Opcjonalne. Odczytuje wartości parametrów z powrotem z zapisanego HTML, używane wraz z skip_data_azb i skip_params przez elementy takie jak Image, które przechowują wartości w atrybutach <img> zamiast data-azat-*. |
Parametry
Każdy wpis w params ma:
| Klucz | Znaczenie |
|---|---|
type |
Jeden z zarejestrowanych typów parametrów (następna sekcja). |
heading |
Etykieta pola. |
param_name |
Klucz w this.attrs i, w zapisanym HTML, atrybut data-azat-<param_name>. content jest specjalne: to treść elementu, nie atrybut. |
value |
Wartość domyślna. Dla dropdown to obiekt opcji z callbackami getText, getValue i getDefault. |
description |
Tekst pomocy pod polem. |
tab |
Grupuje pole w nazwany akordeon, na przykład Drupal.t("SEO"). |
can_be_empty |
Przechowaj pusty ciąg zamiast porzucać atrybut. |
safe |
Pomiń kodowanie URL przechowywanej wartości. |
Typy parametrów to wartości type wepchnięte na
window.dxprBuilder.dxpr_param_types w
dxpr_builder/dxpr_param_types.js: boxmodel, checkbox,
checkboxes, colorpicker, datetime, dropdown, dxb_slider,
html, icon, image, images, link, links, numericfield,
row_layout, saved_datetime, social_links, textarea,
textfield i video. Typ, którego nie zarejestrujesz, wraca do
zwykłego wejścia tekstowego (BaseParamType).
Nie używaj ponownie param_name, które dziedziczy każdy element, takiego jak
color, background, el_class, hash albo nazwy animacji an_*. Karta Style już posiada color, więc drugi parametr
o tej nazwie nigdy nie jest zapisywany do data-azat-color.
Co się zapisuje
update_data() w dxpr_builder.js zapisuje element do HTML:
data-azb="<base>"na elemencie głównym;data-azat-<param_name>="<value>"dla każdego parametru, którego wartość różni się od domyślnej, kodowane URL, chyba że parametr ustawiasafe: true;- parametry karty Style jako osadzone
stylei klasy, nigdy jako atrybutydata-azat-*; data-azcnt="true"na elemencie treści, gdy ustawionohas_content.
Odwiedzający bez edytora otrzymują ten HTML bez jego
atrybutów data-az*: DxprBuilderService::parseDocumentForCleanup()
usuwa je, poza stałą listą zachowywaną na elementach animowanych i
na wbudowanych elementach dynamicznych takich jak Carousel. Jeśli
element potrzebuje JavaScript albo CSS dla odwiedzających, umieść
atrybut data-dxpr-builder-libraries="<key>" na jego elemencie głównym:
parseDocumentForTemplateLibrary() dołącza
dxpr_builder/elements.<key> dla każdego klucza bez ukośnika. Klucze
to biblioteki elements.* w dxpr_builder.libraries.yml;
klucz z ukośnikiem honorowany jest tylko, gdy jest library zarejestrowanego
zestawu ikon.
Minimalny działający przykład
Przykład dodaje element „Notice”, który renderuje akapit z
wybranym kolorem. Buduje swój DOM bezpośrednio, ponieważ skompilowane szablony twig.js
w dxpr_templates.js są częścią pakietu edytora i
nie mogą być rozszerzane przez inny moduł.
-
Utwórz
mymodule/js/notice-element.js:window.dxprBuilder.dxpr_elements.push({ base: "az_notice", name: Drupal.t("Notice"), nameEn: "Notice", icon: "az-custom-icon az-alert-icon", params: [ { type: "textfield", heading: Drupal.t("Text"), param_name: "text", value: Drupal.t("Notice text"), }, { type: "colorpicker", heading: Drupal.t("Colour"), param_name: "notice_color", value: "#0d6efd", }, ], show_settings_on_create: true, render(...args) { const el = document.createElement("div"); el.className = `az-element az-notice ${this.get_el_classes()}`; if (this.attrs.style) { el.setAttribute("style", this.attrs.style); } const p = document.createElement("p"); p.style.color = this.attrs.notice_color; p.textContent = this.attrs.text; el.appendChild(p); this.dom_element = el; this.baseclass.prototype.render.apply(this, args); }, save_history() { this.get_my_container().save_container_history(Drupal.t("Edit notice")); }, }); -
Wstaw plik do biblioteki edytora między
dxpr_elements.js(waga-4) adxpr_builder.js(waga-3) wmymodule.module:/** * Implements hook_library_info_alter(). */ function mymodule_library_info_alter(array &$libraries, string $extension): void { if ($extension === 'dxpr_builder' && isset($libraries['editor.builder'])) { $path = '/' . \Drupal::service('extension.list.module')->getPath('mymodule'); $libraries['editor.builder']['js'][$path . '/js/notice-element.js'] = [ 'weight' => -3.5, 'preprocess' => FALSE, 'attributes' => ['defer' => TRUE], ]; } }preprocess: FALSEideferodpowiadają wpisom definiowanym przez moduł dla własnych plików, więc plik zachowuje swoje miejsce w sekwencji niezależnie od tego, czy pliki edytora pochodzą z CDN, czy z lokalnej kompilacji. -
Wyczyść pamięć podręczną i otwórz stronę kreatora:
drush cr -
Dodaj element z wybieraka, ustaw jego tekst i kolor, i zapisz. Pole przechowuje:
<div class="az-element az-notice" id="..." data-azb="az_notice" data-azat-text="Hello" data-azat-notice_color="%23198754"> <p style="color: #198754;">Hello</p> </div>Odwiedzający dostaje ten sam HTML bez atrybutów
data-az*. Akapit zachowuje swój osadzony kolor, więc ten element nie potrzebuje biblioteki dla odwiedzających.
Ograniczenia, o których warto wiedzieć
- Profile nie wymieniają własnych elementów. Lista kontrolna elementów
w profilu kreatora pochodzi ze stałej listy w
src/Form/DxprBuilderProfileForm.phpisrc/Service/Handler/ProfileHandler.php. Elementy spoza tej listy nigdy nie są ukrywane przez profil. - Ikony dla wybieraka potrzebują CSS z twojego modułu;
klasy
az-custom-icondostarczane przez kreator obejmują tylko dostarczone elementy. DxprBuilderService::getDxprElementsFolders()i jegohook_dxpr_builder_elements_folders_alter()zwracają listę katalogówelementsw motywach, ale nic w edytorze nie odczytuje tej listy. To nie jest trasa rejestracji.- Karty Style i Animation dodawane są za ciebie przez
register_animated_element(); nie redefiniuj tych parametrów.
Co dalej?
- Hooki API dla hooków PHP dodających klasy narzędziowe i zestawy ikon.
- Architektura dla dopasowania edytora i formatera pola do siebie.