{"id":13481728,"url":"https://github.com/ErikOnBike/d3-template","last_synced_at":"2025-03-27T12:31:21.770Z","repository":{"id":49729258,"uuid":"118825808","full_name":"ErikOnBike/d3-template","owner":"ErikOnBike","description":"D3 plugin to create and render templates using D3's data binding mechanism","archived":false,"fork":false,"pushed_at":"2023-05-23T13:22:24.000Z","size":1560,"stargazers_count":8,"open_issues_count":4,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-19T09:32:57.303Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/ErikOnBike.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,"publiccode":null,"codemeta":null}},"created_at":"2018-01-24T21:41:59.000Z","updated_at":"2023-05-23T13:17:00.000Z","dependencies_parsed_at":"2024-10-30T22:36:12.268Z","dependency_job_id":null,"html_url":"https://github.com/ErikOnBike/d3-template","commit_stats":{"total_commits":175,"total_committers":3,"mean_commits":"58.333333333333336","dds":"0.13142857142857145","last_synced_commit":"b17dea6b5f0f85c71f79ff7d4511ce438e4addf5"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ErikOnBike%2Fd3-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ErikOnBike%2Fd3-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ErikOnBike%2Fd3-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ErikOnBike%2Fd3-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ErikOnBike","download_url":"https://codeload.github.com/ErikOnBike/d3-template/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245844901,"owners_count":20681800,"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":[],"created_at":"2024-07-31T17:00:54.797Z","updated_at":"2025-03-27T12:31:21.382Z","avatar_url":"https://github.com/ErikOnBike.png","language":"JavaScript","funding_links":[],"categories":["Utils"],"sub_categories":[],"readme":"# d3-template\n\n*(This version is meant for V4/V5 and has not been tested on V3 or earlier versions of D3)*\n\nThis is version 2 of d3-template. If you have used version 1 before, please check out the [explanation](#History).\n\nd3-template is a D3 plugin to support templates using D3's data binding mechanism.  This means you can use D3's familiar functionality directly on or with your templates. Apply transitions or add event handlers to template elements with access to the bound data. Render new data on a template thereby updating attributes, styles, properties and text. Also new elements are added and superfluous elements are removed from repeating groups (D3's enter/exit update pattern). This works for both HTML as well as SVG elements both in the browser as well as within Node. Templates will normally be acting on the live DOM, but can be used on virtual DOM's (like [jsdom](https://github.com/jsdom/jsdom)) as well.\n\nIf you are looking for existing templating support like Handlebars, Mustache or Nunjucks have a look at [d3-templating](https://github.com/jkutianski/d3-templating).\n\nThe following information is available:\n* [Usage](#Usage)\n* [Installing](#Installing)\n* [Features](#Features)\n* [Limitations](#Limitations)\n* [API Reference](#API-Reference)\n* [Details](#Details)\n    * [Repeating groups](#Repeating-groups)\n    * [If groups](#If-groups)\n    * [Import templates](#Import-templates)\n    * [Transitions](#Transitions)\n    * [Event handlers](#Event-handlers)\n* [History](#History)\n* [Examples](examples/README.md)\n* [License](LICENSE)\n\n## \u003ca name=\"Usage\"\u003eUsage\u003c/a\u003e\n\nTemplates look like they do in most other templating tools: rendering data by placing expressions within curly braces into HTML or SVG elements. These expressions are data functions (as described in the [introduction](https://d3js.org/#properties) of the D3 homepage) but lack an explicit `return` statement. The standard arguments `d, i, nodes` are present and `this` is set to the (Template) node being rendered.\n\nThe general usage is probably best described by an example (see example on [bl.ocks.org](https://bl.ocks.org/ErikOnBike/f36ce2b4c88ef525d0cfe34a766d8067)):\n\n```HTML\n\u003cdiv id=\"person\" data-class-alive=\"{{!d.deathdate}}\"\u003e\n    \u003cdiv\u003e\n        \u003cspan\u003e{{`Name: ${d.name}`}}\u003c/span\u003e\n    \u003c/div\u003e\n    \u003cdiv\u003e\n        \u003cspan\u003e{{`Birthdate: ${d3.timeFormat(\"%-d %B %Y\")(d.date)}`}}\u003c/span\u003e\n    \u003c/div\u003e\n    \u003cdiv\u003e\n        \u003cspan\u003eHonours given name to:\u003c/span\u003e\n        \u003cul data-repeat=\"{{d.honours.given}}\"\u003e\n            \u003cli\u003e{{d}}\u003c/li\u003e\n        \u003c/ul\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\n\n    // Add event handler to list element before template creation\n    d3.select(\"#person ul li\")\n        .on(\"click\", function(d, i, nodes) {\n            // d will be entry from the honours.given array\n            // i will be current index\n            // nodes will be the li nodes\n            // this will refer to the current node (ie nodes[i])\n            console.log(d, i, nodes.length);\n        })\n    ;\n\n    // Turn selection into a template\n    // This will remove some elements from the DOM as well as add some attributes to elements\n    // for identification.\n    d3.select(\"#person\")\n        .template()\n    ;\n\n    // ...\n\n    // Render data onto earlier created template\n    // Information retrieved from https://en.wikipedia.org/wiki/Alan_Turing#Awards,_honours,_recognition,_and_tributes\n    d3.select(\"#person\")\n        .render({\n            name: \"Alan Turing\",\n            birthdate: new Date(1912, 5, 23),\n            deathdate: new Date(1954, 5, 7),\n            honours: {\n                received: [\n                    \"Order of the British Empire\",\n                    \"Fellow of the Royal Society\"\n                ],\n                given: [\n                    \"Good–Turing frequency estimation\",\n                    \"Turing completeness\",\n                    \"Turing degree\",\n                    \"Turing fixed-point combinator\",\n                    \"Turing Institute\",\n                    \"Turing Lecture\",\n                    \"Turing machine examples\",\n                    \"Turing patterns\",\n                    \"Turing reduction\",\n                    \"Turing switch\"\n                ]\n            }\n        })\n    ;\n\n    // The click event handler is now present on all li elements\n\u003c/script\u003e\n```\n\nWhen rendering data onto a template which is already rendered, the new data will be bound and elements will be updated accordingly. A [transition](#Transitions) can be created to animate the new data rendering.\n\n## \u003ca name=\"Installing\"\u003eInstalling\u003c/a\u003e\n\nTo install via [npm](https://www.npmjs.com) use `npm install d3-template-plugin`. Or use/install directly using [unpkg](https://unpkg.com/).\n\n    \u003cscript src=\"https://unpkg.com/d3-template-plugin/build/d3-template.min.js\"\u003e\u003c/script\u003e\n\n## \u003ca name=\"Features\"\u003eFeatures\u003c/a\u003e\n\nThe following *features* are present:\n* Data rendering onto attributes and text directly.\n* Data can also be rendered on attributes, styles, properties or class fields indirectly (through `data-attr-\u003cname\u003e`, `data-style-\u003cname\u003e`, `data-prop-\u003cname\u003e` and `data-class-\u003cname\u003e`). Properties can be useful for setting the `value` or `checked` property of HTML input elements for example. The indirect rendering is especially useful for SVG because most browsers do not like 'invalid' attribute values:\n\n    ```SVG\n    \u003c!-- Most browsers do not like this (invalid according to SVG spec) --\u003e\n    \u003ccircle cx=\"{{scalex(d.x)}}\" cy=\"{{scaley(d.y)}}\" r=\"{{d.radius}}\"\u003e\u003c/circle\u003e\n\n    \u003c!-- Browsers are okay with this (valid according to SVG spec) --\u003e\n    \u003ccircle data-attr-cx=\"{{scalex(d.x)}}\" data-attr-cy=\"{{scaley(d.y)}}\" data-attr-r=\"{{d.radius}}\"\u003e\u003c/circle\u003e\n    ```\n\n* [Repeating](#Repeating-groups) and conditional groups (through `data-repeat` and `data-if` attribute).\n* A scope group similar to the Javascript `with` statement (through `data-with` attribute).\n* Other templates can be [imported](#Import-templates). Which template gets imported can be decided on render time based on the bound data.\n* Possibility to overwrite the template attribute names with custom names. If for example `repeat`, `if` and `with` is preferred over de long names, this can be specified when creating a [template](#template). Although such custom attributes are not compliant with HTML5 or SVG specifications, most browsers will accept it without complaining.\n* Render only part of a template by rendering on a group element (repeat, if, with or import).\n* [Event handlers](#Event-handlers) added onto elements before the template was created (using `selection.on()`), will be (re)applied when rendering the template.\n* Rendering can be done within a [transition](#Transitions) allowing animations.\n* Tweens (for attribute, style, property or text) can also be used in combination with a transition by providing a [tween data function](#tweenDataFunction).\n\n## \u003ca name=\"Limitations\"\u003eLimitations\u003c/a\u003e\n\nThe following known *limitations* are present:\n* Data references (the curly braces) can only be applied to the full element or the full attribute value. (For completeness: Surrounding whitespace is allowed for elements or attributes, but will be removed.)\n\n    ```HTML\n    \u003c!-- This will not be recognised by d3-template --\u003e\n    \u003cdiv data-style-width=\"{{d.width}}px\"\u003e...\u003c/div\u003e\n\n    \u003c!-- Use one of the following instead --\u003e\n    \u003cdiv data-style-width=\"{{d.width + 'px'}}\"\u003e...\u003c/div\u003e\n    \u003cdiv data-style-width=\"{{`${d.width}px`}}\"\u003e...\u003c/div\u003e\n\n    \u003c!-- This will not be recognised by d3-template --\u003e\n    \u003cspan\u003e{{jobCount}} jobs\u003c/span\u003e\n\n    \u003c!-- Use one of the following instead --\u003e\n    \u003cspan\u003e{{d.jobCount + \" jobs\"}}\u003c/span\u003e\n    \u003cspan\u003e{{`${d.jobCount} jobs`}}\u003c/span\u003e\n    \u003cspan\u003e\u003cspan\u003e{{d.jobCount}}\u003c/span\u003e jobs\u003c/span\u003e\n    \u003cspan\u003e{{d.jobCount}}\u003c/span\u003e \u003cspan\u003ejobs\u003c/span\u003e\n    ```\n\n* There should be none or one child element for a grouping element (`repeat`, `if` or `with`). If more child elements are needed, these have to be wrapped in a container element. If only text is present, this has to be wrapped in a container element as well. An exception will be thrown during parsing of the template if such invalid structures are present. (Having no child element on a group is actually useless, but allowed for convenience during development.)\n\n    ```HTML\n    \u003c!-- This is not allowed by d3-template --\u003e\n    \u003cul data-repeat=\"{{d}}\"\u003e\n        \u003cli\u003e{{d}}\u003c/li\u003e\n        \u003cli class=\"separator\"\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n\n    \u003c!-- Use the following (or something similar) instead --\u003e\n    \u003cul data-repeat=\"{{d}}\"\u003e\n        \u003cli\u003e\n            \u003cdiv\u003e{{d}}\u003c/div\u003e\n            \u003cdiv class=\"separator\"\u003e\u003c/div\u003e\n        \u003c/li\u003e\n    \u003c/ul\u003e\n\n    \u003c!-- This is not allowed by d3-template --\u003e\n    \u003cdiv data-repeat=\"{{d.stats}}\"\u003e\n        Requests: \u003cspan\u003e{{d.requests}}\u003c/span\u003e (per month)\n    \u003c/div\u003e\n\n    \u003c!-- Use the following (or something similar) instead --\u003e\n    \u003cdiv data-repeat=\"{{d.stats}}\"\u003e\n        \u003cdiv\u003e{{`Requests: ${d.requests} (per month)`}}\u003c/div\u003e\n    \u003c/span\u003e\n    ```\n\n* Grouping elements (`repeat`, `if` or `with`) can not be combined on the same element. One has to be wrapped inside the other.\n* An import element can only be combined with the `with` grouping to scope (or map) the data for the imported template. Combining `import` with `repeat` or `if` is not allowed.\n* There is no `else` for `if` groupings. A second `if` needs to be added (with a negated expression) or an `import` could be used (see [if groups](#If-groups) explanation).\n* Setting properties of (for example) HTML input elements can not be done using transitions, since D3 transitions do not support it. It is however possible to create a [tween data function](#tweenDataFunction).\n\n## \u003ca name=\"API-Reference\"\u003eAPI Reference\u003c/a\u003e\n\n\u003ca name=\"template\" href=\"#template\"\u003e#\u003c/a\u003e d3.\u003cb\u003etemplate\u003c/b\u003e(\u003ci\u003eselection[, options]\u003c/i\u003e) [\u003c\u003e](https://github.com/ErikOnBike/d3-template/blob/master/src/template.js#L101)\n\nCreates a template from the specified *selection*. The selection might be changed as a result of this. Attributes or text consisting of template references will be removed. Child elements of an element containing a valid grouping attribute (`data-repeat`, `data-if` or `data-with`) will be removed. Different elements will have an attribute (`data-d3t7s` or `data-d3t7b`) applied for identification purposes.\n\nIf *options* is specified it should be an object containing properties describing the template attribute names being used. Only the properties that need custom values should be present. The following are the default options values:\n\n```Javascript\n{\n    repeatAttribute: \"data-repeat\",\n    ifAttribute: \"data-if\",\n    withAttribute: \"data-with\",\n    importAttribute: \"data-import\",\n    indirectAttributePrefix: \"data-attr-\",\n    indirectStylePrefix: \"data-style-\",\n    indirectPropertyPrefix: \"data-prop-\",\n    indirectClassPrefix: \"data-class-\"\n}\n```\n\n\u003ca name=\"render\" href=\"#render\"\u003e#\u003c/a\u003e d3.\u003cb\u003erender\u003c/b\u003e(\u003ci\u003eselection, data\u003c/i\u003e) [\u003c\u003e](https://github.com/ErikOnBike/d3-template/blob/master/src/template.js#L142)\n\nRenders *data* onto the specified *selection*. If no template has been created from *selection* an exception is thrown. If *selection* is part of a (larger) template and *selection* is a grouping element like `repeat`, `if`, `with` or `import` then rendering will be performed. Do remember that rendering on the template (root) will overwrite all template elements. So updating parts of a template should be done with caution.\n\n\u003ca name=\"selection_template\" href=\"#selection_template\"\u003e#\u003c/a\u003e \u003ci\u003eselection\u003c/i\u003e.\u003cb\u003etemplate\u003c/b\u003e(\u003ci\u003e[options]\u003c/i\u003e) [\u003c\u003e](https://github.com/ErikOnBike/d3-template/blob/master/src/template.js#L96)\n\nCreates a template from this *selection*. The following are all equivalent:\n\n```Javascript\nd3.template(selection, options);\nselection.template(options);\nselection.call(d3.template, options)\n```\n\n\u003ca name=\"selection_render\" href=\"#selection_render\"\u003e#\u003c/a\u003e \u003ci\u003eselection\u003c/i\u003e.\u003cb\u003erender\u003c/b\u003e(\u003ci\u003edata\u003c/i\u003e) [\u003c\u003e](https://github.com/ErikOnBike/d3-template/blob/master/src/template.js#L135)\n\nRenders *data* onto this *selection*. The following are all equivalent:\n\n```Javascript\nd3.render(selection, data);\nselection.render(data);\nselection.call(d3.render, data);\n```\n\n\u003ca name=\"transition_render\" href=\"#transition_render\"\u003e#\u003c/a\u003e \u003ci\u003etransition\u003c/i\u003e.\u003cb\u003erender\u003c/b\u003e(\u003ci\u003edata\u003c/i\u003e) [\u003c\u003e](https://github.com/ErikOnBike/d3-template/blob/master/src/template.js#L140)\n\nRenders *data* onto this *transition*. The following are all equivalent:\n\n```Javascript\nd3.render(transition, data);\ntransition.render(data);\ntransition.call(d3.render, data);\n```\n\n## \u003ca name=\"Details\"\u003eDetails\u003c/a\u003e\n\n### \u003ca name=\"Repeating-groups\"\u003eRepeating groups\u003c/a\u003e\n\nRepeating groups can only be used with arrays as data. The array will be bound to the element when rendered. The group's child element will be appended conform the regular D3 enter/exit pattern. A copy of the child element will be rendered for every array element provided. It will have the corresponding array element bound as data.\n\n```HTML\n\u003cul id=\"my-list\" data-repeat=\"{{d}}\"\u003e\n   \u003cli\u003e{{d}}\u003c/li\u003e\n\u003c/ul\u003e\n\u003cscript\u003e\n    var list = d3.select(\"#my-list\").template();\n\n    // Render a list containing the numbers 1 to 4\n    list.render([ 1, 2, 3, 4 ]);\n\n    // Render a list of words (replacing the numbers)\n    list.render([ \"Hello\", \"I\", \"Just\", \"Called\", \"To\", \"Say\", \"I\", \"Love\", \"You\" ]);\n\n    // Render an empty list (all existing li elements will be removed)\n    list.render([]);\n\u003c/script\u003e\n```\n\nTo use the index or length of the repeat group, use the D3 typical `i` or `nodes` parameters:\n\n```HTML\n\u003c!-- Insert index and position of element within repeat group --\u003e\n\u003cul data-repeat=\"{{d}}\"\u003e\n    \u003cli data-index=\"{{i}}\"\u003e\u003cspan\u003e{{`${i + 1} of ${nodes.length}`}}\u003c/span\u003e - \u003cspan\u003e{{d}}\u003c/span\u003e\u003c/li\u003e\n\u003c/ul\u003e\n```\n\n### \u003ca name=\"If-groups\"\u003eIf groups\u003c/a\u003e\n\nIf groups are conditional elements within a template. It allows a child element to be rendered (or not) based on a condition. If the condition expression evaluaties to a thruthy value, the child is rendered. Otherwise no child will be rendered (an existing child will be removed).\n\n```HTML\n\u003cdiv data-if=\"{{d.employees.length \u003e 0}}\"\u003e\n    \u003cdiv data-repeat=\"{{d.employees}}\"\u003e\n        \u003cdiv\u003e...\u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv data-if=\"{{d.employees.length === 0}}\"\u003e\n    \u003cdiv\u003eThere are no employees in this company.\u003c/div\u003e\n\u003c/div\u003e\n```\n\nAs can be seen in the example above, there is no `else` clause for if groups. Another approach would be to have a dynamic import which chooses the correct template.\n\n```HTML\n\u003cdiv id=\"templates\" style=\"display: none;\"\u003e\n    \u003cdiv id=\"employees\"\u003e\n        \u003cdiv data-repeat=\"{{d.employees}}\"\u003e\n            \u003cdiv\u003e...\u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv id=\"no-employees\"\u003e\n        \u003cdiv\u003eThere are no employees in this company.\u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"my-template\" data-import=\"{{d.employees.length \u003e 0 ? '#employees' : '#no-employees'}}\"\u003e\n        \u003c!-- No child elements allowed here! --\u003e\n\u003c/div\u003e\n```\n\n### \u003ca name=\"Import-templates\"\u003eImport templates\u003c/a\u003e\n\nIt is possible to import another template. The data bound to the element during rendering can be used to dynamically decide which template gets imported. The data function for the `data-import` attribute should answer either a (CSS) selector or a D3 selection. The element can not have children in the template (the imported template will render the child/children).\n\n```HTML\n\u003cdiv id=\"templates\" style=\"display: none;\"\u003e\n    \u003cdiv id=\"incoming-message\"\u003e\n        \u003cdiv\u003e\n            \u003cdiv\u003e{{`From: ${d.sender}`}}\u003c/div\u003e\n                \u003cdiv\u003e{{d.content}}\u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n        \u003cdiv id=\"outgoing-message\"\u003e\n            \u003cdiv\u003e{{d.content}}\u003c/div\u003e\n        \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"messenger\"\u003e\n    \u003cdiv class=\"list\" data-repeat=\"{{d}}\"\u003e\n        \u003cdiv data-import=\"{{d.sender === 'Me' ? '#outgoing-message' : '#incoming-message'}}\"\u003e\n            \u003c!-- No child elements allowed here! --\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\n    var messages = [\n        { sender: \"Someone\", content: \"Hello world\" },\n        { sender: \"Me\", content: \"Hello to you too\" },\n        { sender: \"Someone\", content: \"What are you doing?\" },\n        { sender: \"Me\", content: \"Writing a D3 template\" },\n        { sender: \"Someone\", content: \"That sounds interesting\" },\n        { sender: \"Someone\", content: \"I am already familiar with D3\" },\n        { sender: \"Someone\", content: \"Where can I learn about that?\" },\n        { sender: \"Me\", content: \"Check out the other examples\" }\n    ];\n\n    // Create templates from the two message types incoming and outgoing\n    d3.select(\"#incoming-message\").template();\n    d3.select(\"#outgoing-message\").template();\n    \n    // Create template from the messages group and render data\n    d3.select(\"#messenger\")\n        .template()\n        .render(messages)\n    ;\n\u003c/script\u003e\n```\n\nIn the example above templates have an `id` attribute. According to the HTML/SVG specifications these should be unqiue. These `id` attributes will therefore not be present when the template is rendered on an import. Only the original template will have it.\n\nAn import can be combined with `with` grouping to scope (or map) the data onto the imported template.\n\n```HTML\n\u003cdiv id=\"#templates\" style=\"display: none;\"\u003e\n    \u003cdiv id=\"person\"\u003e\n        \u003cdl\u003e\n            \u003cdt\u003eName\u003c/dt\u003e\u003cdd\u003e{{d.fullname}}\u003c/dd\u003e\n            \u003cdt\u003eEmail\u003c/dt\u003e\u003cdd\u003e{{d.email}}\u003c/dd\u003e\n        \u003c/dl\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv id=\"company\"\u003e\n    \u003ch1\u003e{{d.name}}\u003c/h1\u003e\n    \u003cdiv class=\"list\" data-repeat=\"{{d.employees}}\"\u003e\n        \u003cdiv data-import=\"{{'#person'}}\" data-with=\"{{employeeToPerson(d)}}\"\u003e\n            \u003c!-- No child elements allowed here! --\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript\u003e\n    // Function to convert employee to person\n    function employeeToPerson(employee) {\n        return {\n            fullname: employee.firstname + \" \" + employee.lastname,\n            email: employee.workEmail\n        };\n    }\n\n    // Create template (for importing)\n    d3.select(\"#person\").template();\n\n    // Create template and render data\n    d3.select(\"#company\")\n        .template()\n        .render({\n            name: \"Some company\",\n            employees: [\n                { firstname: \"Alan\", lastname: \"Turing\", workEmail: \"alan@some.com\", privateEmail: \"alan.turing@gmail.com\" },\n                { firstname: \"Alan\", lastname: \"Kay\", workEmail: \"alan2@some.com\", privateEmail: \"alan.kay@yahoo.com\" },\n                { firstname: \"Bret\", lastname: \"Victor\", workEmail: \"bret@some.com\", privateEmail: \"bret.victor@hotmail.com\" }\n            ] \n        })\n    ;\n```\n\n### \u003ca name=\"Transitions\"\u003eTransitions\u003c/a\u003e\n\nTransitions can be combined with rendering data onto a template. This allows for example SVG diagrams to transition from one shape to another. The general approach for rendering on a transition is the following:\n\n```Javascript\nselection\n    .transition()\n        .delay(100)\n        .duration(700)\n        .render(data)\n;\n```\n\n#### \u003ca name=\"tweenDataFunction\"\u003eTween data function\u003c/a\u003e\n\nSome data like text or strings do not animate well. Also sometimes a bit more control is needed on the way data is transitioned. In D3 there are tween functions for that. In d3-template these can be created by tagging a data function with the tag 'tween'.\n\n```HTML\n\u003cdiv id=\"tweenBlock\" data-style-background-color=\"{{tween:d3.interpolateRgb('white', d.color)}}\"\u003e\n    \u003cspan\u003e{{tween:textTween(d.text)}}\u003c/span\u003e\n\u003c/div\u003e\n\u003cscript\u003e\n    function textTween(d) {\n        return function(t) {\n            return d.substr(0, Math.floor(t * d.length));\n        };\n    }\n\n    d3.selection(\"#tweenBlock\")\n        .template()\n        .transition()\n            .delay(100)\n            .duration(700)\n            .render({ fill: \"red\", text: \"Hello world\" })\n    ;\n\u003c/script\u003e\n```\n\nThe tween data function should return a function accepting a single parameter `t` in accordance with the regular tween functions [attrTween](https://github.com/d3/d3-transition#transition_attrTween), [styleTween](https://github.com/d3/d3-transition#transition_styleTween) and/or [tween](https://github.com/d3/d3-transition#transition_tween).\n\nA tween data function is to be used in combination with rendering on a [transition](#transition_render). If a tween data function is specified within a template, but the render is performed without an active transition then the final tween result is rendered directly (ie the value returned by calling the tween data function with value `1.0`).\n\n### \u003ca name=\"Event-handlers\"\u003eEvent handlers\u003c/a\u003e\n\nIf event handlers are applied to a selection before a template is being created from it, these event handlers will be applied to the rendered result as well. When an event handler is called it will receive the normal D3 style arguments `d, i, nodes` and `this` will be set to the node receiving the event.\n\n```HTML\n\u003cul id=\"lang-list\" data-repeat=\"{{d}}\"\u003e\n    \u003cli\u003e{{d.english}}\u003c/li\u003e\n\u003c/ul\u003e\n\u003cscript\u003e\n    var list = d3.select(\"#lang-list\");\n\n    // Add event handler\n    list.select(\"li\").on(\"click\", function(d) {\n        window.alert(\"'\" + d.english + \"' translates into '\" + d.dutch + \"' for the Dutch language\");\n    });\n        \n    // Create template now that the event handlers are applied\n    list.template();\n\n    // Render words\n    var words = [\n        { english: \"one\", dutch: \"een\" },\n        { english: \"two\", dutch: \"twee\" },\n        { english: \"three\", dutch: \"drie\" },\n        { english: \"four\", dutch: \"vier\" }\n    ];\n    list.render(words);\n\n    // Clicking on a list element will show the alert specified \n\u003c/script\u003e\n```\n\n## \u003ca name=\"History\"\u003eHistory\u003c/a\u003e\n\nd3-template was created to remove some of the burden of having to create each and every DOM element when applying the enter/exit update pattern. For version 1 additional tooling was foreseen which would create data structures based on the templates. Work the other way around so to say. This did not work out as expected and adding the much needed filters did not help. So with version 2 the approach where the template expressions are fields (and filters) is dropped. Beginning with version 2 template expressions are Javascript expressions with parameters `d, i, nodes` defined as in D3 data functions. Version 1 code will break on the version 2 plugin. Sorry for any inconvenience. The new expressions should have a higher expressiveness and should be eassier to debug. As with version 1: hopefully this is a useful plugin for you.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FErikOnBike%2Fd3-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FErikOnBike%2Fd3-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FErikOnBike%2Fd3-template/lists"}