From 0fe0b9f681d0da79b313e0907933665930074704 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Sat, 14 Sep 2024 15:40:07 +0200 Subject: [PATCH] Documentation: add article about Javelin DOM stuff Summary: Finally we know something about: - how to get an element by id ($) - how to find some children by a parent (scry) - how to find an exact child by a parent (find) - how to find a parent by a child (findAbove) Closes T15870 Test Plan: You read this article and you find something interesting and probably also accurate. Reviewers: O1 Blessed Committers, aklapper Reviewed By: O1 Blessed Committers, aklapper Subscribers: aklapper, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15870 Differential Revision: https://we.phorge.it/D25822 --- .../javelin/docs/concepts/behaviors.diviner | 4 +- .../rsrc/externals/javelin/docs/javelin.book | 5 +- .../javelin/docs/javelin_intro.diviner | 139 ++++++++++++++++++ 3 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 webroot/rsrc/externals/javelin/docs/javelin_intro.diviner diff --git a/webroot/rsrc/externals/javelin/docs/concepts/behaviors.diviner b/webroot/rsrc/externals/javelin/docs/concepts/behaviors.diviner index f3cea9cda6..09b8c8a085 100644 --- a/webroot/rsrc/externals/javelin/docs/concepts/behaviors.diviner +++ b/webroot/rsrc/externals/javelin/docs/concepts/behaviors.diviner @@ -84,7 +84,7 @@ which you access with @{function:JX.initBehavior}. Another way to think about them is that you are defining methods which represent the entirety of the API exposed by the document. The recommended approach to -glue code is that the server interact with Javascript on the client //only// by +glue code is that the server interact with JavaScript on the client //only// by invoking behaviors, so the set of available behaviors represent the complete set of legal interactions available to the server. @@ -152,7 +152,7 @@ now you have a bunch of classes which only really have glue code in them. Javelin behaviors provide a more structured solution to some of these problems: - - All your Javascript code is in Javascript files, not embedded in strings in + - All your JavaScript code is in JavaScript files, not embedded in strings in in some host language on the server side. - You can use static analysis and minification tools normally. - Provided you use a reasonable server-side library, you can't get escaping diff --git a/webroot/rsrc/externals/javelin/docs/javelin.book b/webroot/rsrc/externals/javelin/docs/javelin.book index 7c2a0c2274..9d3147d571 100644 --- a/webroot/rsrc/externals/javelin/docs/javelin.book +++ b/webroot/rsrc/externals/javelin/docs/javelin.book @@ -2,13 +2,16 @@ "name" : "javelin", "title" : "Javelin Documentation", "short" : "Javelin Docs", - "preface" : "Documentation for developers using Javelin.", + "preface" : "Documentation for JavaScript developers using Javelin.", "uri.source": "https://we.phorge.it/diffusion/P/browse/master/%f$%l", "rules": { "(\\.diviner$)": "DivinerArticleAtomizer" }, "groups": { + "introduction": { + "name": "Introduction" + }, "concepts": { "name": "Concepts" } diff --git a/webroot/rsrc/externals/javelin/docs/javelin_intro.diviner b/webroot/rsrc/externals/javelin/docs/javelin_intro.diviner new file mode 100644 index 0000000000..e0fd0a90e6 --- /dev/null +++ b/webroot/rsrc/externals/javelin/docs/javelin_intro.diviner @@ -0,0 +1,139 @@ +@title Javelin Introduction +@group introduction + +Explore the Javelin framework to make your frontend "go brrrrr". + += Preamble = + +As you know, Phorge is the fork of Phabricator. But, you may not know +that Phabricator was designed with a particular Open Source JavaScript +library called **Javelin**. + +So, why I should master Javelin? + +The Javelin APIs are un-documented, un-intuitive, and esoteric, +and you may prefer X / Y / Z framework instead. +But hey: Javelin will //not// be abandoned anytime soon. +Give Javelin a try, so you can make Phorge even better. + +Some advantages of Javelin: + +- Javelin encourages strong separation between CSS selectors and + business logic selectors +- Javelin un-minified is more lightweight than jQuery minified +- it starts with "Jav" like "JavaScript" so it's easy + += Concepts: DOM Traversing with Sigils = + +Traversing the DOM using Javelin is simple... as long as +you know what a "sigil" is. In fact, Javelin is designed to avoid +finding something by CSS classes. Instead, Javelin introduced +"sigils" - that is, exactly like a CSS class but vegan (?). + +So, pretend you don't know what a CSS class is, and explore +this related reading about sigils, and how to store data in +elements marked with a sigil: + +@{article:Concepts: Sigils and Metadata}. + +The source code of the DOM utilities of Javelin is here: + +https://we.phorge.it/source/phorge/browse/master/webroot/rsrc/externals/javelin/lib/DOM.js + +== Find Element by ID with `$` == + +The `$` Javelin method finds exactly one HTML element by its id. Definition: + +```javascript +function X.$(id: string): Element +``` + +Example usage: + +```javascript +var elementById = JX.$('my-id'); +``` + +As you can imagine, this method is just a shorter version for the native +[[ https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById | document.getElementById() ]]. + +Please remember to write `'id'` and not `'#id'`. + +Comparison table from other frameworks: + +| | From Code | To Javelin | +|-----------------|---------------|-----------------| +| **From jQuery** | `$('#my-id')` | `JX.$('my-id')` | + +== Look Down for Multiple Elements with `scry` == + +The `scry` Javelin method looks down for multiple HTML elements by sigil. +Definition: + +```javascript +function JX.DOM.scry(parent: Element, tagName: string, sigil: string): Element[] +``` + +Example usage: + +```javascript +var elementsWithSigil = JX.DOM.scry(document.body, '*', 'my-sigil'); +``` + +The method requires a starting element to descend from and +it returns an array of elements at any child depth, that have +the specified sigil __and__ the specified tag name. Few tips: + +- if you don't want to specify a tag name, set "`*`" as tag name +- if you specify a tagname like "`a`", it may be faster + +Comparison table from other frameworks: + +| | From Code | To Javelin | +|-----------------|---------------------------------|------------------------------------------| +| **From jQuery** | `$(parent).find('.class-name')` | `JX.DOM.scry(parent, '*', 'sigil-name')` | + +== Look Down for One Element with `find` == + +The `find` Javelin method looks down for exactly one element by sigil. +Definition: + +```javascript +function JX.DOM.find(root: Element, tagName: string, sigil: string): Element +``` + +Example usage: + +```javascript +var child = JX.DOM.find(document.body, '*', 'my-sigil'); +``` + +As you can imagine, the method `find` is just a particular case of the method `scry`, +to be sure that you return exactly one element. + +Comparison table from other frameworks: + +| | From Code | To Javelin | +|-----------------|------------------------------------|------------------------------------------| +| **From jQuery** | `$(parent).find('.class-name')[0]` | `JX.DOM.find(parent, '*', 'sigil-name')` | + +== Look Up for One Element with `findAbove` == + +The `findAbove` Javelin method looks up for exactly one HMTL element by sigil. +Definition: + +```javascript +function JX.DOM.findAbove(anchor: Element, tagName: string, sigil: string): Element +``` + +Example usage: + +```javascript +var parent = JX.DOM.findAbove(child, '*', 'my-sigil'); +``` + +Comparison table from other frameworks: + +| | From Code | To Javelin | +|-----------------|---------------------------------------|-----------------------------------------------| +| **From jQuery** | `$(anchor).closest('.class-name')[0]` | `JX.DOM.findAbove(anchor, '*', 'sigil-name')` |