{"id":15357145,"url":"https://github.com/chocolateboy/element-scope-ids","last_synced_at":"2026-02-05T06:01:03.459Z","repository":{"id":48594581,"uuid":"159728622","full_name":"chocolateboy/element-scope-ids","owner":"chocolateboy","description":"Scope IDs to an element by rewriting them to be globally unique","archived":false,"fork":false,"pushed_at":"2021-07-19T05:32:02.000Z","size":504,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-25T08:45:38.603Z","etag":null,"topics":["aria","css","css-modules","dom","html","html-modules","id","ids","modular","scope","scoped","wai-aria"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/chocolateboy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-29T21:18:50.000Z","updated_at":"2021-11-02T22:20:17.000Z","dependencies_parsed_at":"2022-08-27T21:23:37.049Z","dependency_job_id":null,"html_url":"https://github.com/chocolateboy/element-scope-ids","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/chocolateboy/element-scope-ids","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Felement-scope-ids","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Felement-scope-ids/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Felement-scope-ids/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Felement-scope-ids/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chocolateboy","download_url":"https://codeload.github.com/chocolateboy/element-scope-ids/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Felement-scope-ids/sbom","scorecard":{"id":278554,"data":{"date":"2025-08-11","repo":{"name":"github.com/chocolateboy/element-scope-ids","commit":"bb220bcebd5d522f783146971cb00bbd89a0a696"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/16 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 1 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"33 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-w8qv-6jwh-64r5","Warn: Project is vulnerable to: GHSA-257v-vj4p-3w2h","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-7r28-3m3f-r2pr","Warn: Project is vulnerable to: GHSA-r8j5-h5cx-65gg","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-76p3-8jx3-jpfq","Warn: Project is vulnerable to: GHSA-3rfm-jhwj-7488","Warn: Project is vulnerable to: GHSA-hhq3-ff78-jv3g","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-qrpm-p2h7-hrv2","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-rp65-9cf3-cjxr","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-566m-qj78-rww5","Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j","Warn: Project is vulnerable to: GHSA-hwj9-h5mp-3pm3","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-jv35-xqg7-f92r","Warn: Project is vulnerable to: GHSA-g4rg-993r-mgx7","Warn: Project is vulnerable to: GHSA-4rq4-32rv-6wp6","Warn: Project is vulnerable to: GHSA-64g7-mvw6-v9qj","Warn: Project is vulnerable to: GHSA-4wf5-vphf-c2xc"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T15:08:36.190Z","repository_id":48594581,"created_at":"2025-08-17T15:08:36.190Z","updated_at":"2025-08-17T15:08:36.190Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29114493,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T05:31:32.482Z","status":"ssl_error","status_checked_at":"2026-02-05T05:31:29.075Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["aria","css","css-modules","dom","html","html-modules","id","ids","modular","scope","scoped","wai-aria"],"created_at":"2024-10-01T12:33:27.919Z","updated_at":"2026-02-05T06:01:03.408Z","avatar_url":"https://github.com/chocolateboy.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# element-scope-ids\n\n[![Build Status](https://travis-ci.org/chocolateboy/element-scope-ids.svg)](https://travis-ci.org/chocolateboy/element-scope-ids)\n[![NPM Version](https://img.shields.io/npm/v/element-scope-ids.svg)](https://www.npmjs.org/package/element-scope-ids)\n\n- [NAME](#name)\n- [INSTALLATION](#installation)\n- [SYNOPSIS](#synopsis)\n- [DESCRIPTION](#description)\n- [WHY?](#why)\n- [TYPES](#types)\n  - [IdAttrs](#type-idattrs)\n  - [Options](#type-options)\n- [EXPORTS](#exports)\n  - [Scoper (default)](#scoper-class)\n    - [Events](#events)\n      - [id](#id)\n      - [ids](#ids)\n    - [Options](#options)\n      - [exclude](#exclude)\n      - [idAttrs](#idattrs)\n    - [Methods](#methods)\n      - [scopeIds](#scope-ids-method)\n      - [scopeOwnIds](#scope-own-ids-method)\n  - [scopeIds](#scope-ids-function)\n  - [scopeOwnIds](#scope-own-ids-function)\n- [EXAMPLES](#examples)\n  - [Debugging](#debugging)\n  - [Exclude global IDs](#exclude-global-ids)\n  - [Use with jQuery](#use-with-jquery)\n- [DEVELOPMENT](#development)\n  - [NPM Scripts](#npm-scripts)\n- [COMPATIBILITY](#compatibility)\n- [SEE ALSO](#see-also)\n- [VERSION](#version)\n- [AUTHOR](#author)\n- [COPYRIGHT AND LICENSE](#copyright-and-license)\n\n# NAME\n\nelement-scope-ids - scope IDs to an element by rewriting them to be globally unique\n\n# INSTALLATION\n\n    $ npm install element-scope-ids\n\n# SYNOPSIS\n\n```javascript\nimport { scopeIds } from 'element-scope-ids'\n\nfor (const el of document.querySelectorAll('.tabs')) {\n    scopeIds(el)\n}\n```\n\n**before**:\n\n```html\n\u003cdiv class=\"tabs\"\u003e\n    \u003cul role=\"tablist\"\u003e\n        \u003cli id=\"foo-tab\" role=\"tab\" aria-controls=\"foo-panel\"\u003eFoo\u003c/li\u003e\n        \u003cli id=\"bar-tab\" role=\"tab\" aria-controls=\"bar-panel\"\u003eBar\u003c/li\u003e\n    \u003c/ul\u003e\n    \u003cdiv id=\"foo-panel\" role=\"tabpanel\"\u003e...\u003c/div\u003e\n    \u003cdiv id=\"bar-panel\" role=\"tabpanel\"\u003e...\u003c/div\u003e\n\u003c/div\u003e\n```\n\n**after**:\n\n```html\n\u003cdiv class=\"tabs\"\u003e\n    \u003cul role=\"tablist\"\u003e\n        \u003cli id=\"foo-tab-123\" role=\"tab\" aria-controls=\"foo-panel-234\"\u003eFoo\u003c/li\u003e\n        \u003cli id=\"bar-tab-345\" role=\"tab\" aria-controls=\"bar-panel-456\"\u003eBar\u003c/li\u003e\n    \u003c/ul\u003e\n    \u003cdiv id=\"foo-panel-234\" role=\"tabpanel\"\u003e...\u003c/div\u003e\n    \u003cdiv id=\"bar-panel-456\" role-\"tabpanel\"\u003e...\u003c/div\u003e\n\u003c/div\u003e\n```\n\n# DESCRIPTION\n\nThis module exports a class (and helper functions which wrap an instance of the class)\nwhich rewrites IDs within elements so that they're safe to compose with other elements\non the page which use the same IDs. This is done by rewriting each ID to be globally unique\n(while preserving any internal references). This is similar to the technique used to transpile\nscoped CSS (e.g. CSS modules) by PostCSS, Angular etc.\n\n# WHY?\n\nIDs are the natural way to declare relationships between elements in various HTML components, e.g.:\n\n- [accordions](https://www.w3.org/TR/wai-aria-practices/#accordion) and\n  [tabs](https://www.w3.org/TR/wai-aria-practices/#tabpanel)\n  (e.g. [`aria-controls`](https://www.w3.org/TR/wai-aria/#aria-controls) and\n  [`aria-labelledby`](https://www.w3.org/TR/wai-aria/#aria-labelledby))\n- labeled form elements ([`for`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#Attributes))\n\nThis approach works well for simple, static pages — e.g. if there's only one accordion or form on\na page — but quickly becomes cumbersome in situations where there's more than one such component,\ne.g. in SPAs where many components of the same type may be embedded in the DOM at the same time.\nIt can also be tedious and error prone even in multi-page apps simply because IDs are names, and\n[naming things is hard](https://martinfowler.com/bliki/TwoHardThings.html): decomposing\na page into reusable components can make it difficult to keep track of which IDs are safe to use\nwhere, and this can be compounded in apps which pull in third-party components.\n\nOne solution is to use another attribute, e.g. `data-id`, but these remain unique IDs in everything\nbut name, and they still need to be translated back into actual IDs for ARIA/form elements etc.,\nso this does little more than move the problem sideways.\n\nA better solution is to keep using IDs but to make them safe to compose and reuse — in the\nsame manner as class names in scoped CSS (and local variable names in most programming\nlanguages). This is done by making each ID globally unique (with an escape hatch for\nshared/global IDs).\n\n# TYPES\n\nThe following types are referenced in the descriptions below:\n\n## IdAttrs \u003ca name=\"type-idattrs\"\u003e\u003c/a\u003e\n\nAn array (or other iterable collection) of attribute names to look for IDs in or a function which returns the names.\n\n```typescript\ntype IdAttrs = Iterable\u003cstring\u003e | (idAttrs: Iterable\u003cstring\u003e) =\u003e Iterable\u003cstring\u003e\n```\n\n## Options \u003ca name=\"type-options\"\u003e\u003c/a\u003e\n\nAn options object which can be passed to the [Scoper](#scoper-class) constructor\nand its [`scopeIds`](#scope-ids-method) and [`scopeOwnIds`](#scope-own-ids-method) methods.\n\n```typescript\ntype Options = {\n    exclude?: (HTMLElement, id: { name: string, value: string }, next: (typeof exclude)) =\u003e boolean | string;\n    idAttrs?: IdAttrs;\n}\n```\n\n# EXPORTS\n\n## Scoper (default) \u003ca name=\"scoper-class\"\u003e\u003c/a\u003e\n\nInstances of this class can be used to rewrite IDs within DOM elements so that they can\nsafely be composed with other elements which use the same IDs. This is done by rewriting\nthe IDs to be globally unique, while preserving internal links.\n\n**Type**: Scoper(options?: [Options](#type-options))\n\n```javascript\nimport Scoper from 'element-scope-ids'\n\nconst scoper = new Scoper()\n\nscoper.on('id', (element, id) =\u003e {\n    element.setAttribute(`data-original-${id.name}`, id.old)\n})\n\nfor (const el of document.querySelectorAll('.tabs')) {\n    scoper.scopeIds(el)\n}\n```\n\n### Events\n\nScoper implements the [EventEmitter](https://nodejs.org/api/events.html) interface. The following\nevents are supported:\n\n#### id\n\n**Type**: (el: HTMLElement, { name: string, old: string, new: string }) → void\n\nFired each time an ID-like attribute is changed. As well as the `id` attribute itself, this also includes\nARIA attributes such as `aria-controls` and the `for` attribute on LABEL elements. The listener is passed\nthe element and a delta object which contains the old ID and the new ID.\n\n```javascript\nscoper.on('id', (element, id) =\u003e {\n    element.setAttribute(`data-original-${id.name}`, id.old)\n})\n```\n\nNote that an event is fired for *each ID* rather than each attribute. This distinction is important\nfor attributes which may take multiple IDs, e.g. `aria-labelledby`.\n\n#### ids\n\n**Type**: (el: HTMLElement, { [name: string]: { old: string, new: string } }) → void\n\nFired after all IDs have been replaced in an element. Passed the element and an object whose\nkeys are the names of modified attributes and whose values are delta objects with the old and new\nvalues for the attribute, e.g.:\n\n```javascript\nscoper.on('ids', (element, ids) =\u003e {\n    element.setAttribute('data-scoped-attributes', Object.keys(ids).join(' '))\n})\n```\n\n### Options\n\nThe constructor takes an optional [Options](#type-options) object with the following (optional) fields:\n\n#### exclude\n\n**Type**: (el: HTMLElement, id: { name: string, value: string }, next: (typeof exclude)) → boolean | string\n\nA function which is used to prevent an ID being scoped. Called once for each ID in each ID-like attribute\n(as defined by [`idAttrs`](#idattrs)) in each target element. If supplied, the function can veto scoping\n(i.e. renaming) the ID by returning true. Alternatively, it can veto scoping by returning a replacement ID.\n\nThe `next` value in the final parameter is a reference to the default `exclude` function.\nThere can be up to three `exclude` functions (built-in, constructor option, method option)\nand each one after the built-in can delegate to the one it's overriding, passing the decision\nback from the method option (if supplied) to the constructor option (if supplied) to the\ndefault implementation.\n\nIf the `next` function is called with no arguments, it is passed the original arguments. Otherwise\nthe supplied arguments are passed to the previous `exclude`.\n\n```javascript\nconst scoper = new Scoper({\n    exclude (element, id, next) {\n        // next() (no arguments) is the same as next(...arguments)\n        return (element.dataset.scopeIds || '') === 'false' ? true : next()\n    }\n})\n```\n\n`exclude` can be used to filter by type, e.g. the default implementation restricts the `for`\nattribute to LABEL elements:\n\n```javascript\nconst scoper = new Scoper({\n    exclude (element, id, next) {\n        return id.name === 'for' ? element.tagName !== 'LABEL' : next()\n    }\n})\n```\n\nIt can also be used to [exclude global IDs](#exclude-global-ids).\n\n#### idAttrs\n\n**Type**: [IdAttrs](#type-idattrs)\n\nA list (e.g. array) of attribute names to treat as \"ID-like\" i.e. the names of attributes IDs should be replaced in.\n\nTo add attributes to the default list, or exclude attributes, a function can be supplied which receives the default list as an argument.\nThe function's return value is used as the new list:\n\n```javascript\nconst scoper = new Scoper({\n    idAttrs (defaultIdAttrs) {\n        return defaultIdAttrs.concat(['contextmenu'])\n    }\n})\n```\n\n### Methods\n\n#### scopeIds \u003ca name=\"scope-ids-method\"\u003e\u003c/a\u003e\n\n**Type**: \u003cT extends HTMLElement\u003e(el: T, options?: [Options](#type-options)) → T\n\nTakes a DOM element and rewrites any IDs found in its child/descendant elements so\nthat they are globally unique, and thus safe to combine on a page with another element\nwhich uses the same IDs.\n\nIf the `options` parameter is supplied, its values override the corresponding\noptions passed to the constructor for the scope of the call.\n\n#### scopeOwnIds \u003ca name=\"scope-own-ids-method\"\u003e\u003c/a\u003e\n\n**Type**: \u003cT extends HTMLElement\u003e(el: T, options?: [Options](#type-options)) → T\n\nTakes a DOM element and rewrites any IDs found in the element itself (i.e. not in its\ndescendants) so that they are globally unique, and thus safe to combine on a page with\nanother element which uses the same IDs.\n\nIf the `options` parameter is supplied, its values override the corresponding\noptions passed to the constructor for the scope of the call.\n\n## scopeIds \u003ca name=\"scope-ids-function\"\u003e\u003c/a\u003e\n\n**Type**: (el: HTMLElement, options?: [Options](#type-options)) → void\n\nA functional wrapper around the [`scopeIds`](#scope-ids-method) method of an instance of\nthe [Scoper](#scoper) class created with the default options i.e. this:\n\n```javascript\nimport { scopeIds } from 'element-scope-ids'\n\nfor (const el of document.querySelectorAll('.tabs')) {\n    scopeIds(el)\n}\n```\n\nis equivalent to:\n\n```javascript\nimport Scoper from 'element-scope-ids'\n\nconst scoper = new Scoper()\n\nfor (const el of document.querySelectorAll('.tabs')) {\n    scoper.scopeIds(el)\n}\n```\n\n## scopeOwnIds \u003ca name=\"scope-own-ids-function\"\u003e\u003c/a\u003e\n\n**Type**: (el: HTMLElement, options?: [Options](#type-options)) → void\n\nA functional wrapper around the [`scopeOwnIds`](#scope-own-ids-method) method of\nan instance of the [Scoper](#scoper) class created with the default options.\n\nUses the same default instance of the Scoper class as [`scopeIds`](#scope-ids-function).\n\n# EXAMPLES\n\n## Debugging\n\nTo log what IDs have been changed where, intercept one of the [events](#events)\n(to veto a change, see [`exclude`](#exclude)), e.g.:\n\n```javascript\nconst scoper = new Scoper()\n\nscoper.on('id', (element, id) =\u003e {\n    console.log(`${element.tagName}[${id.name}]: ${id.old} =\u003e ${id.new}`)\n})\n```\n\n## Exclude global IDs\n\nThis can be done by supplying an [`exclude`](#exclude) constructor/method\noption which identifies and optionally transforms global IDs, e.g.:\n\n```javascript\nfunction isGlobal (el, { value }, next) {\n    return (value[0] === '/') ? value.substr(1) : next()\n}\n\nconst scoper = new Scoper({ exclude: isGlobal })\n\nfor (const el of document.querySelectorAll('[data-scope-ids=\"true\"]')) {\n    scoper.scopeIds(el)\n    el.setAttribute('data-scope-ids', 'done')\n}\n```\n\n**before**:\n\n```html\n\u003cdiv data-scope-ids=\"true\"\u003e\n    \u003cspan id=\"foo\"\u003e\u003c/span\u003e\n    \u003cspan id=\"/bar\"\u003e\u003c/span\u003e\n    \u003cspan id=\"/baz\"\u003e\u003c/span\u003e\n    \u003cspan id=\"quux\"\u003e\u003c/span\u003e\n\u003c/div\u003e\n```\n\n**after**:\n\n```html\n\u003cdiv data-scope-ids=\"done\"\u003e\n    \u003cspan id=\"foo-123\"\u003e\u003c/span\u003e\n    \u003cspan id=\"bar\"\u003e\u003c/span\u003e\n    \u003cspan id=\"baz\"\u003e\u003c/span\u003e\n    \u003cspan id=\"quux-234\"\u003e\u003c/span\u003e\n\u003c/div\u003e\n```\n\n## Use with jQuery\n\nelement-scope-ids doesn't depend on jQuery, but it can easily be\nintegrated with it, or any other front-end library or framework.\n\nIn this example, we mount a Tabs controller object on each tabs\nwidget after its IDs have been scoped.\n\n```javascript\nimport 'jquery-initialize'\nimport Tablist from '@accede-web/tablist'\n\n// scope IDs in every current and future element which has data-scope-ids=\"true\"\n$.initialize('[data-scope-ids=\"true\"]', function () {\n    scopeIds(this)\n    $(this).attr('data-scope-ids', 'done') // mark the IDs as scoped\n})\n\n// don't process tabs until their IDs have been scoped\n$.initialize('[data-scope-ids=\"done\"] [role=\"tablist\"]', function () {\n    new Tablist(this).mount()\n})\n```\n\n# DEVELOPMENT\n\n\u003cdetails\u003e\n\n## NPM Scripts\n\nThe following NPM scripts are available:\n\n- build - compile the library and package it for release\n- bundle - package the compiled source code for CommonJS, ESM etc.\n- clean - remove temporary files and build artifacts\n- compile - compile the source code ready for bundling\n\n\u003c/details\u003e\n\n# COMPATIBILITY\n\n- \u0026gt; 1% of browsers\n- IE 11\n- not Opera Mini\n\n# SEE ALSO\n\n## IDs\n\n- [@zthun/zidentifier.core](https://www.npmjs.com/package/@zthun/zidentifier.core) - generate namespaced IDs from nested paths\n\n## ARIA widgets\n\n- [@accede-web/accordion](https://www.npmjs.com/package/@accede-web/accordion) - a dependency-free WAI-ARIA accordion plugin\n- [@accede-web/tablist](https://www.npmjs.com/package/@accede-web/tablist) - a dependency-free WAI-ARIA tab plugin\n- [posthtml-aria-tabs](https://www.npmjs.com/package/posthtml-aria-tabs) - a PostHTML plugin for creating accessible tabs with minimal markup\n\n## Scoped CSS\n\n- [CSS Modules](https://github.com/css-modules/css-modules)\n\n# VERSION\n\n0.1.1\n\n# AUTHOR\n\n[chocolateboy](mailto:chocolate@cpan.org)\n\n# COPYRIGHT AND LICENSE\n\nCopyright © 2018-2021 by chocolateboy.\n\nThis is free software; you can redistribute it and/or modify it under the terms\nof the [MIT license](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchocolateboy%2Felement-scope-ids","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchocolateboy%2Felement-scope-ids","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchocolateboy%2Felement-scope-ids/lists"}