{"id":22761119,"url":"https://github.com/dldevinc/data-xclass","last_synced_at":"2025-03-30T09:10:35.105Z","repository":{"id":134846919,"uuid":"611627210","full_name":"dldevinc/data-xclass","owner":"dldevinc","description":"A lightweight widget library for traditional SSR apps","archived":false,"fork":false,"pushed_at":"2024-02-05T17:08:57.000Z","size":316,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T13:43:22.381Z","etag":null,"topics":["html-attributes","ssr","widget"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dldevinc.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-03-09T08:05:03.000Z","updated_at":"2023-03-11T05:37:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"8e63528a-13ca-4a98-adaa-51b82f4723e2","html_url":"https://github.com/dldevinc/data-xclass","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dldevinc%2Fdata-xclass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dldevinc%2Fdata-xclass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dldevinc%2Fdata-xclass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dldevinc%2Fdata-xclass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dldevinc","download_url":"https://codeload.github.com/dldevinc/data-xclass/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246296619,"owners_count":20754635,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["html-attributes","ssr","widget"],"created_at":"2024-12-11T09:10:47.832Z","updated_at":"2025-03-30T09:10:35.072Z","avatar_url":"https://github.com/dldevinc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# data-xclass\n\nThis is a lightweight library that is designed to make applying widgets to old-school \nSSR applications. It works by letting you add the names of the widgets you want \nto use in the `data-xclass` attribute.\n\n## Installation\n\nThere are few options on how to include/import `data-xclass` into your project.\n\n### Install from NPM\n\nWe can install XClass from NPM\n\n```\nnpm install data-xclass\n```\n\n```js\nimport XClass from \"data-xclass\";\n\nXClass.register(...);\n```\n\n### Use XClass from CDN\n\nIf you don't want to include `data-xclass` files in your project, you may use it from CDN:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/data-xclass/dist/umd.min.js\"\u003e\u003c/script\u003e\n```\n\n### Download assets\n\nIf you want to use `data-xclass` locally, you can directly download them from https://www.jsdelivr.com/package/npm/data-xclass\n\n## Quick Start\n\nCreating a simple widget:\n\n```js\nimport XClass from \"data-xclass\";\n\n// Register a new widget \"red-class\"\nXClass.register(\"red-class\", {\n    // Initalize the widget on the element\n    init: function (element) {\n        element.classList.add(\"red\");\n    },\n\n    // Clean up any resources when the widget is destroyed\n    destroy: function (element) {\n        element.classList.remove(\"red\");\n    }\n});\n```\n\nThe above code will register the `red-class` widget, which will add the `red` class \nto any element it is applied to.\n\nTo apply the widget, we add the `data-xclass` attribute to the element:\n\n```html\n\u003cdiv data-xclass=\"red-class\"\u003e\n  This element will have the red class\n\u003c/div\u003e\n```\n\n\u003e You can apply multiple widgets to an element by separating the widget names \n\u003e with a space.\n\nNow we need to initialize XClass:\n\n```js\nwindow.addEventListener(\"DOMContentLoaded\", () =\u003e {\n    XClass.start();\n});\n```\n\nThis method will search for DOM elements with the `data-xclass` attribute and initialize \nthe appropriate widgets on them. In addition, it will track changes in the DOM tree and \ninitialize widgets on new DOM elements.\n\n\u003e If you imported XClass into a bundle, you have to make sure you are registering \n\u003e any widget IN BETWEEN when you import the `XClass` global object, and when you \n\u003e initialize XClass by calling `XClass.start()`. Otherwise, you will have to call\n\u003e `XClass.initTree()` to manually initialize the widgets.\n\n## API\n\n### XClass.register(name, widgetObject)\n\nRegister a widget with the given name.\n\n**Parameters**\n\n- `name`: The name of the widget.\n- `widgetObject`: The widget object to be registered. It can have the following properties:\n  - `onRegister(self)` - A method that is called when the widget is registered.\n  - `init(element, self)` - A method that is called when the widget is applied to an element.\n  - `destroy(element, self)` - A method that is called when the widget is removed from an element.\n  - `dependencies` - An array of widget names that have to be initialized before this widget.\n\n### XClass.start()\n\nInitialize XClass by searching for DOM elements with the `data-xclass` attribute\nand initializing the appropriate widgets on them.\n\nIn addition, it will track changes in the DOM tree and initialize widgets on new DOM elements.\n\n### XClass.stop()\n\nStops XClass from tracking changes in the DOM tree and initializing widgets on new DOM elements.\n\n### XClass.mutateDOM(callback)\n\nMutates the DOM in a safe way by temporarily disabling XClass and then re-enabling it \nafter the DOM mutation is finished.\n\n**Parameters**\n\n- `callback`: A function that will be called with no arguments. This callback will be \n  executed with XClass disabled and should contain the DOM mutation logic.\n\n### XClass.isWidgetApplied(element, name)\n\nChecks if the widget with the given name is applied to the given element.\n\n**Parameters**\n\n- `element`: The element to check.\n- `name`: The name of the widget to check.\n\n**Returns**\n\nA boolean value indicating if the widget is applied to the given element.\n\n### XClass.addWidget(element, ...names)\n\nAdds the given widgets to the given element.\n\n**Parameters**\n\n- `element`: The element to which the widgets will be applied.\n- `names`: The names of the widgets to be applied.\n\n```js\nconst button = document.querySelector(\"#form-button\");\nXClass.addWidget(button, \"red-class\", \"animated-button\");\n```\n\n### XClass.deleteWidget(element, ...names)\n\nRemoves the given widgets from the given element.\n\n**Parameters**\n\n- `element`: The element from which the widgets will be removed.\n- `names`: The names of the widgets to be removed.\n\n```js\nconst button = document.querySelector(\"#form-button\");\nXClass.deleteWidget(button, \"animated-button\");\n```\n\n### XClass.deleteAllWidgets(element)\n\nRemoves all widgets from the given element.\n\n**Parameters**\n\n- `element`: The element from which all widgets will be removed.\n\n```js\nconst button = document.querySelector(\"#form-button\");\nXClass.deleteAllWidgets(button);\n```\n\n### XClass.findClosest(element, name)\n\nFinds the closest ancestor of the given element that has the given widget applied.\n\n**Parameters**\n\n- `element`: The element to start searching from.\n- `name`: The name of the widget.\n\n**Returns**\n\nThe element that has the widget applied, or null if the widget is not found.\n\n```js\nconst nameField = document.querySelector(\"input[name=name]\");\nconst ajaxFormElement = XClass.findClosest(nameField, \"ajax-form\");\n```\n\n### XClass.find(root, name)\n\nFinds the first element in the given root element that has the given widget applied.\n\n**Parameters**\n\n- `root`: The element to start searching from.\n- `name`: The name of the widget.\n\n**Returns**\n\nThe element that has the widget applied, or null if the widget is not found.\n\n```js\nconst redElement = XClass.find(document, \"red-class\");\nif (redElement) {\n    XClass.deleteWidget(redElement, \"red-class\");\n}\n```\n\n### XClass.findAll(root, name)\n\nFinds all elements in the given root element that have the given widget applied.\n\n**Parameters**\n\n- `root`: The element to start searching from.\n- `name`: The name of the widget.\n\n**Returns**\n\nAn array of elements that have the widget applied.\n\n```js\n// Delete all instances of \"red-class\" widget\nconst redElements = XClass.findAll(document.documentElement, \"red-class\");\nredElements.forEach(node =\u003e {\n  XClass.deleteWidget(node, \"red-class\");\n});\n```\n\n### XClass.initTree(root = document.documentElement)\n\nInitalizes all widgets in the given root element.\n\n**Parameters**\n\n- `root`: The root element to start searching from. Defaults to `document.documentElement`.\n\n### XClass.destroyTree(root = document.documentElement)\n\nDestroys all widgets in the given root element.\n\n**Parameters**\n\n- `root`: The root element to start searching from. Defaults to `document.documentElement`.\n\n## Examples\n\n### Swiper.js widget\n\nThis example shows how to create a simple widget that uses [Swiper.js](https://swiperjs.com/) \nto create a carousel:\n\n```js\nimport XClass from \"data-xclass\";\nimport Swiper from \"swiper\";\nimport { FreeMode } from \"swiper/modules\";\n\nimport \"swiper/css\";\n\nXClass.register(\"simple-swiper\", {\n    init: function (element) {\n        new Swiper(element, {\n            modules: [FreeMode],\n            spaceBetween: parseInt(element.dataset.swiperSpaceBetween) || 10,\n            slidesPerView: parseInt(element.dataset.swiperSlidesPerView) || \"auto\"\n        });\n    },\n    destroy: function (element) {\n        const swiper = element.swiper;\n        if (swiper) {\n            swiper.destroy();\n        }\n    }\n});\n```\n\nWe can then apply this widget to an element with the `data-xclass` attribute:\n\n```html\n\u003cdiv class=\"swiper\" data-xclass=\"simple-swiper\" data-swiper-space-between=\"10\" data-swiper-slides-per-view=\"3\"\u003e\n    \u003cdiv class=\"swiper-wrapper\"\u003e\n        \u003cdiv class=\"swiper-slide\"\u003eSlide 1\u003c/div\u003e\n        \u003cdiv class=\"swiper-slide\"\u003eSlide 2\u003c/div\u003e\n        \u003cdiv class=\"swiper-slide\"\u003eSlide 3\u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n\n\u003e Note that we are passing options to the widget via the `data-` attributes.\n\u003e This is a good practice as it allows us to configure the widget without having\n\u003e to modify our code.\n\n### Widget dependencies\n\nThis example shows how to create a widget that depends on another widget:\n\n```js\nimport XClass from \"data-xclass\";\n\nXClass.register(\"red-class\", {\n    init: function (element) {\n        element.classList.add(\"red\");\n    },\n    destroy: function (element) {\n        element.classList.remove(\"red\");\n    }\n});\n\nXClass.register(\"blue-class\", {\n    dependencies: [\"red-class\"],\n    init: function (element) {\n        element.classList.add(\"blue\");\n    },\n    destroy: function (element) {\n        element.classList.remove(\"blue\");\n    }\n});\n```\n\nIn this example, the `blue-class` widget depends on the `red-class` widget. This\nmeans that when the `blue-class` widget is applied, the `red-class` widget will\nautomatically be applied first.\n\nTo apply the `blue-class` widget, we just need to set the `data-xclass` attribute:\n\n```html\n\u003cdiv data-xclass=\"blue-class\"\u003e\n  This element will have the red and blue classes\n\u003c/div\u003e\n```\n\n### Alias for a set of widgets\n\nSometimes we want to apply multiple widgets to an element with a single command.\nWe can do this by creating an alias for a set of widgets:\n\n```js\n// Create an alias for the red-class and blue-class widgets\nXClass.register(\"red-blue-classes\", {\n    dependencies: [\"red-class\", \"blue-class\"]\n});\n```\n\nNow we can apply both the `red-class` and `blue-class` widgets with a single command:\n\n```html\n\u003cdiv data-xclass=\"red-blue-classes\"\u003e\n  This element will have the red and blue classes\n\u003c/div\u003e\n```\n\n## License\n\n[MIT](https://github.com/dldevinc/data-xclass/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdldevinc%2Fdata-xclass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdldevinc%2Fdata-xclass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdldevinc%2Fdata-xclass/lists"}