├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── css └── style.css ├── index.html ├── index.js ├── package.json ├── rollup.config.js └── src └── metatable.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build/ 3 | node_modules 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test/ 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | ## [1.0.1](https://github.com/mapbox/d3-metatable/compare/v1.0.0...v1.0.1) (2017-12-03) 7 | 8 | 9 | 10 | 11 | # [1.0.0](https://github.com/mapbox/d3-metatable/compare/v0.3.0...v1.0.0) (2017-11-27) 12 | 13 | 14 | ### Features 15 | 16 | * Compatibility with d3 v4 & ES6 modules ([33f7864](https://github.com/mapbox/d3-metatable/commit/33f7864)) 17 | 18 | 19 | ### BREAKING CHANGES 20 | 21 | * will no longer play well with d3 v3. 22 | 23 | 24 | 25 | ### v0.4.0 26 | 27 | - Interfaces like `renameCol`, `deleteCol`, and `newCol` can now be disabled 28 | if the option is passed in metatable. 29 | - Allow a client to pass in a custom interface for renaming or deleting a column. 30 | - HTML Markup cleanup 31 | - Adds `renameprompt` and `deleteprompt` events to disable default behaviour with users own. 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c), Mapbox 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | - Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | - Neither the name "Mapbox" nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## d3-metatable 2 | 3 | A table view component for [d3js](http://d3js.org/) designed for JSON 4 | objects of varying schemas. 5 | 6 | ### Example 7 | 8 | ```js 9 | container.append('div') 10 | .data([props]) 11 | .call( 12 | metatable() 13 | .on('change', function(d, i) { 14 | // a row's data is changed 15 | }) 16 | .on('rowfocus', function(d, i) { 17 | // a row is focused 18 | }) 19 | ``` 20 | 21 | ### API 22 | 23 | ```js 24 | metatable(options); 25 | ``` 26 | 27 | The `options` param should be an object and is optional. 28 | 29 | | property | default | description | 30 | | ---- | ---- | ---- | 31 | | newCol | true | Adds a link to add a new column to a table. | 32 | | deleteCol | true | Adds a link to rename a column in a table. | 33 | | renameCol | true | Adds a link to delete a column in a table. | 34 | 35 | A behavior that expects to be called with a selection an array of objects 36 | of data. Emits events: 37 | 38 | * `change`: a row is changed. returns the object and the index 39 | * `rowfocus`: a row is focused. returns the object and the index 40 | * `renameprompt`: Column is about to be renamed. Useful for passing in a custom workflow for submitting a value that overrides the default. usage: 41 | 42 | ``` js 43 | .on('renameprompt', function(d, process) { 44 | // Prevent the default prompt. 45 | this.preventprompt('rename'); 46 | 47 | // Do it your own way 48 | var newname = prompt('Rename column to:'); 49 | 50 | // Continue internally by passing the new name and current one. 51 | if (newname) process(newname, d); 52 | }); 53 | ``` 54 | 55 | * `deleteprompt`: Column is about to be deleted. Useful for passing in a custom workflow for delete confirmation to override the default one. usage: 56 | 57 | ``` js 58 | .on('deleteprompt', function(d, process) { 59 | // Prevent the default prompt. 60 | this.preventprompt('delete'); 61 | 62 | // Do it your own way 63 | if (confirm('Are you sure you want to delete ' + d + '?')) process(d); 64 | }); 65 | ``` 66 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | /* Reset ♥ 2 | http://meyerweb.com/eric/tools/css/reset/ 3 | v2.0 | 20110126 4 | License: none (public domain) 5 | ------------------------------------------------------- */ 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin:0; 20 | padding:0; 21 | border:0; 22 | font-size:100%; 23 | font:inherit; 24 | vertical-align:baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display:block; 30 | } 31 | body { line-height:1; } 32 | ol, ul { list-style:none; } 33 | blockquote, q { quotes:none; } 34 | blockquote:before, blockquote:after, 35 | q:before, q:after { content:''; content:none; } 36 | /* tables still need 'cellspacing="0"' in the markup */ 37 | table { border-collapse: collapse; border-spacing:0; } 38 | /* remember to define focus styles. Hee Haw */ 39 | :focus { outline:0; } 40 | 41 | /* Inline Elements & Typography 42 | ------------------------------------------------------- */ 43 | body, 44 | input, 45 | textarea { 46 | color:#333; 47 | font:15px/1.67 'Helvetica Neue', Helvetica, Arial, sans-serif; 48 | -webkit-font-smoothing:antialiased; 49 | } 50 | *, *:after, *:before { 51 | -webkit-box-sizing: border-box; 52 | -moz-box-sizing: border-box; 53 | box-sizing: border-box; 54 | } 55 | 56 | h1, 57 | h2, 58 | h3, 59 | h4, 60 | h5, 61 | h6 { 62 | margin:0; 63 | font-weight:bold; 64 | } 65 | 66 | h1 { 67 | font-size:32px; 68 | margin-bottom:20px; 69 | line-height:1em; 70 | } 71 | 72 | h2 { 73 | font-size:28px; 74 | margin-bottom:20px; 75 | line-height:1.25em; 76 | } 77 | 78 | h3 { 79 | font-size:20px; 80 | margin-bottom:20px; 81 | line-height:1.5em; 82 | } 83 | 84 | h4, h5 { 85 | font-size:15px; 86 | margin-bottom:0; 87 | line-height:1.67em; 88 | } 89 | 90 | p { 91 | margin:0 0 20px; 92 | } 93 | p:last-child { margin-bottom:0;} 94 | 95 | abbr { 96 | border-bottom:1px dotted #000; 97 | cursor:help; 98 | } 99 | 100 | address { font-style:italic;} 101 | small { font-size:11px;} 102 | strong { font-weight:bold;} 103 | em { font-style:italic;} 104 | 105 | hr { 106 | margin:0 0 20px; 107 | border:0; 108 | height:1px; 109 | background:#f8f8f8; 110 | } 111 | 112 | /* Block Quotes */ 113 | blockquote, 114 | q { 115 | quotes:none; 116 | font-style:italic; 117 | padding-left:20px; 118 | margin:10px; 119 | } 120 | 121 | blockquote:before, 122 | blockquote:after, 123 | q:before, 124 | q:after { 125 | content:''; 126 | } 127 | 128 | /* Code Blocks & Pre */ 129 | code, 130 | pre { 131 | padding:5px; 132 | font-family:Menlo, Bitstream Vera Sans Mono, Monaco, Consolas, monospace; 133 | font-size:12px; 134 | border-radius:3px; 135 | } 136 | code { 137 | padding:5px; 138 | background:#f8f8f8; 139 | border:1px solid #ddd; 140 | } 141 | pre { 142 | display:block; 143 | padding:10px; 144 | margin-bottom:10px; 145 | font-size:12px; 146 | word-break:break-all; 147 | word-wrap:break-word; 148 | white-space:pre; 149 | white-space:pre-wrap; 150 | background:#f8f8f8; 151 | border:1px solid #ddd; 152 | border-radius:3px; 153 | } 154 | pre code { 155 | padding:0; 156 | color:inherit; 157 | background-color:transparent; 158 | border:0; 159 | } 160 | .pre-scrollable { 161 | max-height:300px; 162 | overflow-y:scroll; 163 | } 164 | 165 | /* sub/superscripts */ 166 | sup, 167 | sub { 168 | height:0; 169 | line-height:1; 170 | vertical-align:baseline; 171 | _vertical-align:bottom; 172 | position:relative; 173 | font-size:75%; 174 | } 175 | sup { 176 | top:.5em; 177 | bottom:1em; 178 | } 179 | 180 | label { 181 | display:block; 182 | } 183 | select, 184 | textarea, 185 | input[type=text] { 186 | display:inline-block; 187 | height:30px; 188 | width:95%; 189 | max-width:400px; 190 | margin-bottom:10px; 191 | font-size:13px; 192 | font-weight:500; 193 | line-height:20px; 194 | color:#a0a0a0; 195 | vertical-align:middle; 196 | padding:4px 6px; 197 | -webkit-border-radius:1px; 198 | border-radius:1px; 199 | } 200 | textarea, 201 | input[type=text] { 202 | background-color:#fff; 203 | border:1px solid #ccc; 204 | -webkit-box-shadow:1px 1px 2px rgba(0,0,0,0.1); 205 | -moz-box-shadow:1px 1px 2px rgba(0,0,0,0.1); 206 | box-shadow:1px 1px 2px rgba(0,0,0,0.1); 207 | -webkit-transition:border linear .2s, box-shadow linear .2s; 208 | -moz-transition:border linear .2s, box-shadow linear .2s; 209 | -o-transition:border linear .2s, box-shadow linear .2s; 210 | transition:border linear .2s, box-shadow linear .2s; 211 | } 212 | textarea:focus, 213 | input[type=text]:focus { 214 | outline:thin dotted\8; /* ie8 below */ 215 | color:#404040; 216 | border-color:#00395D; 217 | border-width:1px; 218 | } 219 | 220 | textarea { 221 | height:200px; 222 | max-width:none; 223 | } 224 | input[type=submit] { 225 | background-color:#00395D; 226 | cursor:pointer; 227 | color:#fff; 228 | font-weight:bold; 229 | text-transform:uppercase; 230 | border:none; 231 | padding:9px 20px; 232 | -webkit-box-shadow:2px 2px 4px rgba(0,0,0,0.1); 233 | -moz-box-shadow:2px 2px 4px rgba(0,0,0,0.1); 234 | box-shadow:2px 2px 4px rgba(0,0,0,0.1); 235 | } 236 | input[type=submit]:hover { 237 | background-color:#002f4c; 238 | } 239 | input[type=submit]:active { 240 | position:relative; 241 | top:1px; 242 | } 243 | 244 | table { 245 | width:100%; 246 | background-color:transparent; 247 | border-collapse:collapse; 248 | border-spacing:0; 249 | margin-bottom:20px; 250 | table-layout:fixed; 251 | } 252 | th, 253 | td { 254 | padding:4px 0; 255 | line-height:20px; 256 | text-align:left; 257 | vertical-align:top; 258 | border-bottom:1px solid #d5d5d5; 259 | } 260 | th { 261 | font-weight:bold; 262 | } 263 | thead th { 264 | vertical-align:bottom; 265 | color:#57594D; 266 | } 267 | 268 | /* Read content styling */ 269 | .prose ul { 270 | list-style:disc; 271 | margin-left:40px; 272 | } 273 | .prose ol { 274 | list-style:decimal; 275 | } 276 | .prose p { 277 | margin:0 0 10px; 278 | } 279 | 280 | .icon { 281 | background:transparent url(img/sprite.png) no-repeat 0 0; 282 | display:block; 283 | width:30px; 284 | height:30px; 285 | text-indent:-999em; 286 | } 287 | 288 | /* Layout 289 | ------------------------------------------------------- */ 290 | .container { 291 | max-width:1600px; 292 | margin:0 auto; 293 | overflow:hidden; 294 | } 295 | 296 | /* Columns 297 | ------------------------------------------------------- */ 298 | .col0 { float:left; width:04.1666%; } 299 | .col1 { float:left; width:08.3333%; } 300 | .col2 { float:left; width:16.6666%; } 301 | .col3 { float:left; width:25.0000%; } 302 | .col4 { float:left; width:33.3333%; } 303 | .col5 { float:left; width:41.6666%; } 304 | .col6 { float:left; width:50.0000%; } 305 | .col7 { float:left; width:58.3333%; } 306 | .col8 { float:left; width:66.6666%; } 307 | .col9 { float:left; width:75.0000%; } 308 | .col10 { float:left; width:83.3333%; } 309 | .col11 { float:left; width:91.6666%; } 310 | .col12 { width:100%; } 311 | .margin0 { margin-left:04.1666%; } 312 | .margin1 { margin-left:08.3333%; } 313 | .margin2 { margin-left:16.6666%; } 314 | .margin3 { margin-left:25.0000%; } 315 | .margin4 { margin-left:33.3333%; } 316 | .margin5 { margin-left:41.6666%; } 317 | .margin6 { margin-left:50.0000%; } 318 | .margin7 { margin-left:58.3333%; } 319 | .margin8 { margin-left:66.6666%; } 320 | .margin9 { margin-left:75.0000%; } 321 | .margin10 { margin-left:83.3333%; } 322 | .margin11 { margin-left:91.6666%; } 323 | .margin12 { margin-left:100.0000%; } 324 | 325 | /* Padding 326 | ------------------------------------------------------- */ 327 | .pad1 { padding:10px; } 328 | .pad2 { padding:20px; } 329 | .pad21h { padding:10px 20px; } 330 | .pad2h { padding:0 20px; } 331 | .pad4 { padding:40px; } 332 | .pad4h { padding-left:40px; padding-right:40px; } 333 | .pad8 { padding:80px 40px; } 334 | .pad4c { padding:40px; } 335 | 336 | /* Additional Utility Classes 337 | ------------------------------------------------------- */ 338 | .fr { float:right; } 339 | .fl { float:left; } 340 | .show { display:block; } 341 | .hide { display:none; } 342 | .deemphasize { color:#888; } 343 | .center { text-align:center; } 344 | 345 | .tip-top:after, 346 | .tip-right:after, 347 | .tip-bottom:after, 348 | .tip-left:after { 349 | content:''; 350 | border-width:0 5px 5px; 351 | border-style:solid; 352 | position:absolute; 353 | border-color:#333 transparent; 354 | } 355 | .tip-bottom:after { 356 | border-width:5px 5px 0; 357 | } 358 | .tip-left:after { 359 | border-width:5px 5px 5px 0; 360 | border-color:transparent #333; 361 | } 362 | .tip-right:after { 363 | border-width:5px 0 5px 5px; 364 | } 365 | 366 | /* Markup free clearing 367 | Details: http://www.positioniseverything.net/easyclearing.html 368 | ------------------------------------------------------- */ 369 | .clearfix:after { 370 | content:'.'; 371 | display:block; 372 | height:0; 373 | clear:both; 374 | visibility:hidden; 375 | } 376 | 377 | .clearfix { display:inline-block; } 378 | 379 | /* Tablet Layout 380 | ------------------------------------------------------- */ 381 | @media only screen and (max-width:770px) { 382 | .hide-tablet { display:none; } 383 | .show-tablet { display:block; } 384 | } 385 | 386 | /* Mobile Layout 387 | ------------------------------------------------------- */ 388 | @media only screen and (max-width:640px) { 389 | .col1, 390 | .col2, 391 | .col3, 392 | .col4, 393 | .col5, 394 | .col6, 395 | .col7, 396 | .col8, 397 | .col9, 398 | .col10, 399 | .col11, 400 | .col12 { width:100%; max-width:100%; } 401 | .margin0, 402 | .margin1, 403 | .margin2, 404 | .margin3, 405 | .margin4, 406 | .margin5, 407 | .margin6, 408 | .margin7, 409 | .margin8, 410 | .margin9, 411 | .margin10, 412 | .margin11, 413 | .margin12 { margin-left:0; } 414 | .pad4c { padding:0; } 415 | .pad4, 416 | .pad4h { padding-left:20px; padding-right:20px; } 417 | .pad8 { padding:40px 20px; } 418 | .hide-mobile { display:none; } 419 | .show-mobile { display:block; } 420 | .icon { 421 | background-image:url(img/sprite@2x.png); 422 | background-size:240px 240px; 423 | } 424 | } 425 | 426 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 12 |A table interface for heterogeneous JSON collections.
19 | 20 | 21 |