NoccyLabs JSL
This is a collection of libraries that make working with JavaScript and data.
Each component is available in it's own file, and example/default stylesheets are available in separate files.
Installing
For now, clone this somewhere and copy the files to your project. Hopefully Symfony Issue #53999 will be completed soon, in which case you will hopefully be able to import JSL using the AssetMapper CLI commands.
Components
date.js
Warning
WORK IN PROGRESS! MOSTLY NOT WORKING!
This component makes working with dates less of a pain.
import { date, Timestamp } from "./date.js";
// now
const now = date();
// nothing below here in this example works, to be implemented!
// tomorrow
const tomorrow = date().add({days:1});
// yesterday
const yesterday = now.sub({ days:1 });
// sometime
const custom = date("2025-09-01 15:00:42 +02:00");
// format dates, php style
let ts = now.format("Y-m-d H:i:s P");
dialog.js
This component creates dialogs on the fly, and resolves a promise when the dialog is accepted.
import { dialog } from "./dialog.js";
// show a message box
dialog.msgbox("Something");
// show a message box and do something when dismissed
dialog.msgbox("Ready!").then(
function (result) {
// do something!
}
);
// show a confirmation in an async callback
... async () => {
const result = await dialog.confirm("Are you sure about that?");
if (result === "ok") {
// do it
}
}
// show custom actions in a custom select style dialog
dialog.select("Put in warehouse", "Select", { "none":"None", "1":"WH1", "2":"WH2" }).then(...)
dialog.TYPE(body, ?title, ?actions, ?options)
→Promise
Options:
showClose
- true to show close button in top left cornerwidth
- valid CSS width definition
dom.js
This component offers dom
and el
that can be used to manipulate the DOM.
import { dom, el } from "./dom.js";
// build DOM
const myDiv = el.div({ class: "form-row" }, [
el.label({ class:"form-label", for:"myInput" }, "Label"),
el.input({ class:"form-control", id:"myInput", type:"text" })
]);
// update element attributes
dom.apply(myDiv, { style:"font-weight:bold;" });
// append children
dom.append(myDiv, [
"Some text",
el.span()
]);
json.js
This component contains tools to query and update data structures using simplified JSON paths.
import { jsonQuery, jsonPatch } from './json.js';
let model = {
name: "Bob",
info: {
age: 42
}
};
jsonQuery(model, ".name") // → "Bob"
jsonPatch(model, ".name", "Bobby"); // → { name:"Bobby", info:{ age:42 }}
let items = [
{ "name": "cheese", "price": "5.99" },
{ "name": "wine", "price": "2.99" }
];
jsonQuery(items, "[].name") // → [ "cheese", "wine" ]
jsonform.js
This component not only builds forms and allow you to map it against paths in a model dataset, but it also allows you to do inline editing of your data, with type mapping.
import { JsonForm, TextField } from "./jsonform.js";
const productForm = new JsonForm();
productForm.layout.addRow()
.append(new TextField({ label:"Product name", path:".product.name", width:70 }))
.append(new TextField({ label:"Price", path:".price" }));
myTargetEl.appendChild(productForm.dom());
productForm.model = {
product: {
name: "Swedish Fish"
},
price: "9.99"
};
// make it possible to edit the form
productForm.editable = true;
// when the user is done editing set editable = false and access the updated model
productForm.editable = false;
const newModel = productForm.model; // → { product:{ name:"Swedish Fish" }, price:"8.99" }
// You can even put a form inside a dialog!
dialog.dialog(productForm.dom(), "Title", {"ok":"Update"}, { showClose:true, width:'400px' }).then(
(result) => {
productForm.editable = false;
if (result == 'ok') {
// productForm.model is updated
}
}
)
productForm.editable = true;