Dorui est une librarie JavaScript qui propose une meilleure alternative pour créer des éléments DOM.
Elle est grandement inspirée d'UI-js, optimisée pour des interfaces plus complexes avec des éléments s'affichant de façon conditionnelle, avec des objets plus propres pour les éléments avec attributs, et du code plus joli utilisant des fonctions nommées après les éléments au lieu de se reposer sur type.
Le nom de la librairie fait référence à mon nom d'utilisateur, pour que vous vous rappeliez de moi.
Import
You know how this goes:
importArticle({
type: 'script',
article: 'u:dev:MediaWiki:Dorui.js'
});
mw.hook('doru.ui').add(function(ui) {
// Votre code ici
// `ui` est un alias de `window.dev.dorui`
// Il est préférable de garder une référence à `ui`, pour faciliter la création d'éléments
// Vous trouverez plus d'informations dans la section d'exemples.
});
Différences avec UI-js
Étant donné que Dorui est dérivé de UI-js, un bon début est de préciser en quoi il diffère de l'original.
Ajouts
- Il n'y a plus de propriété
typedans l'objet passé à la fonction constructeur. Avec Dorui, vous appelez des fonctions nommées d'après les éléments à créer :
// UI-js
var div = dev.ui({
type: 'div'
});
var span = dev.ui({
type: 'span',
text: 'Hello, world!'
});
// Dorui
var div = ui.div();
var span = ui.span({
text: 'Hello, world!'
});
- Pour les cas (très) rares où il n'y a pas encore d'alias pour l'élément, vous pouvez demander à ce qu'il soit rajouté. En attendant, utilisez le premier paramètre de la fonction de base. Il s'agit de l'unique et très rare cas où vous allez utiliser la fonction exportée directement.
var marquee = ui('marquee', {
text: 'I am classified as a carcinogenic'
});
- Les attributs peuvent maintenant être assignés directement dans l'objet passé aux constructeurs, cela permet d'éviter d'avoir un sous-objet
attrquand vous devez, par exemple, seulement avoir unidsur votre élément.
// UI-js
var div = dev.ui({
type: 'div',
attr: {
id: 'container'
}
});
// Dorui
var div = ui.div({
id: 'container'
});
- Pour les cas où vous devez utiliser un nom d'attribut réservé (par exemple,
text), vous pouvez toujours utiliser la méthode d'UI-js, bien queattrait été renommé enattrspour des raisons d'homogénéité.
- Pour les cas où vous devez utiliser un nom d'attribut réservé (par exemple,
var div = ui.div({
attrs: {
id: 'container',
text: 'boohoo'
}
});
- Il y a désormais une propriété
childpour quand un élément n'a qu'un seul enfant. Cela permet d'avoir un arbre moins profond quand vos éléments n'ont besoin d'avoir qu'un seul enfant chacun.
// UI-js
var div = dev.ui({
type: 'div',
children: [
{
type: 'span',
text: 'I am a child'
}
]
});
// Dorui
var div = ui.div({
child: ui.span({
text: 'I am a child'
})
});
- Comme vous pouvez le constater dans l'exemple ci-dessus, les enfants ne sont plus des objets, mais des nœuds eux-mêmes. Dans ce cas, ils sont ce qui est retourné par les fonctions
ui.balise(). childne permet pas d'utiliser des chaînes de caractères, contrairement àchildren. Cela est dû au fait que la propriététextpermet de gérer ce cas.- Vous ne devriez pas utiliser
childetchildrenen même temps. Ils seront simplement ajoutés dans l'ordre dans lequel ils sont déclarés, mais c'est un peu idiot.
- Comme vous pouvez le constater dans l'exemple ci-dessus, les enfants ne sont plus des objets, mais des nœuds eux-mêmes. Dans ce cas, ils sont ce qui est retourné par les fonctions
stylesupporte désormais des propriétés CSS customisées à ajouter.
var div = ui.div({
style: {
// Vous pouvez utiliser du camelCase ou du dashed-case
backgroundColor: 'var(--custom-color)',
'--custom-color': '#0ff'
}
});
classespermet désormais de passer un objet pour des classes conditionnelles. Il s'agit d'une fonctionnalité supplémentaire et les tableaux sont toujours supportés.
var button = ui.button({
classes: {
'wds-button': true,
'wds-is-disbled': buttonData.disabled
},
props: {
disabled: buttonData.disabled
},
text: buttonData.text
});
Différences
attra été renommé enattrspour des raisons d'homogénéité vis-à-vis depropsetclasses, puisque ils vous laissent ajouter plusieurs classes ou propriétés à la fois.- Les propriétés
childetchildrens'attendent à recevoir des nœuds déjà créés, contrairement à comment UI-js décrivait l'arbre complet avec des simples objets.- Ce choix a été fait car il permet l'utilisation des abréviations
ui.balise(), et d'améliorer le court-circuitage conditionnel.
- Ce choix a été fait car il permet l'utilisation des abréviations
- Les éléments conditionnels ont été changés afin d'utiliser le court-circuitage avec
&&. En effet, les éléments qui doivent être affichés de manière conditionnelle ne doivent être calculés que s'ils existent, et leconditiond'UI-js ne le permettait pas.
// UI-js
var div = dev.ui({
type: 'div',
children: [
{
type: 'span',
text: 'Stop! You violated the law!',
condition: shouldShowBanner
}
]
});
// Dorui
var div = ui.div({
children: [
shouldShowBanner && ui.span({
text: 'Stop! You violated the law!'
})
]
// Cela fonctionne aussi avec `child`:
// child: shouldShowBanner && ui.span({
// text: 'Stop! You violated the law!'
// })
});
- Cela permet d'éviter de nombreuses répétitions de code lorsque vous avez également besoin des données utilisées dans la condition, dans l'élément que vous créez.
// UI-js
var div = dev.ui({
type: 'div',
children: [
{
type: 'span',
text: banner && banner.message,
condition: banner && banner.message
}
]
});
// Dorui
var div = ui.div({
child: banner && banner.message && ui.span({
// Vous êtes certain que `banner` et `banner.message` sont truthy.
// Vous pouvez donc vous passer de la vérification ici
text: banner.message
})
});
- Les valeurs falsy sont formellement ignorées dans
childetchildren.
- Les valeurs falsy sont formellement ignorées dans
- Dorui supporte une multitude de balises svg de plus que UI-js, et a quelques mappings d'espace de noms d'attributs SVG de plus que UI-js. Cependant, cela n'est pas suffisant pour dire que Dorui est meilleur sur ce front, les deux librairies ont été utilisées pour recréer chaque élément SVG dans un document Fandom normal avec succès.
- Une autre raison de ne pas choisir Dorui plutôt qu'UI-js sont les performances. Dorui est environ 2 fois plus rapide lorsque vous l'utilisez uniquement pour créer des éléments vides, mais cet écart se réduit lorsque vous commencez à faire des choses avec ceux-ci, comme ajouter des attributs ou des écouteurs d'événements. Avec des chargements complexes, il n'est qu'environ 20% plus rapide, et cela est annulé par le fait que, après minification, Dorui est plus gros qu'UI-js (~2kb contre ~4kb).
Suppressions
- La propriété
typea été complètement supprimée, puisqu'il s'agit désormais du premier paramètre passé àui, et les utilisateurs sont encouragés à utiliser les alias avec le nom des balises. conditiona été supprimé, et à la place les valeurs falsy sont ignorées danschildetchildren.parenta été supprimé. Il était ambigu dans ce qu'il faisait et a changé son comportement au fil du temps. Au début, il clonait le nœud pour chaque élément correspondant trouvé dans le document. Une fois que cloner des nœuds est devenu problématique, cela a été remplacé par le comportement actuel, où il ajoute le même élément à chaque élément correspondant, ce qui signifie que le dernier élément l'obtient. Ce comportement n'est pas documenté et est bizarre, et il semblerait logique que l'élément soit ajouté au premier élément correspondant.- Solution : Utiliser
appendChildou n'importe qu'elle autre méthode pour ajouter les éléments dans le DOM.
- Solution : Utiliser
// Avec JQuery
$('#mw-content-text').append(ui.div());
// Avec JavaScript vanilla
document.querySelector('#mw-content-text').appendChild(
ui.div()
);
// Avec des null checks
var parent = document.querySelector('#mw-content-text');
if (parent !== null) {
parent.appendChild(
ui.div()
);
}
// Ajouter en premier
var parent = document.getElementById('mw-content-text');
parent.insertBefore(
ui.div(),
parent.firstChild
);
selecteda été supprimé. La raison est logique pour quiconque a essayé de l'utiliser : Cela ne marche pas. Parce queselectedassigne la valeur à la propriétéselectedIndex, qui dépend de combien d'enfant l'élément possède. Toutefois, cette étape est faite avant l'ajout des enfants, donc cela ne met jamais la propriété à jour correctement.- Solution : Utiliser
propsavecselectedIndex! Cela marchera tant que vous vous souviendrez d'avoir vospropsaprèschildren.
- Solution : Utiliser
var select = ui.select({
children: [
ui.option({ text: 'Option 1' }),
ui.option({ text: 'Option 2' }),
],
// Rappel: avoir `props` APRÈS `children`
props: {
// Par défaut, 'Option 2' est sélectionné
selectedIndex: 1
}
});
checkeda été supprimé. Il n'y a pas de réelle raison ici, vous pouvez juste faire la même chose avecprops.checked:
var checkbox = ui.input({
type: 'checkbox',
props: {
checked: true
}
});
dataa été supprimé. Il s'agit d'un mapping vers les attributsdata-, que vous pouvez faire en utilisantattrs. Cela a été supprimé car cela pouvait être confondu avec la propriété HTML5dataset, ce qui n'est pas souvent ce que vous souhaitez.- Solution : Utiliser simplement
data-.
- Solution : Utiliser simplement
var chatEntry = ui.li({
attrs: {
'data-name': username
},
text: content
});
- Passer
undefinedou#document-fragmentne créé plus un document fragment. Si vous avez besoin d'en créer un avec cette librairie, Par exemple, pour regrouper un groupe de nœuds dans un parent pour une utilisation conditionnelle, vous pouvez utiliser la fonctionui.frag(children). Elle prend un tableau de nœuds, tout comme la propriétéchildren. - De la même façon,
#textne créé plus un nœud textuel. Il s'agit simplement d'un détail d'implémentation non documenté, vous ne devez donc pas vous en préoccuper. Pour créer des nœuds textuels à l'aide de Dorui, vous pouvez utilisertext, ou passer une chaîne de caractères à l'un des éléments dans le tableauchildren.
Documentation
Dorui exporte une unique fonction, ui(tag, options), which que nous appellerons ui factory. Elle prend deux arguments.
- tag
- C'est une chaîne de caractères qui représente le nom de la balise HTML que vous voulez créer. Par exemple,
div. Cette propriété doit être obligatoirement passée et ne doit pas être une chaîne de caractères vide. - options
- C'est un objet qui représente les options qui vont configurer l'élément qui va être créé. Nous appelons cet objet Options, et il possède certaines propriétés qui ont une signification particulière. Toute propriété non reconnue sera mise en argument. Cet objet ne doit pas être
undefined, ou quoi que ce soit qui ne soit pas un simple objet.
Heureusement, les utilisateurs ont rarement besoin d'utiliser la fonction factory directement, car elle est un peu bizarre à utiliser et vous devez toujours passer des options même si vous voulez un élément vierge. Au lieu de cela, ils utilisent des fonctions alias qui leur permettent de construire plus facilement des éléments communs.
Fonctions alias
Il y a plusieurs fonctions qui sont des alias de l'ui factory, mais liés à un nom de balise. Par exemple, ui.div(options). Appeler cette fonction directement est l'équivalent d'appeler ui('div', options).
Il y a encore une chose qui les rend encore plus pratique à utiliser, et c'est la gestion automatique de l'objet options si vous ne le mettez pas car elles sont moins strictes que la factory. Il est donc tout à fait possible d'utiliser ui.br() pour créer un retour à la ligne sans attributs ou enfants.
Voici une liste d'alias de balises HTML :
ui.a()ui.abbr()ui.address()ui.area()ui.article()ui.aside()ui.audio()ui.b()ui.bdi()ui.bdo()ui.blockquote()ui.body()ui.br()ui.button()ui.canvas()ui.caption()ui.cite()ui.code()ui.col()ui.colgroup()ui.data()ui.datalist()ui.dd()ui.del()ui.details()ui.dfn()ui.dialog()ui.div()ui.dl()ui.dt()ui.em()ui.embed()ui.fieldset()ui.figcaption()ui.figure()ui.footer()ui.form()ui.h1()ui.h2()ui.h3()ui.h4()ui.h5()ui.h6()ui.head()ui.header()ui.hr()ui.html()ui.i()ui.iframe()ui.img()ui.input()ui.ins()ui.kbd()ui.label()ui.legend()ui.li()ui.link()ui.main()ui.map()ui.mark()ui.meta()ui.meter()ui.nav()ui.noscript()ui.object()ui.ol()ui.optgroup()ui.option()ui.output()ui.p()ui.param()ui.picture()ui.pre()ui.progress()ui.q()ui.s()ui.samp()ui.script()ui.section()ui.select()ui.small()ui.source()ui.span()ui.strong()ui.style()ui.sub()ui.summary()ui.sup()ui.table()ui.tbody()ui.td()ui.textarea()ui.tfoot()ui.th()ui.thead()ui.time()ui.title()ui.tr()ui.track()ui.u()ui.ul()ui.video()
Et les balises SVG enregistrées qui ont une sémantique SVG spéciale :
ui.animate()ui.animation()ui.circle()ui.clipPath()ui.defs()ui.desc()ui.ellipse()ui.feColorMatrix()ui.feGaussianBlur()ui.feOffset()ui.filter()ui.foreignObject()ui.g()ui.geometry()ui.image()ui.line()ui.linearGradient()ui.mask()ui.path()ui.polygon()ui.rect()ui.stop()ui.svg()ui.symbol()ui.text()ui.use()
L'ensemble des balises SVG prises en charge devrait s'étoffer à l'avenir.
L'objet Options
C'est le nerf de la guerre de la création d'éléments, sans laquelle la bibliothèque n'est qu'un appel à document.createElement glorifié.
Comment fonctionne-t-il ? Chaque propriété de l'objet est une paire composée d'une clé et d'une valeur. La clé est ce que le script interprétera comme ayant une signification particulière ou comme étant utilisé en tant qu'attribut. La valeur détermine ce qui est fait exactement.
Lorsque la clé n'est pas reconnue comme ayant une signification particulière, on suppose que la clé est un nom d'attribut et que la valeur est la valeur de l'attribut. La valeur sera simplement convertie en chaîne de caractères, donc un objet deviendra attribute="[object Object]" et une valeur booléenne comme false deviendra attribute="false".
Il y a un autre comportement de l'objet options que vous devez connaître, c'est que leurs effets se produisent dans l'ordre dans lequel ils sont déclarés dans l'objet. Vous avez pu l'entrapercevoir dans la section sur les suppressions par rapport à UI-js, où l'ordre de children et props.selectedIndex avait un impact pour la sélection de la valeur par défaut. La plupart du temps, cela ne changera pas grand chose, mais cela a vraiment de l'importance lors de la définition de comportements avec child, children, et text en simultané. Vous devriez seulement utiliser children au lieu de mélanger les trois pour des raisons de clarté, mais cela montre un des cas aux limites.
Voici la liste des clés qui ont une signification particulière :
- attrs
- Il doit s'agir d'un objet simple qui représente les valeurs qui seront attribuées à l'élément. Il s'agit d'une échappatoire aux clés à signification particulière, au cas où vous auriez besoin de définir un attribut avec le nom
childoueventspour une raison ou une autre. - Toutefois ce n'est pas seulement une échappatoire, elle gère également les valeurs booléennes de façon spéciale. Au lieu d'être converties en chaîne de caractères comme les comportement par défauts, elles peuvent être utilisées comme des attributs conditionnels. Par exemple, si vous passez
checked: false, l’élément n'aura pas attribut checked du tout. Cependant, si vous passezchecked: true, il aurachecked="checked". - Il s'agit seulement d'un exemple, pour l'attribut checked, vous devriez utiliser
props, qui est la meilleure façon de gérer les valeurs d'input. - child
- Il doit s'agir d'un nœud, tel un nœud textuel (bien que dans ce cas vous utiliseriez
text), un document fragment (bien que dans ce cas vous utiliseriezchildren), ou un élément. En fait, utilisez seulement un élément. Vous ne devriez utiliser cette clé que lorsque vous n'avez pas besoin de plusieurs enfants et que le seul enfant est un élément et non du texte. Si une valeur falsy est passée (ex.0, false, null, undefined, NaN), elle sera ignorée. - children
- Il doit s'agir d'un tableau de nœuds ou de chaînes de caractères. Ils seront ajoutés dans l'ordre au parent. Les chaînes seront converties en nœuds textuels. Si une valeur falsy est trouvée dans le tableau, elle sera ignorée.
- text
- Il doit s'agir d'une chaîne de caractères et ajoute un nœud textuel à l'élément.
- html
- Il doit s'agir d'une chaîne de caractères. Il remplace complètement le contenu de l'élément par le code HTML donné. N'utilisez cette fonction que si vous devez absolument gérer de l'HTML externe au lieu de créer des nœuds vous-même.
- classes
- Il peut s'agir d'un tableau de chaînes ou d'un simple objet. S'il s'agit d'un tableau, il affecte ces classes à l'élément. S'il s'agit d'un objet, ses clés sont utilisées comme noms de classe, et la valeur détermine si la classe est ajoutée à l'élément ou non. Vous pouvez imaginer ce fonctionnement comme des classes conditionnelles, de la même façon que
attrspeut avoir des attributs conditionnels. - events
- Il doit s'agir d'un simple objet. Ses clés sont utilisées comme noms d'événements, et les valeurs doivent être des fonctions qui seront des callbacks passés à
addEventListener. - style
- Il doit s'agir d'un simple objet. Ses clés sont utilisées comme noms de propriétés CSS et ses valeurs comme... des valeurs. Vous pouvez utiliser des noms de propriétés en camelCase (par exemple,
backgroundColor,borderTopRightRadius,WebkitTransform) ou en dashed-case. Les variables CSS sont aussi supportées. - props
- Il doit s'agir d'un simple objet. Les propriétés personnalisées seront assignées directement à l'élément une fois créé.
Document fragments
Une fonction utilitaire supplémentaire est fournie pour créer des document fragments, ui.frag().
Il prend un seul argument, qui est un tableau d'enfants. Comme dans l'objet options, ce tableau peut contenir des nœuds normaux ou des chaînes qui seront converties en nœuds textuels.
Exemples
Avant de voir des exemples d'utilisation plus simples, nous allons nous attaquer au problème beaucoup plus compliqué de la structure des scripts.
Même si vous n'utilisez pas certaines méthodes, il est utile d'établir un contexte dans lequel les autres exemples pourraient se trouver et comment ils s'exécuteraient.
Structure générale
L'ajout de dépendances aux scripts en général nécessite une certaine réflexion sur la façon dont vous allez structurer votre programme pour qu'il reste ordonné
En général, le plus simple est le mieux, donc si vous n'avez besoin que d'une ou de quelques dépendances, une structure comme la suivante peut convenir à votre script.
(function() {
var ui;
function init(lib) {
ui = lib;
$('#my-tools-menu').append(
ui.li({
text: 'My script'
})
);
}
importArticle({
type: 'script',
article: 'u:dev:MediaWiki:Dorui.js'
});
mw.hook('doru.ui').add(init);
})();
C'est bien fait, et c'est la norme pour les scripts sur le Dev Wiki. Cependant, si vous voulez un exemple de code plus tendancieux pour un script qui pourrait avoir besoin d'une gestion des dépendances plus complexe, n'hésitez pas à jeter un coup d'œil à l'exemple suivant.
(function() {
// Double exécutions
if (window.MyScript && MyScript.loaded) return;
var ui;
window.MyScript = {
loaded: true,
// Liste des dépendances
loading: [
'dorui',
'i18n-js',
'i18n'
],
// Callback pour chaque dépendance chargée
onload: function(key, arg) {
switch (key) {
case 'i18n-js':
arg.loadMessages('MyScript').then(this.onload.bind(this, 'i18n'));
break;
case 'i18n':
this.i18n = arg;
break;
case 'dorui':
ui = arg;
break;
}
var index = this.loading.indexOf(key);
if (index === -1) throw new Error('Unregistered dependency loaded: ' + key);
this.loading.splice(index, 1);
if (this.loading.length !== 0) return;
this.init();
},
// Import des dépendances et lien à leurs hooks
preload: function() {
importArticles({
type: 'script',
articles: [
'u:dev:MediaWiki:Dorui.js',
'u:dev:MediaWiki:I18n-js/code.js'
]
});
mw.hook('dev.i18n').add(this.onload.bind(this, 'i18n-js'));
mw.hook('doru.ui').add(this.onload.bind(this, 'dorui'));
},
// Fonction qui sera appelée quand toutes les dépendances auront été chargées
init: function() {
var menu = document.getElementById('my-tools-menu');
if (menu === null) return;
menu.appendChild(
ui.li({
text: this.i18n.msg('tools-menu-label').plain()
})
);
}
};
MyScript.preload();
})();
Bien sûr, c'est beaucoup plus complexe, mais cela permet de gérer un arbre de dépendance plus compliqué. C'est à vous de voir si le coût de cette complexité en vaut la peine ou non, ou si vous pouvez adapter certaines parties du code ci-dessus pour vous-même.
Créer des éléments simples
Pour la suite, nous allons assumer que vous avez la structure appropriée dans votre code et que la variable ui réfère à la fonction factory.
Vous devriez maintenant avoir une bonne idée de la façon dont fonctionne la création d'éléments. Ces exemples ne devraient donc pas vous paraître étranges, mais ils pourraient vous permettre de vous habituer à quoi ça ressemble,et à leur fonctionnement.
var span = ui.span({
class: 'my-span-element',
text: 'Howdy'
});
var div = ui.div({
id: 'my-wrapper',
child: span
});
var container = ui.div({
id: 'my-container',
style: {
display: 'flex'
},
children: [
div,
ui.div({
text: 'Badonk'
})
]
});
Gérer les éléments d'input
Les éléments d'input font partie des plus compliqués en HTML, aux vues de leur diversité.
Heureusement, props vous permet de traiter les aspects les plus problématiques, telles que les différentes manières de définir les valeurs par défaut, etc.
// Équivalent à <input type="text" value="hello">
// Rappelez vous que type="text" est la valeur implicite du navigateur si omise
ui.input({
type: 'text',
props: {
value: 'hello'
}
});
// Équivalent à <textarea>hello</textarea>
// Oh mais dis donc, on peut utiliser la même méthode pour définir la valeur par défaut !
ui.textarea({
props: {
value: 'hello'
}
});
// Équivalent à <input type="checkbox" checked="checked">
// L'attribut n'est jamais réellement défini, car la propriété checked est définie avec JS
// Mais la checkbox sera cochée
ui.input({
type: 'checkbox',
props: {
checked: true
}
});
Faire des boutons WDS
C'est une bonne chose de pouvoir créer des éléments, mais ils se démarqueront toujours en quelque sorte si vous ne les stylisez pas comme le reste du site.
Pour créer un bouton qui ressemble au bouton d'édition en haut de cette page, nous aurons besoin de WDSIcons, nous supposerons donc que vous l'avez importé.
var button = ui.button({
class: 'wds-button',
children: [
dev.wds.icon('pencil-small'),
ui.span({
text: 'Edit'
})
]
});
Qu'est-ce qu'il y a ? Vous voulez aussi le menu déroulant ? Eh bien, qu'est-ce que vous êtes difficile, d'accord, voilà :
var buttonGroup = ui.div({
class: 'wds-button-group',
children: [
ui.button({
class: 'wds-button',
children: [
dev.wds.icon('pencil-small'),
ui.span({
text: 'Edit'
})
]
}),
ui.div({
class: 'wds-dropdown',
children: [
ui.div({
classes: ['wds-button', 'wds-dropdown__toggle'],
child: dev.wds.icon('dropdown-tiny')
}),
ui.div({
classes: ['wds-dropdown__content', 'wds-is-not-scrollable', 'wds-is-right-aligned'],
child: ui.ul({
classes: ['wds-list', 'wds-is-linked'],
children: [
ui.li({
child: ui.a({
text: 'Ha-ha'
})
})
]
})
})
]
})
]
});
Extraire des fonctions
Mais le code ci-dessus est super compliqué à réutiliser partout. Et si nous pouvions avoir un objet plus simple contenant uniquement les données pertinentes, et générer un élément à partir de celui-ci ? Comme ceci :
buildWDSButton({
text: 'Click me',
dropdown: [
{
text: 'Choice 1',
href: '/wiki/User:Dorumin'
},
{
text: 'Choice 2',
href: mw.util.getUrl('User:Sophiedp')
}
]
});
Vous pouvez facilement extraire la création d'éléments dans des fonctions, en utilisant des objets et des tableaux comme entrées. En fait, c'est encouragé, de sorte que vous pouvez garder votre interface utilisateur facile à comprendre sous la forme de petites fonctions, comme ceci :
function buildDropdownItem(data) {
return ui.li({
child: ui.a({
href: data.href || '#',
text: data.text
})
});
}
function buildDropdown(children) {
return ui.div({
class: 'wds-dropdown',
children: [
ui.div({
classes: ['wds-button', 'wds-dropdown__toggle'],
child: dev.wds.icon('dropdown-tiny')
}),
ui.div({
classes: ['wds-dropdown__content', 'wds-is-not-scrollable', 'wds-is-right-aligned'],
child: ui.ul({
classes: ['wds-list', 'wds-is-linked'],
children: children.map(buildDropdownItem)
})
})
]
});
}
function buildWDSButton(data) {
return ui.div({
class: 'wds-button-group',
children: [
ui.button({
class: 'wds-button',
children: [
dev.wds.icon('pencil-small'),
ui.span({
text: data.text
})
]
}),
data.dropdown && buildDropdown(data.dropdown)
]
});
}
N'est-ce pas plus facile à comprendre ?
Utiliser des modales
Pour afficher des modales avec ShowCustomModal, vous pouvez utiliser un code comme celui-ci :
mw.hook('dev.showCustomModal').add(function() {
dev.showCustomModal('My modal', {
id: 'MyModal',
content: ui.ul({
children: [
ui.li({ text: 'Your pastimes consisted of the strange' }),
ui.li({ text: 'And twisted and deranged' }),
ui.li({ text: 'And I hate that little game you had called' }),
ui.li({ text: 'Crying Lightning' }),
]
})
});
});
Utiliser des fragments
Fragments sont une fonctionnalité très spécifique qui pourraient selon certains ne pas avoir sa place dans cette librairie.
Tout d'abord, vous avez raison. Mais ils sont un moyen très pratique de regrouper facilement des enfants !
Normalement, avec Dorui, vous pouvez déjà le faire avec children, mais les fragments vous permettent de le faire même à l'intérieur de ce tableau.
Cela s'avère utile pour choisir d'inclure un ou plusieurs éléments en fonction d'une condition, sans avoir de conteneur :
var shouldRepeat = true;
var lyrics = ui.ul({
children: [
// vs. SAYU, No Straight Roads soundtrack
ui.li({ text: 'One, two, three, four' }),
ui.li({ text: 'Motion on the ocean floor!' }),
ui.li({ text: 'Five, six, seven, eight' }),
ui.li({ text: 'Double bubble, swim some more!' }),
shouldRepeat && ui.frag([
ui.li({ text: 'One, two, three, four' }),
ui.li({ text: 'Motion on the ocean floor!' }),
])
]
});
Ils sont également utiles pour passer dans des fonctions qui attendent un seul nœud. Par exemple, si vous voulez afficher une modale avec plusieurs enfants, mais que vous ne voulez pas ajouter de conteneur, vous pouvez utiliser les fragments !
Revisitons l'exemple des modales et changeons le pour utiliser des fragments, et lister les éléments en paragraphes:
mw.hook('dev.showCustomModal').add(function() {
dev.showCustomModal('My modal', {
id: 'MyModal',
content: ui.frag([
ui.p({ text: 'Your pastimes consisted of the strange' }),
ui.p({ text: 'And twisted and deranged' }),
ui.p({ text: 'And I hate that little game you had called' }),
ui.p({ text: 'Crying Lightning' }),
])
});
});
Cela permet de se débarrasser d'un niveau d'indentation et d'un élément enveloppant inutile. Nous espérons que les fragments vous seront utiles, ne serait-ce que quelques fois.
Portage depuis UI-js
Le portage des scripts d'UI-js vers Dorui n'est généralement pas nécessaire, à moins que vous ne continuiez à travailler dessus et que vous pensiez que Dorui sera plus agréable à utiliser à long terme.
Quelques exemples de scripts qui ont été portés depuis UI-js vers Dorui peuvent être trouvés ici et ici.
Portage depuis HTML
Si vous avez un morceau d'HTML que vous voulez transformer en Dorui, vous n'avez pas besoin d'effectuer la transformation vous-même. Vous pouvez utiliser cet outil pour le convertir en arbre Dorui.