Creare elementi personalizzati.
Ogni elemento di DXPR Builder è un oggetto JavaScript inserito in
window.dxprBuilder.dxpr_elements. L’editor trasforma ogni oggetto
in una classe di elemento con le schede Style e Animation già
collegate. Questa pagina mostra come sono definiti gli elementi inclusi in
dxpr_builder/dxpr_elements.js, come un modulo aggiunge la sua
definizione all’editor e come appare l’HTML risultante.
Non esistono modelli Twig lato server per elemento; gli elementi
sono renderizzati nel browser.
Come l’editor registra gli elementi
L’editor carica sei script in quest’ordine, definiti in
dxpr_builder_library_info_build() in dxpr_builder.module come
libreria dxpr_builder/editor.builder:
dxpr_templates.js: modelli twig.js lato client compilati dadxpr_builder/templates/.dxpr_global.js: helper condivisi e integrazione CKEditor 5.dxpr_events.jsdxpr_param_types.js: inserisce un oggetto per tipo di input inwindow.dxprBuilder.dxpr_param_types.dxpr_elements.js: crea l’arraywindow.dxprBuilder.dxpr_elementse inserisce una definizione per elemento.dxpr_builder.js: l’editor. Quando questo file è eseguito chiamacreate_dxpr_elements(), che cicla suwindow.dxprBuilder.dxpr_elementse per ogni definizione:- chiama
register_animated_element(base, is_container, Class), così la classe estendeAnimatedElement(scheda Style, scheda Animation, HTML ID, HTML classes e parametri di posizionamento); - accoda i parametri ereditati ai
paramsdella definizione; - converte ogni parametro tramite
make_param_type(), che confrontaparam.typecon i tipi di parametro registrati; - mescola le proprietà della definizione nel prototipo della classe.
- chiama
Una definizione deve quindi stare sull’array dopo che
dxpr_elements.js è girato e prima che dxpr_builder.js giri. Tutti
e sei i file si caricano con l’attributo defer, quindi l’ordine dei
tag script nel documento è l’ordine di esecuzione.
La definizione di elemento
Questo è l’elemento Alert da dxpr_builder/dxpr_elements.js
(sorgente: dxpr_builder/build/dxpr-elements/elements/az_alert.js),
ridotto alle proprietà necessarie a ogni elemento. L’originale imposta anche
el_class, un handler onCancel e un 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"));
},
});
| Proprietà | Scopo |
|---|---|
base |
Nome macchina. È scritto nell’HTML salvato come data-azb="az_alert" ed è usato per trovare la classe quando la pagina è analizzata di nuovo. Mantieni il prefisso az_. |
name, nameEn |
Etichetta nel selettore di elementi e sua forma non tradotta. |
icon |
Classi CSS per l’icona del selettore. Le icone incluse sono definite in dxpr_builder/sass/dxpr-builder-backend/components/_custom-icons.scss; un elemento personalizzato richiede il proprio CSS per la sua classe icona. |
category |
Scheda del selettore. Gli elementi di layout usano Drupal.t("Layout"); blocchi e viste usano "CMS". Omettila per la scheda di contenuto predefinita. |
is_container |
true quando l’elemento contiene altri elementi. |
largeSettingsWindow |
Apre la finestra delle impostazioni nella dimensione maggiore. |
hidden |
Nasconde l’elemento dal selettore mantenendolo renderizzabile. |
params |
Impostazioni mostrate nella finestra. Vedi sotto. |
show_settings_on_create |
Apre la finestra delle impostazioni appena l’elemento è rilasciato. |
has_content |
L’elemento ha un’area di contenuto modificabile (dom_content_element). |
render(...args) |
Costruisce this.dom_element da this.attrs, poi chiama il render base. |
save_history() |
Inserisce una voce di annullamento con un’etichetta. |
parse_attrs_from_dom(element) |
Opzionale. Rilegge i valori dei parametri dal markup salvato, usato insieme a skip_data_azb e skip_params da elementi come Image che memorizzano i valori negli attributi <img> invece che in data-azat-*. |
Parametri
Ogni voce in params ha:
| Chiave | Significato |
|---|---|
type |
Uno dei tipi di parametro registrati (sezione successiva). |
heading |
Etichetta del campo. |
param_name |
Chiave in this.attrs e, nell’HTML salvato, l’attributo data-azat-<param_name>. content è speciale: è il corpo dell’elemento, non un attributo. |
value |
Valore predefinito. Per dropdown è un oggetto di opzioni con callback getText, getValue e getDefault. |
description |
Testo di aiuto sotto il campo. |
tab |
Raggruppa il campo in un accordion con nome, ad esempio Drupal.t("SEO"). |
can_be_empty |
Memorizza una stringa vuota invece di rimuovere l’attributo. |
safe |
Salta la codifica URL del valore memorizzato. |
I tipi di parametro sono i valori type inseriti in
window.dxprBuilder.dxpr_param_types in
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 e video. Un tipo non registrato ripiega a un
semplice input di testo (BaseParamType).
Non riutilizzare un param_name ereditato da ogni elemento, come
color, background, el_class, hash o i nomi di
animazione an_*. La scheda Style possiede già color, quindi un secondo
parametro con quel nome non è mai scritto in data-azat-color.
Cosa viene salvato
update_data() in dxpr_builder.js scrive l’elemento in HTML:
data-azb="<base>"sull’elemento root;data-azat-<param_name>="<value>"per ogni parametro il cui valore differisce dal predefinito, codificato URL a meno che il parametro impostisafe: true;- i parametri della scheda Style come
styleinline e classi, mai come attributidata-azat-*; data-azcnt="true"sull’elemento di contenuto quandohas_contentè impostato.
I visitatori senza editor ricevono questo HTML senza i suoi
attributi data-az*: DxprBuilderService::parseDocumentForCleanup()
li rimuove, tranne un elenco fisso mantenuto sugli elementi animati e
sugli elementi dinamici integrati come Carousel. Se l’elemento
richiede JavaScript o CSS per i visitatori, metti un
attributo data-dxpr-builder-libraries="<key>" sulla sua root:
parseDocumentForTemplateLibrary() collega
dxpr_builder/elements.<key> per ogni chiave senza slash. Le
chiavi sono le librerie elements.* in dxpr_builder.libraries.yml;
una chiave con slash è onorata solo quando è la library di un
set di icone registrato.
Esempio minimo funzionante
L’esempio aggiunge un elemento "Notice" che renderizza un paragrafo con un
colore scelto. Costruisce il suo DOM direttamente perché i modelli twig.js
compilati in dxpr_templates.js fanno parte del bundle dell’editor e
non possono essere estesi da un altro modulo.
-
Crea
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")); }, }); -
Inserisci il file nella libreria dell’editor tra
dxpr_elements.js(peso-4) edxpr_builder.js(peso-3) inmymodule.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: FALSEedefercorrispondono alle voci che il modulo definisce per i suoi file, così il file mantiene il suo posto nella sequenza sia che gli asset dell’editor vengano dalla CDN o da una build locale. -
Svuota la cache e apri una pagina builder:
drush cr -
Aggiungi l’elemento dal selettore, impostane testo e colore, e salva. Il campo memorizza:
<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>Un visitatore riceve lo stesso markup senza gli attributi
data-az*. Il paragrafo mantiene il suo colore inline, quindi nessuna libreria per visitatori serve per questo elemento.
Limiti da conoscere
- I profili non elencano elementi personalizzati. La checklist degli elementi
in un profilo builder viene da un elenco fisso in
src/Form/DxprBuilderProfileForm.phpesrc/Service/Handler/ProfileHandler.php. Gli elementi fuori da quell’elenco non sono mai nascosti da un profilo. - Le icone per il selettore richiedono CSS dal tuo modulo; le
classi
az-custom-iconincluse nel builder coprono solo gli elementi inclusi. DxprBuilderService::getDxprElementsFolders()e il suohook_dxpr_builder_elements_folders_alter()restituiscono un elenco di cartelleelementsnei temi, ma niente nell’editor legge quell’elenco. Non è una route di registrazione.- Le schede Style e Animation sono aggiunte per te da
register_animated_element(); non ridefinire quei parametri.
Prossimi passi
- Riferimento API hook per gli hook PHP che aggiungono classi di utilità e set di icone.
- Architettura per come l’editor e il formatter di campo stanno insieme.