{"id":18794230,"url":"https://github.com/conversejs/skeletor","last_synced_at":"2025-04-13T14:32:34.979Z","repository":{"id":42389171,"uuid":"270693974","full_name":"conversejs/skeletor","owner":"conversejs","description":"Skeletor is a Backbone fork that lets you turn Views into Web Components.","archived":false,"fork":false,"pushed_at":"2024-03-22T21:05:35.000Z","size":27928,"stargazers_count":13,"open_issues_count":2,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-28T06:44:13.193Z","etag":null,"topics":["backbone"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/conversejs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":".github/FUNDING.yml","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,"publiccode":null,"codemeta":null},"funding":{"patreon":"jcbrand","liberapay":"jcbrand"}},"created_at":"2020-06-08T14:13:03.000Z","updated_at":"2024-06-18T18:43:00.617Z","dependencies_parsed_at":"2022-09-19T16:52:01.704Z","dependency_job_id":"503ab4f3-3fb1-4354-86f6-f75c0562fe3c","html_url":"https://github.com/conversejs/skeletor","commit_stats":{"total_commits":2579,"total_committers":354,"mean_commits":7.285310734463277,"dds":0.6835982939123691,"last_synced_commit":"7011d38ee78d982627586f9d42e085cce11ca99f"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/conversejs%2Fskeletor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/conversejs%2Fskeletor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/conversejs%2Fskeletor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/conversejs%2Fskeletor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/conversejs","download_url":"https://codeload.github.com/conversejs/skeletor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223591754,"owners_count":17170363,"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":["backbone"],"created_at":"2024-11-07T21:28:44.113Z","updated_at":"2024-11-07T21:28:44.703Z","avatar_url":"https://github.com/conversejs.png","language":"JavaScript","funding_links":["https://patreon.com/jcbrand","https://liberapay.com/jcbrand"],"categories":[],"sub_categories":[],"readme":"# Skeletor\n\n[![XMPP Chat](https://conference.conversejs.org/muc_badge/discuss@conference.conversejs.org)](https://inverse.chat/#converse/room?jid=discuss@conference.conversejs.org)\n[![CI Tests](https://github.com/conversejs/skeletor/actions/workflows/karma-tests.yml/badge.svg)](https://github.com/conversejs/skeletor/actions/workflows/karma-tests.yml)\n\nSkeletor is a modernization of [Backbone](http://backbonejs.org)'s Models and Collections,\nwhile getting rid of the old Views.\n\nIt provides you with a more modern Backbone-like way to manage state.\n\n## Introduction\n\nThe original goal of Skeletor was to modernize Backbone to allow writing\ndeclarative view code instead of the imperative code (e.g. manually adding and\nremoving DOM nodes). In other words, to allow for component-based code that\nautomatically updates only the changed parts of the DOM, similarly to basically\nall modern JavaScript frameworks.\n\nThe original Backbone Views aren't components and can't be rendered in a nested and\ndeclarative way. Instead, it's up to you to manually make sure that these views\nare rendered in the correct place in the DOM. This approach becomes unwieldy,\ndifficult and fragile as your site becomes larger and more complex.\n\nSkeletor solves this by creating a new type of View, called `ElementView`,\nwhich is very similar to the original Backbone `View` but which is also a web\ncomponent that gets instantiated automatically as soon as its rendered in the\nDOM.\n\nThe thing is, [Lit](https://lit.dev) Elements already provide anything one\nmight need for a modern Backbone-line application. There's not really a need\nfor the `ElementView` anymore, except to provide an upgrade path from a\nBackbone app to one that uses web components. It'll therefore likely be removed\nentirely in a future version, thereby leaving only Models and Collections, for\nmanaging state.\n\n## Installation\n\n```\nnpm install @converse/skeletor\n```\n\n## Changes from Backbone\n\nWe've made big, backwards incompatible changes in version 2:\n\n- Removed the old `View` type\n- Removed the old `Events` constructor function and instead added the `EventsEmitter` mixin class.\n- Removed the `Router` and `History` classes.\n- All other types (`Model`, `Collection`, `ElementView`) are now ES6 classes.\n\n### Sekeletor adds the following changes to Backbone\n\n* Added TypeScript type declarations (generated from typed JSDoc comments)\n* Removes the dependency on jQuery\n* Replaces [underscore](http://underscorejs.org) with [lodash](https://lodash.com)\n* Imports lodash methods individually to allow for tree-shaking\n* Uses the native browser API instead of lodash whereever possible\n* Drops support for older browsers (including IE) and uses ES6+ language features\n* Splits models and collections into separate modules\n* Adds the possibility to returns promises for asynchronous operations\n* Adds a new `ElementView` class, which is a like a Backbone View, but doubles\n  as an instance of HTMLElement and can be used to register a custom element or\n  web-component.\n\n### Other backwards incompatible changes\n\n* Collection.prototype.forEach no longer returns the items being iterated over.\n  If you need that, use `map` instead.\n* The `chain`, `clone` and `escape` methods on Models have been removed.\n* The `clone` method has also been removed from Collections\n* The `inject`, `foldl` and `foldr` methods on Collections has been removed. You can use `reduce` instead.\n* Removed the `sample`, `take`, `tail` and `initial` method on Collections.\n* Removed the `without`, `reject` and `select` methods on Collections, use `filter`.\n* Removed the `.extend()` method on `Model` and `Collection`.\n* Models and Collections should be defined via `class .. extends` syntax.\n\n#### Changes due to using Lodash instead of Underscore\n\n1. Use `drop` instead of `rest`.\n2. `indexBy` is called `keyBy`\n3. Use `invokeMap` for collections instead of `invoke`.\n4. Use `includes` instead of `contains`\n5. The `partition` and `invokeMap` methods have been removed.\n\n### ElementView example\n\nThe ElementView looks very similar to a normal Backbone View.\n\nSince it's a web component, you need to call `CustomElementRegistry.define` to\nregister it.\n\nThe `this` variable for the ElementView is the custom DOM element itself,\nin this case, `\u003cmy-custom-button\u003e`.\n\nSo there is no `el` attribute and `this.el` will be undefined. Whereever in a\nBackbone View you'd use `this.el`, with an ElementView you'd just use `this`.\n\n\n```javascript\n\nimport { ElementView } from '@converse/skeletor/src/element.js';\nimport { render } from 'lit';\nimport { html } from 'lit';\n\nexport default class MyCustomButton extends ElementView {\n    events = {\n        'click .button': 'onButtonClicked'\n    }\n\n    async initialize () {\n        this.model = new Model({ count: 0 });\n        this.listenTo(this.model, 'change', this.render)\n    }\n\n    render () {\n      return render(html`\u003cbutton class=\"button\"\u003eI've been clicked ${model.get('count')} times!\u003c/button\u003e`, this);\n    }\n\n    onButtonClicked () {\n      this.model.save('count', this.model.get('count')+1);\n    }\n}\n\nCustomElementRegistry.define('my-custom-button', MyCustomButton);\n```\n\nYou can now put your custom element in the DOM, and once the DOM is loaded by\nthe browser, your ElementView will automatically be instantiated and\n`initialize` will be called.\n\n\n```html\n  \u003cdiv\u003e\n    \u003cmy-custom-button\u003e\u003c/my-custom-button\u003e\n  \u003c/div\u003e\n```\n\n![](https://raw.githubusercontent.com/conversejs/skeletor/master/images/skeletor2.jpg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconversejs%2Fskeletor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconversejs%2Fskeletor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconversejs%2Fskeletor/lists"}