├── .gitignore ├── make-jsdoc.sh ├── index.html ├── test ├── test-load.js ├── index.html ├── test-types.js ├── test-column.js ├── test-row.js ├── test-static.js ├── test-tagpattern.js ├── test-dataset.js └── test-filters.js ├── lib ├── qunit.LICENSE ├── papaparse.LICENSE ├── qunit-1.17.1.css └── papaparse.min.js ├── LICENSE.md ├── CHANGELOG ├── hxl-parse-hashtag.js ├── jsdoc ├── files.html ├── symbols │ ├── _global_.html │ ├── hxl.classes.html │ ├── hxl.classes.CacheFilter.html │ ├── hxl.classes.IndexFilter.html │ ├── hxl.classes.BaseFilter.html │ ├── hxl.classes.RenameFilter.html │ ├── hxl.classes.ColumnFilter.html │ ├── hxl.classes.RowFilter.html │ ├── hxl.classes.CountFilter.html │ ├── hxl.classes.Row.html │ ├── hxl.classes.Column.html │ ├── hxl.classes.Dataset.html │ └── hxl.classes.TagPattern.html └── index.html └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /make-jsdoc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf jsdoc 4 | mkdir jsdoc 5 | jsdoc --directory=jsdoc hxl.js 6 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | libhxl-js 5 | 6 | 7 |

libhxl-js

8 |

9 | A Javascript library for the Humanitarian Exchange Language 11 | data standard. 12 |

13 |
14 |

Resources

15 |
  • 16 | libhxl-js on GitHub 17 |
  • 18 |
  • 19 | API documentation 20 |
  • 21 |
  • 22 | Unit tests 23 |
  • 24 |
    25 | 26 | 27 | -------------------------------------------------------------------------------- /test/test-load.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | QUnit.module("hxl.load", { 4 | setup: function () { 5 | this.url = "https://raw.githubusercontent.com/HXLStandard/libhxl-js/main/test/test-data/sample-data.csv"; 6 | } 7 | }); 8 | 9 | QUnit.test("load dataset directly", function(assert) { 10 | var done = assert.async(); 11 | hxl.load(this.url, function (dataset) { 12 | assert.ok(dataset); 13 | assert.ok(dataset.columns.length > 5); 14 | done(); 15 | }); 16 | }); 17 | 18 | QUnit.test("load dataset via HXL Proxy", function(assert) { 19 | var done = assert.async(); 20 | hxl.proxy(this.url, function (dataset) { 21 | assert.ok(dataset); 22 | assert.ok(dataset.columns.length > 5); 23 | done(); 24 | }, true); 25 | }); 26 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | libhxl-js unit tests 6 | 7 | 8 | 9 |
    10 |
    11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/test-types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * hxl.classes.TagPattern tests 3 | */ 4 | 5 | QUnit.module("hxl.types", { 6 | setup: function () { 7 | // no-op 8 | } 9 | }); 10 | 11 | QUnit.test("is number", function(assert) { 12 | assert.ok(hxl.types.isNumber("100.0")); 13 | assert.ok(hxl.types.isNumber(100.0)); 14 | assert.ok(hxl.types.isNumber(" 100.0 ")); 15 | assert.ok(hxl.types.isNumber("1, 100 ")); 16 | 17 | assert.ok(!hxl.types.isNumber("foo")); 18 | }); 19 | 20 | QUnit.test("to number", function(assert) { 21 | assert.equal(100, hxl.types.toNumber("100.0")); 22 | assert.equal(100, hxl.types.toNumber(100.0)); 23 | assert.equal(100.1, hxl.types.toNumber("100.1")); 24 | assert.equal(1100, hxl.types.toNumber("1, 100 ")); 25 | 26 | assert.ok(isNaN(hxl.types.toNumber("foo"))); 27 | }); 28 | 29 | // end 30 | -------------------------------------------------------------------------------- /lib/qunit.LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Matthew Holt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /lib/papaparse.LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Matthew Holt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2021-05-25 Release 0.6 2 | - add support for object-style JSON 3 | - remove Source.getMatchingColumns() 4 | - add Source.getColumnIndex() and Source.getColumnIndices() 5 | - many speed optimisations 6 | 7 | 2021-05-07 Release 0.5 8 | - updated to eliminate complaints from ESLint 9 | - added getRawValues() method to get all the values in a dataset column (not just unique) 10 | 11 | 2021-04-27 Release 0.4.1 12 | - bug fix for reverse in sort filter 13 | 14 | 2021-04-27 Release 0.4 15 | - added standalone hxl-parse-hashtag.js module for visualisations, etc 16 | - added SortFilter and PreviewFilter, and corresponding hxl.Source.sort() and hxl.Source.preview() methods 17 | - added hxl.Source.sum() aggregation method 18 | 19 | 2019-03-29 Release 0.3 20 | - added hxl.Source.exportArray() to export data as an array 21 | including hashtags (and optionally, headers) 22 | - fix bug with null columns when there's no hashtag 23 | - start adding data typing methods 24 | - add support for wildcard tag patterns (e.g. "#*+f") 25 | - add support for absolute tag patterns (e.g. "#affected+children") 26 | - make hashtag specs and tag patterns case insensitive 27 | - added matchList() method to TagPattern class 28 | - add hxl.match() and hxl.matchList() convenience functions for 29 | matching tag patterns 30 | -------------------------------------------------------------------------------- /test/test-column.js: -------------------------------------------------------------------------------- 1 | /** 2 | * hxl.classes.Column tests 3 | */ 4 | 5 | QUnit.module("hxl.classes.Column", { 6 | setup: function () { 7 | this.column = hxl.classes.Column.parse("#adm1+code+pcode", "Region"); 8 | } 9 | }); 10 | 11 | QUnit.test("column created", function(assert) { 12 | assert.ok(this.column); 13 | }); 14 | 15 | QUnit.test("header ok", function(assert) { 16 | assert.equal(this.column.header, "Region"); 17 | }); 18 | 19 | QUnit.test("tag parsed", function(assert) { 20 | assert.equal(this.column.tag, "#adm1"); 21 | }); 22 | 23 | QUnit.test("attributes ok", function(assert) { 24 | assert.equal(this.column.attributes.length, 2); 25 | assert.ok(this.column.attributes.indexOf("code") > -1); 26 | assert.ok(this.column.attributes.indexOf("pcode") > -1); 27 | }); 28 | 29 | QUnit.test("display tag", function(assert) { 30 | assert.equal(this.column.displayTag, "#adm1+code+pcode"); 31 | }); 32 | 33 | QUnit.test("bad tag", function(assert) { 34 | // no exception 35 | assert.ok(hxl.classes.Column.parse("#0abc")); 36 | // exception 37 | var seen_exception = false; 38 | try { 39 | hxl.classes.Column.parse("#0abc", null, true); 40 | } catch (e) { 41 | seen_exception = true; 42 | } 43 | assert.ok(seen_exception); 44 | }); 45 | 46 | 47 | // end 48 | -------------------------------------------------------------------------------- /test/test-row.js: -------------------------------------------------------------------------------- 1 | /** 2 | * hxl.classes.Row tests 3 | */ 4 | 5 | QUnit.module("hxl.classes.Row", { 6 | setup: function () { 7 | this.columns = ["#org+funder", "#org+impl", "#adm1+code"]; 8 | this.values = ["Donor", "NGO", "Region"]; 9 | this.dataset = new hxl.classes.Dataset([this.columns, this.values]); 10 | this.row = new hxl.classes.Row(this.values, this.dataset.columns, this.dataset); 11 | } 12 | }); 13 | 14 | QUnit.test("row created", function(assert) { 15 | assert.ok(this.row); 16 | }); 17 | 18 | QUnit.test("values", function(assert) { 19 | assert.deepEqual(this.row.values, this.values); 20 | }); 21 | 22 | QUnit.test("columns", function(assert) { 23 | assert.deepEqual(this.row.columns.map(function(col) { return col.displayTag; }), this.columns); 24 | }); 25 | 26 | QUnit.test("get one value", function(assert) { 27 | assert.equal(this.row.get("#org"), "Donor"); 28 | assert.equal(this.row.get("#org+funder"), "Donor"); 29 | assert.equal(this.row.get("#org-funder"), "NGO"); 30 | assert.equal(this.row.get("#org+impl"), "NGO"); 31 | assert.equal(this.row.get("#org-impl"), "Donor"); 32 | }); 33 | 34 | QUnit.test("get all values", function(assert) { 35 | assert.deepEqual(this.row.getAll("#org"), ["Donor", "NGO"]); 36 | assert.deepEqual(this.row.getAll("#org+impl"), ["NGO"]); 37 | assert.deepEqual(this.row.getAll("#org-impl"), ["Donor"]); 38 | }); 39 | 40 | // end 41 | -------------------------------------------------------------------------------- /test/test-static.js: -------------------------------------------------------------------------------- 1 | /** 2 | * static methods tests 3 | */ 4 | 5 | QUnit.module("hxl", {}); 6 | 7 | QUnit.test("normalise whitespace", function(assert) { 8 | assert.equal("xx YY", hxl.normaliseSpace(" xx\n YY\t")); 9 | }); 10 | 11 | QUnit.test("normalise string", function(assert) { 12 | assert.equal("xx yy", hxl.normaliseString(" xx\n YY\t")); 13 | }); 14 | 15 | QUnit.test("normalise year", function(assert) { 16 | assert.equal('2017', hxl.normaliseDate('2017')); 17 | }); 18 | 19 | QUnit.test("normalise year-month", function(assert) { 20 | assert.equal('2017-01', hxl.normaliseDate('2017-01')); 21 | }); 22 | 23 | QUnit.test("normalise quarter", function(assert) { 24 | assert.equal('2017Q1', hxl.normaliseDate('2017Q1')); 25 | }); 26 | 27 | QUnit.test("normalise mm-dd date", function(assert) { 28 | assert.equal('2017-01-13', hxl.normaliseDate('1/13/17')); 29 | }); 30 | 31 | QUnit.test("normalise dd-mm date", function(assert) { 32 | assert.equal('2017-01-13', hxl.normaliseDate('13/1/17')); 33 | }); 34 | 35 | QUnit.test("force dd-mm date", function(assert) { 36 | assert.equal('2017-01-02', hxl.normaliseDate('2/1/17', true)); 37 | }); 38 | 39 | QUnit.test("force mm-dd date", function(assert) { 40 | assert.equal('2017-02-01', hxl.normaliseDate('2/1/17', false)); 41 | }); 42 | 43 | QUnit.test("month name", function(assert) { 44 | assert.equal('2017-01-02', hxl.normaliseDate('2 Jan/17')); 45 | }); 46 | 47 | // end 48 | -------------------------------------------------------------------------------- /hxl-parse-hashtag.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Stand-alone function to parse a HXL hashtag and attributes 3 | * 4 | * The result will be an object with two properties, "tag" for the 5 | * hashtag, and "atts" for an array of attributes. For example, 6 | * #affected+refugees+children+f will parse to 7 | * 8 | * { 9 | * tag: "affected", 10 | * atts: ["refugees", "children", "f"] 11 | * } 12 | * 13 | * Note that the parser removes "#" from the hashtag, and "+" from the 14 | * attribute names. It also normalised all names to lower case. 15 | * 16 | * To check for an attribute: 17 | * 18 | * p = hxl_parse_hashtag("#affected +refugees +children +f"); 19 | * p.atts.includes("refugees"); // true 20 | * p.atts.includes("idps"); // false 21 | * 22 | * @param s The hashtag and attributes (may contain whitespace) 23 | * @returns The parsed object, or False if the hashtag spec was 24 | * unparseable. 25 | */ 26 | function hxl_parse_hashtag (s) { 27 | 28 | var parsed = s.match(/^\s*(#[A-Za-z][A-Za-z0-9_]*)((\s*\+[A-Za-z][A-Za-z0-9_]*)*)?\s*$/); 29 | 30 | if (parsed) { 31 | var attributes = []; 32 | if (parsed[2]) { 33 | attributes = parsed[2].split(/\s*\+/).filter(attribute => attribute.toLowerCase()); 34 | } 35 | return { 36 | tag: parsed[1].toLowerCase().substring(1), 37 | atts: attributes 38 | }; 39 | 40 | } else { 41 | return False; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/test-tagpattern.js: -------------------------------------------------------------------------------- 1 | /** 2 | * hxl.classes.TagPattern tests 3 | */ 4 | 5 | QUnit.module("hxl.classes.TagPattern", { 6 | setup: function () { 7 | this.pattern = hxl.classes.TagPattern.parse("#adm1+code-iso"); 8 | this.column = hxl.classes.Column.parse("#adm1+code+pcode", "Region"); 9 | } 10 | }); 11 | 12 | QUnit.test("pattern created", function(assert) { 13 | assert.ok(this.pattern); 14 | }); 15 | 16 | QUnit.test("tag ok", function(assert) { 17 | assert.equal(this.pattern.tag, "#adm1"); 18 | }); 19 | 20 | QUnit.test("include ok", function(assert) { 21 | assert.deepEqual(this.pattern.includeAttributes, ['code']); 22 | }); 23 | 24 | QUnit.test("exclude ok", function(assert) { 25 | assert.deepEqual(this.pattern.excludeAttributes, ['iso']); 26 | }); 27 | 28 | QUnit.test("positive match", function(assert) { 29 | assert.ok(this.pattern.match(this.column)); 30 | }); 31 | 32 | QUnit.test("embedded whitespace", function(assert) { 33 | assert.ok(hxl.classes.TagPattern.parse('#adm1 +foo')); 34 | assert.ok(hxl.classes.TagPattern.parse(' #adm1+foo')); 35 | assert.ok(hxl.classes.TagPattern.parse(' #adm1+foo ')); 36 | assert.ok(hxl.classes.TagPattern.parse(' #adm1+foo ')); 37 | }); 38 | 39 | QUnit.test("bad pattern", function(assert) { 40 | // no exception 41 | assert.ok(hxl.classes.TagPattern.parse("#abc+x=y") === null); 42 | // exception requested 43 | var seen_exception = false; 44 | try { 45 | hxl.classes.TagPattern.parse("#abc+x=y", true); 46 | } catch (e) { 47 | seen_exception = true; 48 | } 49 | assert.ok(seen_exception); 50 | }); 51 | 52 | QUnit.test("absolute pattern", function(assert) { 53 | var pattern = hxl.classes.TagPattern.parse("#foo+x!"); 54 | assert.ok(pattern); 55 | assert.ok(pattern.match("#foo+x")); 56 | assert.ok(!pattern.match("#foo+y+x")) 57 | }); 58 | 59 | QUnit.test("wildcard pattern", function(assert) { 60 | var pattern = hxl.classes.TagPattern.parse("#*+x"); 61 | assert.ok(pattern); 62 | assert.ok(pattern.match("#foo+x")); 63 | assert.ok(!pattern.match("#foo")); 64 | }); 65 | 66 | QUnit.test("find in list", function(assert) { 67 | var pattern = hxl.classes.TagPattern.parse("#foo+x"); 68 | assert.ok(pattern.matchList(["#xxx", "#foo+y+x", "#yyy"])); 69 | assert.ok(!pattern.matchList(["#xxx", "#foo+y", "#yyy"])); 70 | }); 71 | 72 | // end 73 | -------------------------------------------------------------------------------- /test/test-dataset.js: -------------------------------------------------------------------------------- 1 | /** 2 | * hxl.classes.Dataset tests 3 | */ 4 | 5 | QUnit.module("hxl.classes.Dataset", { 6 | setup: function () { 7 | this.test_data = [ 8 | ['Pointless header'], 9 | ['Organisation', 'Second organisation', 'Sector', 'Province', 'Number reached'], 10 | ['#org', '#org', '#sector+cluster', '#adm1', '#reached'], 11 | ['Org 1', 'Org 1b', 'WASH', 'Coastal Province', '200'], 12 | ['Org 2', '', 'Health', 'Mountain Province', '300'], 13 | ['Org 3', '', 'Protection', 'Coastal Province', '400'] 14 | ]; 15 | this.dataset = new hxl.wrap(this.test_data); 16 | } 17 | }); 18 | 19 | QUnit.test("dataset created", function(assert) { 20 | assert.ok(this.dataset); 21 | }); 22 | 23 | QUnit.test("object-style JSON", function(assert) { 24 | let data = [ 25 | {'#org': 'Org 1', '#sector+cluster': 'WASH', '#adm1': 'Coastal Province', '#reached': '200'}, 26 | {'#org': 'Org 2', '#adm1': 'Mountain Province', '#reached': '300'}, 27 | {'#org': 'Org 3', '#reached': '400', '#sector+cluster': 'Protection', '#adm1': 'Coastal Province'} 28 | ]; 29 | dataset = hxl.wrap(data); 30 | assert.deepEqual(dataset.displayTags, ['#org', '#sector+cluster', '#adm1', '#reached']); 31 | assert.deepEqual(dataset.rawData, [ 32 | ["Org 1", "WASH", "Coastal Province", "200"], 33 | ["Org 2", "", "Mountain Province", "300"], 34 | ["Org 3", "Protection", "Coastal Province", "400"] 35 | ]); 36 | }); 37 | 38 | QUnit.test("headers", function(assert) { 39 | assert.deepEqual(this.dataset.headers, this.test_data[1]); 40 | }); 41 | 42 | QUnit.test("tags", function(assert) { 43 | assert.notDeepEqual(this.dataset.tags, this.test_data[2]); 44 | assert.deepEqual(this.dataset.displayTags, this.test_data[2]); 45 | }); 46 | 47 | QUnit.test("columns", function(assert) { 48 | assert.deepEqual(this.dataset.columns.map(function (col) { return col.header; }), this.test_data[1]); 49 | assert.deepEqual(this.dataset.columns.map(function (col) { return col.displayTag; }), this.test_data[2]); 50 | }); 51 | 52 | QUnit.test("dataset export", function(assert) { 53 | assert.deepEqual(this.dataset.exportArray(), this.test_data.slice(1)); 54 | assert.deepEqual(this.dataset.exportArray(false), this.test_data.slice(1)); 55 | assert.deepEqual(this.dataset.exportArray(true), this.test_data.slice(2)); 56 | }); 57 | 58 | QUnit.test("partly-tagged dataset", function(assert) { 59 | // confirm no null columns when not tagged 60 | var dataset = hxl.wrap([ 61 | ['header', 'header', 'header'], 62 | ['#tag', '', '#tag'], 63 | ['a', 'b', 'c'], 64 | ['d', 'e', 'f'] 65 | ]); 66 | dataset.columns.forEach((column) => { 67 | assert.ok(column); 68 | }); 69 | }); 70 | 71 | QUnit.test("rows", function(assert) { 72 | assert.deepEqual(this.dataset.rows.map(function (row) { return row.values; }), this.test_data.slice(3)); 73 | }); 74 | 75 | QUnit.test("raw data", function(assert) { 76 | assert.deepEqual(this.test_data.slice(3), this.dataset.rawData); 77 | }); 78 | 79 | QUnit.test("iterator", function(assert) { 80 | var iterator = this.dataset.iterator(); 81 | var index = 3; 82 | var row = null; 83 | while (row = iterator.next()) { 84 | assert.deepEqual(row.values, this.test_data[index]); 85 | index++; 86 | } 87 | }); 88 | 89 | QUnit.test("each", function(assert) { 90 | var test_data = this.test_data; 91 | assert.equal(this.dataset.each(function (row, dataset, rowNumber) { 92 | assert.deepEqual(row.values, test_data[rowNumber + 3]); 93 | }), 3); 94 | }); 95 | 96 | QUnit.test("min", function(assert) { 97 | assert.equal(this.dataset.getMin('#reached'), 200); 98 | }); 99 | 100 | QUnit.test("max", function(assert) { 101 | assert.equal(this.dataset.getMax('#reached'), 400); 102 | }); 103 | 104 | QUnit.test("sum", function(assert) { 105 | assert.equal(this.dataset.getSum('#reached'), 900); 106 | }); 107 | 108 | QUnit.test("unique values", function(assert) { 109 | assert.deepEqual(this.dataset.getValues('#adm1'), ['Coastal Province', 'Mountain Province']); 110 | }); 111 | 112 | QUnit.test("raw values", function(assert) { 113 | assert.deepEqual(this.dataset.getRawValues('#adm1'), ['Coastal Province', 'Mountain Province', 'Coastal Province']); 114 | }); 115 | 116 | QUnit.test("numbery", function(assert) { 117 | assert.ok(!this.dataset.isNumbery('#org')); 118 | assert.ok(this.dataset.isNumbery('#reached')); 119 | }); 120 | 121 | // end 122 | -------------------------------------------------------------------------------- /jsdoc/files.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | JsDoc Reference - File Index 8 | 9 | 10 | 174 | 175 | 176 | 177 | 179 | 180 |
    181 |
    Class Index 182 | | File Index
    183 |
    184 |

    Classes

    185 | 218 |
    219 |
    220 | 221 |
    222 |

    File Index

    223 | 224 | 225 |
    226 |

    hxl.js

    227 | 228 |
    229 | 230 | 231 | 232 | 233 |
    234 |
    235 |
    236 | 237 | 238 |
    239 |
    240 | 241 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 242 |
    243 | 244 | -------------------------------------------------------------------------------- /lib/qunit-1.17.1.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * QUnit 1.17.1 3 | * http://qunitjs.com/ 4 | * 5 | * Copyright jQuery Foundation and other contributors 6 | * Released under the MIT license 7 | * http://jquery.org/license 8 | * 9 | * Date: 2015-01-20T19:39Z 10 | */ 11 | 12 | /** Font Family and Sizes */ 13 | 14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 16 | } 17 | 18 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 19 | #qunit-tests { font-size: smaller; } 20 | 21 | 22 | /** Resets */ 23 | 24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 25 | margin: 0; 26 | padding: 0; 27 | } 28 | 29 | 30 | /** Header */ 31 | 32 | #qunit-header { 33 | padding: 0.5em 0 0.5em 1em; 34 | 35 | color: #8699A4; 36 | background-color: #0D3349; 37 | 38 | font-size: 1.5em; 39 | line-height: 1em; 40 | font-weight: 400; 41 | 42 | border-radius: 5px 5px 0 0; 43 | } 44 | 45 | #qunit-header a { 46 | text-decoration: none; 47 | color: #C2CCD1; 48 | } 49 | 50 | #qunit-header a:hover, 51 | #qunit-header a:focus { 52 | color: #FFF; 53 | } 54 | 55 | #qunit-testrunner-toolbar label { 56 | display: inline-block; 57 | padding: 0 0.5em 0 0.1em; 58 | } 59 | 60 | #qunit-banner { 61 | height: 5px; 62 | } 63 | 64 | #qunit-testrunner-toolbar { 65 | padding: 0.5em 1em 0.5em 1em; 66 | color: #5E740B; 67 | background-color: #EEE; 68 | overflow: hidden; 69 | } 70 | 71 | #qunit-userAgent { 72 | padding: 0.5em 1em 0.5em 1em; 73 | background-color: #2B81AF; 74 | color: #FFF; 75 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 76 | } 77 | 78 | #qunit-modulefilter-container { 79 | float: right; 80 | padding: 0.2em; 81 | } 82 | 83 | .qunit-url-config { 84 | display: inline-block; 85 | padding: 0.1em; 86 | } 87 | 88 | .qunit-filter { 89 | display: block; 90 | float: right; 91 | margin-left: 1em; 92 | } 93 | 94 | /** Tests: Pass/Fail */ 95 | 96 | #qunit-tests { 97 | list-style-position: inside; 98 | } 99 | 100 | #qunit-tests li { 101 | padding: 0.4em 1em 0.4em 1em; 102 | border-bottom: 1px solid #FFF; 103 | list-style-position: inside; 104 | } 105 | 106 | #qunit-tests > li { 107 | display: none; 108 | } 109 | 110 | #qunit-tests li.running, 111 | #qunit-tests li.pass, 112 | #qunit-tests li.fail, 113 | #qunit-tests li.skipped { 114 | display: list-item; 115 | } 116 | 117 | #qunit-tests.hidepass li.running, 118 | #qunit-tests.hidepass li.pass { 119 | display: none; 120 | } 121 | 122 | #qunit-tests li strong { 123 | cursor: pointer; 124 | } 125 | 126 | #qunit-tests li.skipped strong { 127 | cursor: default; 128 | } 129 | 130 | #qunit-tests li a { 131 | padding: 0.5em; 132 | color: #C2CCD1; 133 | text-decoration: none; 134 | } 135 | #qunit-tests li a:hover, 136 | #qunit-tests li a:focus { 137 | color: #000; 138 | } 139 | 140 | #qunit-tests li .runtime { 141 | float: right; 142 | font-size: smaller; 143 | } 144 | 145 | .qunit-assert-list { 146 | margin-top: 0.5em; 147 | padding: 0.5em; 148 | 149 | background-color: #FFF; 150 | 151 | border-radius: 5px; 152 | } 153 | 154 | .qunit-collapsed { 155 | display: none; 156 | } 157 | 158 | #qunit-tests table { 159 | border-collapse: collapse; 160 | margin-top: 0.2em; 161 | } 162 | 163 | #qunit-tests th { 164 | text-align: right; 165 | vertical-align: top; 166 | padding: 0 0.5em 0 0; 167 | } 168 | 169 | #qunit-tests td { 170 | vertical-align: top; 171 | } 172 | 173 | #qunit-tests pre { 174 | margin: 0; 175 | white-space: pre-wrap; 176 | word-wrap: break-word; 177 | } 178 | 179 | #qunit-tests del { 180 | background-color: #E0F2BE; 181 | color: #374E0C; 182 | text-decoration: none; 183 | } 184 | 185 | #qunit-tests ins { 186 | background-color: #FFCACA; 187 | color: #500; 188 | text-decoration: none; 189 | } 190 | 191 | /*** Test Counts */ 192 | 193 | #qunit-tests b.counts { color: #000; } 194 | #qunit-tests b.passed { color: #5E740B; } 195 | #qunit-tests b.failed { color: #710909; } 196 | 197 | #qunit-tests li li { 198 | padding: 5px; 199 | background-color: #FFF; 200 | border-bottom: none; 201 | list-style-position: inside; 202 | } 203 | 204 | /*** Passing Styles */ 205 | 206 | #qunit-tests li li.pass { 207 | color: #3C510C; 208 | background-color: #FFF; 209 | border-left: 10px solid #C6E746; 210 | } 211 | 212 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 213 | #qunit-tests .pass .test-name { color: #366097; } 214 | 215 | #qunit-tests .pass .test-actual, 216 | #qunit-tests .pass .test-expected { color: #999; } 217 | 218 | #qunit-banner.qunit-pass { background-color: #C6E746; } 219 | 220 | /*** Failing Styles */ 221 | 222 | #qunit-tests li li.fail { 223 | color: #710909; 224 | background-color: #FFF; 225 | border-left: 10px solid #EE5757; 226 | white-space: pre; 227 | } 228 | 229 | #qunit-tests > li:last-child { 230 | border-radius: 0 0 5px 5px; 231 | } 232 | 233 | #qunit-tests .fail { color: #000; background-color: #EE5757; } 234 | #qunit-tests .fail .test-name, 235 | #qunit-tests .fail .module-name { color: #000; } 236 | 237 | #qunit-tests .fail .test-actual { color: #EE5757; } 238 | #qunit-tests .fail .test-expected { color: #008000; } 239 | 240 | #qunit-banner.qunit-fail { background-color: #EE5757; } 241 | 242 | /*** Skipped tests */ 243 | 244 | #qunit-tests .skipped { 245 | background-color: #EBECE9; 246 | } 247 | 248 | #qunit-tests .qunit-skipped-label { 249 | background-color: #F4FF77; 250 | display: inline-block; 251 | font-style: normal; 252 | color: #366097; 253 | line-height: 1.8em; 254 | padding: 0 0.5em; 255 | margin: -0.4em 0.4em -0.4em 0; 256 | } 257 | 258 | /** Result */ 259 | 260 | #qunit-testresult { 261 | padding: 0.5em 1em 0.5em 1em; 262 | 263 | color: #2B81AF; 264 | background-color: #D2E0E6; 265 | 266 | border-bottom: 1px solid #FFF; 267 | } 268 | #qunit-testresult .module-name { 269 | font-weight: 700; 270 | } 271 | 272 | /** Fixture */ 273 | 274 | #qunit-fixture { 275 | position: absolute; 276 | top: -10000px; 277 | left: -10000px; 278 | width: 1000px; 279 | height: 1000px; 280 | } 281 | -------------------------------------------------------------------------------- /jsdoc/symbols/_global_.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - _global_ 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Built-In Namespace _global_ 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |

    243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 |
    268 |
    269 | 270 | 271 | 272 |
    273 | 274 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:52 GMT-0400 (EDT) 275 |
    276 | 277 | 278 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | libhxl-js 2 | ========= 3 | 4 | JavaScript support library for the Humanitarian Exchange Language (HXL) data standard. 5 | 6 | http://hxlstandard.org 7 | 8 | ## Overview 9 | 10 | This library supports high-level filtering and aggregation operations 11 | on HXL datasets. Auto-generated API documentation (which may or may 12 | not be up to date) is available at https://hxlstandard.github.io/libhxl-js/ 13 | 14 | ## Usage 15 | 16 | ### Load a CSV dataset from the web: 17 | 18 | Requires that the Papa Parse CSV library be loaded before HXL (there 19 | is a copy bundled in lib/, with permission): 20 | 21 | hxl.load('http://example.org/dataset.csv', function (dataset) { 22 | console.log('Dataset has ' + dataset.columns.length + ' columns.'); 23 | }); 24 | 25 | The HXL library will soon also support autodetecting the availability 26 | of D3 and JQuery-based CSV parsing. 27 | 28 | ### Create a dataset from array data 29 | 30 | var rawData = [ 31 | [ "Organisation", "Cluster", "Province" ], 32 | [ "#org", "#sector", "#adm1" ], 33 | [ "Org A", "WASH", "Coastal Province" ], 34 | [ "Org B", "Health", "Mountain Province" ], 35 | [ "Org C", "Education", "Coastal Province" ], 36 | [ "Org A", "WASH", "Plains Province" ], 37 | ]; 38 | 39 | var dataset = hxl.wrap(rawData); 40 | console.log('Dataset has ' + dataset.columns.length + ' columns'); 41 | 42 | ### Read a remote JSON-encoded HXL dataset 43 | 44 | fetch("http://example.org/data/sample.hxl.json").then(r => { 45 | r.json().then(rawData => { 46 | let dataset = hxl.wrap(rawData); 47 | console.log('Dataset has ' + dataset.columns.length + ' columns'); 48 | }); 49 | }); 50 | 51 | ## Classes 52 | 53 | ### hxl.classes.Source 54 | 55 | *Note:* Any method that takes a hxl.classes.TagPattern as an argument can accept a 56 | string representation instead (e.g. "#affected+f-adults"). Any method 57 | that takes a list of TagPatterns as an argument can accept a single 58 | pattern (as above) or list of patterns. 59 | 60 | #### Properties 61 | 62 | Property | Data type | Description 63 | -- | -- | -- 64 | columns | array of hxl.classes.Column | All the column objects for the dataset 65 | rows | array of hxl.classes.Row | All the row objects for the dataset (excluding header and hashtag row) 66 | rawData | array of arrays | Get all the raw row data for the dataset (excluding header and hashtag row) 67 | headers | array of strings | Get all the text headers as strings 68 | tags | array of strings | Get all the hashtags (without attributes) as strings 69 | displayTags | array of strings | Get all the hasthag specs (with attributes) as strings 70 | 71 | #### Row iteration methods 72 | 73 | Method | Description 74 | -- | -- | -- 75 | each(callback) | iterator through each row of the dataset, invoking _callback_ with the row, dataset, and row number as arguments 76 | forEach(callback) | synonym for _each()_ 77 | iterator() | return a simple iterator with a next() function (but not done(); it returns null when finished) 78 | 79 | #### Aggregate methods 80 | 81 | Use these methods to extract aggregate values from the dataset. 82 | 83 | Method | Result | Description 84 | -- | -- | -- 85 | getSum(tagPattern) | number | Sum of all numeric values in the first column matching _tagPattern_ 86 | getMin(tagPattern) | number | Lowest of all numeric values in the first column matching _tagPattern_ 87 | getMax(tagPattern) | number | Highest of all numeric values in the first column matching _tagPattern_ 88 | getValues(tagPattern) | array | List of unique values in the first column matching _tagPattern_ 89 | getRawValues(tagPattern) | array | List of all values in the first column matching _tagPattern_ (including repetitions and nulls), in the original order 90 | 91 | #### Filter methods 92 | 93 | The return value from a filter is always a new (virtual) dataset with the filter applied. 94 | 95 | Method | Description 96 | -- | -- 97 | withRows(predicates) | Include only rows matching (any of) _predicates_ 98 | withoutRows(predicates) | Include only rows _not_ matching (any of) _predicates_ 99 | withColumns(tagPatterns) | Include only columns matching (any of) _tagPatterns_ 100 | withoutColumns(tagPatterns) | Include only columns _not_ matching (any of) _tagPatterns_ 101 | count(tagPatterns, aggregate=null) | Aggregate data (like in a pivot table) for the columns matching _tagPatterns,_ and optionally produce aggregate values for the first column matching the tag pattern _aggregate_ 102 | rename(tagPattern, spec, header=null, index=0) | Rename the _index_ column matching _tagPattern_ to use the hashtag and attributes _spec_ and optionally the new header _header_ 103 | sort(tagPatterns, reverse=false) | Sort the dataset using columns matching tagPatterns as keys, with numeric comparison where possible 104 | preview(maxRows=10) | Filter to a maximum of _maxRows_ rows. 105 | catch() | Create a permanent copy of the data at this point in the pipeline, so that earlier filters don't have to be rerun. 106 | index() | Number repeated tag specs by adding the attributes +i0, +i1, etc to simplify processing. 107 | 108 | #### Other methods 109 | 110 | Method | Result | Description 111 | -- | -- | -- 112 | isNumbery(tagPattern) | boolean | Return true if the first column matching _tagPattern_ contains mainly numbers 113 | iterator() | object | Return a simple iterator with a next() method for reading through the rows (returns null at the end) 114 | exportArray() | array of arrays | Export the whole dataset as an array of arrays (including the headers and hashtag row) 115 | hasColumn(tagPattern) | boolean | true if the dataset has at least one column matching _tagPattern_ 116 | getMatchingColumns(tagPattern) | array of int | List of 0-based indices for columns matching _tagPattern_ 117 | 118 | 119 | ## Filter examples 120 | 121 | Filters create a new virtual version of the dataset, on the fly. The 122 | original dataset is unmodified. 123 | 124 | ### Column filtering 125 | 126 | #### Include only specific columns 127 | 128 | dataset.withColumns(['#org', '#sector', '#adm1']).each(...); 129 | 130 | #### Remove specific columns 131 | 132 | dataset.withoutColumns('#contact+email').each(...); 133 | 134 | ### Row filtering 135 | 136 | #### Include only specific rows 137 | 138 | dataset.withRows('#sector=WASH').each(...); 139 | 140 | #### Remove specific rows 141 | 142 | dataset.withoutRows('#status=Unreleased').each(...); 143 | 144 | #### Test an entire row 145 | 146 | dataset.withRows(function (row) { 147 | return row.get('#population+targeted+num') < row.get('#population+affected+num'); 148 | }).each(...); 149 | 150 | ### Aggregation 151 | 152 | #### Count values of #adm1 153 | 154 | dataset.count('#adm1').each(...); 155 | 156 | #### Count combinations of #adm1 and #sector 157 | 158 | dataset.count(['#adm1', '#sector']).each(...); 159 | 160 | ### Chain filters together 161 | 162 | Count #adm only in the WASH sector: 163 | 164 | dataset.withRows('#sector=WASH').count('#adm1').each(row => { 165 | // do something with each row 166 | }); 167 | 168 | or 169 | 170 | var iterator = dataset.iterator(); 171 | var row = iterator.next(); 172 | while (row != null) { 173 | // do something with each row 174 | row = iterator.next(); 175 | } 176 | 177 | 178 | ## Tests 179 | 180 | To run the unit tests, open the file tests/index.html in a modern web browser. You may need to install them in a web server to avoid cross-domain errors in browsers with strict security models. 181 | -------------------------------------------------------------------------------- /jsdoc/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | JsDoc Reference - Index 8 | 9 | 10 | 174 | 175 | 176 | 177 | 179 | 180 |
    181 |
    Class Index 182 | | File Index
    183 |
    184 |

    Classes

    185 | 218 |
    219 |
    220 | 221 |
    222 |

    Class Index

    223 | 224 | 225 |
    226 |

    _global_

    227 | 228 |
    229 |
    230 | 231 |
    232 |

    hxl

    233 | 234 |
    235 |
    236 | 237 |
    238 |

    hxl.classes

    239 | 240 |
    241 |
    242 | 243 |
    244 |

    hxl.classes.BaseFilter

    245 | 246 |
    247 |
    248 | 249 |
    250 |

    hxl.classes.CacheFilter

    251 | 252 |
    253 |
    254 | 255 |
    256 |

    hxl.classes.Column

    257 | 258 |
    259 |
    260 | 261 |
    262 |

    hxl.classes.ColumnFilter

    263 | 264 |
    265 |
    266 | 267 |
    268 |

    hxl.classes.CountFilter

    269 | 270 |
    271 |
    272 | 273 |
    274 |

    hxl.classes.Dataset

    275 | 276 |
    277 |
    278 | 279 |
    280 |

    hxl.classes.IndexFilter

    281 | 282 |
    283 |
    284 | 285 |
    286 |

    hxl.classes.RenameFilter

    287 | 288 |
    289 |
    290 | 291 |
    292 |

    hxl.classes.Row

    293 | 294 |
    295 |
    296 | 297 |
    298 |

    hxl.classes.RowFilter

    299 | 300 |
    301 |
    302 | 303 |
    304 |

    hxl.classes.Source

    305 | 306 |
    307 |
    308 | 309 |
    310 |

    hxl.classes.TagPattern

    311 | 312 |
    313 |
    314 | 315 | 316 |
    317 |
    318 | 319 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 320 |
    321 | 322 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Namespace hxl.classes 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Namespace Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes 262 |
    263 |
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 |
    281 |
    282 | Namespace Detail 283 |
    284 | 285 |
    286 | hxl.classes 287 |
    288 | 289 |
    290 | 291 | 292 |
    293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 |
    306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 |
    318 |
    319 | 320 | 321 | 322 |
    323 | 324 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:52 GMT-0400 (EDT) 325 |
    326 | 327 | 328 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.CacheFilter.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.CacheFilter 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.CacheFilter 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes.CacheFilter(source) 262 |
    263 |
    HXL filter to save a copy of a transformed HXL dataset.
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 |
    281 |
    282 | Class Detail 283 |
    284 | 285 |
    286 | hxl.classes.CacheFilter(source) 287 |
    288 | 289 |
    290 | HXL filter to save a copy of a transformed HXL dataset. 291 | 292 | This filter stops the chain, so that any future requests won't 293 | go back and repeat earlier transformations. You should use it 294 | when there are some expensive operations earlier in the chain 295 | that you don't want to repeat. 296 | 297 |
    298 | 299 | 300 | 301 | 302 | 303 |
    304 |
    Parameters:
    305 | 306 |
    307 | {hxl.classes.Source} source 308 | 309 |
    310 |
    the hxl.classes.Source
    311 | 312 |
    313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 |
    322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 |
    334 |
    335 | 336 | 337 | 338 |
    339 | 340 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 341 |
    342 | 343 | 344 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.IndexFilter.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.IndexFilter 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.IndexFilter 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes.IndexFilter(source, pattern) 262 |
    263 |
    Add index attributes (+i0, +i1, etc.
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 |
    281 |
    282 | Class Detail 283 |
    284 | 285 |
    286 | hxl.classes.IndexFilter(source, pattern) 287 |
    288 | 289 |
    290 | Add index attributes (+i0, +i1, etc.) to a repeated tag. 291 | 292 | This is useful for query-type processing, where it's not otherwise 293 | easy to work with order. Normally, it's better to use semantic 294 | attributes like #org+funder, #org+impl, etc., but in some cases, 295 | that's not available, so you can automatically number the tags 296 | as #org+i0, #org+i1, etc., from left to right. 297 | 298 |
    299 | 300 | 301 | 302 | 303 | 304 |
    305 |
    Parameters:
    306 | 307 |
    308 | {hxl.classes.Source} source 309 | 310 |
    311 |
    the hxl.classes.Source
    312 | 313 |
    314 | {string} pattern 315 | 316 |
    317 |
    the tag pattern to replace (see hxl.classes.TagPattern).
    318 | 319 |
    320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 |
    329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 |
    341 |
    342 | 343 | 344 | 345 |
    346 | 347 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 348 |
    349 | 350 | 351 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.BaseFilter.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.BaseFilter 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.BaseFilter 232 |

    233 | 234 | 235 |

    236 | 237 |
    Extends 238 | hxl.classes.Source.
    239 | 240 | 241 | 242 | 243 | 244 |
    Defined in: hxl.js. 245 | 246 |

    247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 267 | 268 | 269 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      262 |
    263 | hxl.classes.BaseFilter(source) 264 |
    265 |
    Abstract class for a HXL filter.
    266 |
    270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 |
    279 |
    Fields borrowed from class hxl.classes.Source:
    columns, displayTags, headers, rows, tags
    280 |
    281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 |
    291 |
    Methods borrowed from class hxl.classes.Source:
    cache, count, each, forEach, getColumns, getDisplayTags, getHeaders, getMatchingColumns, getMax, getMin, getRows, getTags, getValues, hasColumn, index, isNumbery, iterator, rename, withColumns, withoutColumns, withoutRows, withRows
    292 |
    293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 |
    301 |
    302 | Class Detail 303 |
    304 | 305 |
    306 | hxl.classes.BaseFilter(source) 307 |
    308 | 309 |
    310 | Abstract class for a HXL filter. 311 | 312 | Provide basic scaffolding for creating a class that reads from 313 | a HXL source, transforms the data on the fly, then sends out a new 314 | stream of HXL data. 315 | 316 |
    317 | 318 | 319 | 320 | 321 | 322 |
    323 |
    Parameters:
    324 | 325 |
    326 | {hxl.classes.Source} source 327 | 328 |
    329 |
    Another HXL data source to read from.
    330 | 331 |
    332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 |
    341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 |
    353 |
    354 | 355 | 356 | 357 |
    358 | 359 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:52 GMT-0400 (EDT) 360 |
    361 | 362 | 363 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.RenameFilter.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.RenameFilter 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.RenameFilter 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes.RenameFilter(source, pattern, newTag, newHeader, index) 262 |
    263 |
    HXL filter to rename a column (new header and tag).
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 294 | 295 | 296 | 297 | 298 | 303 | 304 | 305 | 306 |
    Method Summary
    Method AttributesMethod Name and Description
      290 |
    getColumns() 291 |
    292 |
    Get the renamed columns.
    293 |
      299 |
    iterator() 300 |
    301 |
    Return copies of the rows with the new columns.
    302 |
    307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 |
    317 |
    318 | Class Detail 319 |
    320 | 321 |
    322 | hxl.classes.RenameFilter(source, pattern, newTag, newHeader, index) 323 |
    324 | 325 |
    326 | HXL filter to rename a column (new header and tag). 327 | 328 |
    329 | 330 | 331 | 332 | 333 | 334 |
    335 |
    Parameters:
    336 | 337 |
    338 | source 339 | 340 |
    341 |
    the hxl.classes.Source
    342 | 343 |
    344 | pattern 345 | 346 |
    347 |
    the tag pattern to replace
    348 | 349 |
    350 | newTag 351 | 352 |
    353 |
    the new HXL tag (with attributes)
    354 | 355 |
    356 | newHeader 357 | 358 |
    359 |
    (optional) the new text header. If undefined or 360 | null or false, don't change the existing header.
    361 | 362 |
    363 | index 364 | 365 |
    366 |
    the zero-based index of the match to replace. If 367 | undefined or null or false, replace *all* matches.
    368 | 369 |
    370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 |
    379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 |
    387 | Method Detail 388 |
    389 | 390 | 391 |
    392 | 393 | 394 | getColumns() 395 | 396 |
    397 |
    398 | Get the renamed columns. 399 | 400 | 401 |
    402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 |
    414 | 415 | 416 |
    417 | 418 | 419 | iterator() 420 | 421 |
    422 |
    423 | Return copies of the rows with the new columns. 424 | 425 | 426 |
    427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 |
    446 |
    447 | 448 | 449 | 450 |
    451 | 452 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 453 |
    454 | 455 | 456 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.ColumnFilter.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.ColumnFilter 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.ColumnFilter 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes.ColumnFilter(source, patterns, invert) 262 |
    263 |
    HXL filter class to remove columns from a dataset.
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 294 | 295 | 296 | 297 | 298 | 303 | 304 | 305 | 306 |
    Method Summary
    Method AttributesMethod Name and Description
      290 |
    getColumns() 291 |
    292 |
    Override hxl.classes.BaseFilter.getColumns to return only the allowed columns.
    293 |
      299 |
    iterator() 300 |
    301 |
    Override hxl.classes.BaseFilter.iterator to get data with some columns removed.
    302 |
    307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 |
    317 |
    318 | Class Detail 319 |
    320 | 321 |
    322 | hxl.classes.ColumnFilter(source, patterns, invert) 323 |
    324 | 325 |
    326 | HXL filter class to remove columns from a dataset. 327 | 328 |
    329 | 330 | 331 | 332 | 333 | 334 |
    335 |
    Parameters:
    336 | 337 |
    338 | source 339 | 340 |
    341 |
    the HXL data source (may be another filter).
    342 | 343 |
    344 | patterns 345 | 346 |
    347 |
    a list of HXL tag patterns to include (or exclude).
    348 | 349 |
    350 | invert 351 | 352 |
    353 |
    if true, exclude matching columns rather than including them (blacklist).
    354 | 355 |
    356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 |
    365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 |
    373 | Method Detail 374 |
    375 | 376 | 377 |
    378 | 379 | 380 | getColumns() 381 | 382 |
    383 |
    384 | Override hxl.classes.BaseFilter.getColumns to return only the allowed columns. 385 | 386 | This method triggers lazy processing that also saves the indices for 387 | slicing the data itself. 388 | 389 | 390 |
    391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 |
    400 |
    Returns:
    401 | 402 |
    a list of hxl.classes.Column objects.
    403 | 404 |
    405 | 406 | 407 | 408 | 409 |
    410 | 411 | 412 |
    413 | 414 | 415 | iterator() 416 | 417 |
    418 |
    419 | Override hxl.classes.BaseFilter.iterator to get data with some columns removed. 420 | 421 | 422 |
    423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 |
    432 |
    Returns:
    433 | 434 |
    an iterator object to read the modified data rows.
    435 | 436 |
    437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 |
    449 |
    450 | 451 | 452 | 453 |
    454 | 455 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 456 |
    457 | 458 | 459 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.RowFilter.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.RowFilter 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.RowFilter 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes.RowFilter(source, predicates, invert) 262 |
    263 |
    HXL filter class to select rows from a source.
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 292 | 293 | 294 | 295 |
    Field Summary
    Field AttributesField Name and Description
    <static>   287 |
    288 | hxl.classes.RowFilter.OPERATORS 289 |
    290 |
    Operator functions.
    291 |
    296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 323 | 324 | 325 |
    Method Summary
    Method AttributesMethod Name and Description
      318 |
    iterator() 319 |
    320 |
    Override HXLFIlter.iterator to return only select rows.
    321 |
    326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 |
    336 |
    337 | Class Detail 338 |
    339 | 340 |
    341 | hxl.classes.RowFilter(source, predicates, invert) 342 |
    343 | 344 |
    345 | HXL filter class to select rows from a source. 346 | 347 | Usage: 348 | 349 | // select all rows where #adm1 is the Coastal Region 350 | // *or* the population is greater than 1,000 351 | var filter = new hxl.classes.RowFilter(source, 352 | { pattern: '#adm1', test: 'Coastal Region' }, 353 | { pattern: '#people_num', test: function(v) { return v > 1000; } } 354 | ]); 355 | 356 | Predicates are always "OR"'d together. If you need 357 | a logical "AND", then chain another select filter. 358 | 359 |
    360 | 361 | 362 | 363 | 364 | 365 |
    366 |
    Parameters:
    367 | 368 |
    369 | source 370 | 371 |
    372 |
    the hxl.classes.Source
    373 | 374 |
    375 | predicates 376 | 377 |
    378 |
    a list of predicates, each of 379 | has a "test" property (and optionally, a "pattern" property).
    380 | 381 |
    382 | invert 383 | 384 |
    385 |
    386 | 387 |
    388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 |
    397 | 398 | 399 | 400 | 401 |
    402 | Field Detail 403 |
    404 | 405 | 406 |
    <static> 407 | 408 | 409 | hxl.classes.RowFilter.OPERATORS 410 | 411 |
    412 |
    413 | Operator functions. 414 | 415 | 416 |
    417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 |
    432 | Method Detail 433 |
    434 | 435 | 436 |
    437 | 438 | 439 | iterator() 440 | 441 |
    442 |
    443 | Override HXLFIlter.iterator to return only select rows. 444 | 445 | 446 |
    447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 |
    456 |
    Returns:
    457 | 458 |
    an iterator object that will skip rows that fail to pass at 459 | least one of the predicates.
    460 | 461 |
    462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 |
    474 |
    475 | 476 | 477 | 478 |
    479 | 480 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 481 |
    482 | 483 | 484 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.CountFilter.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.CountFilter 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.CountFilter 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes.CountFilter(source, patterns, aggregate) 262 |
    263 |
    HXL filter to count and aggregate data.
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 294 | 295 | 296 | 297 | 298 | 303 | 304 | 305 | 306 |
    Method Summary
    Method AttributesMethod Name and Description
      290 |
    getColumns() 291 |
    292 |
    Override hxl.classes.BaseFilter.getColumns to return only the columns for the aggregation report.
    293 |
      299 |
    iterator() 300 |
    301 |
    Override hxl.classes.BaseFilter.iterator to return a set of rows with aggregated values.
    302 |
    307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 |
    317 |
    318 | Class Detail 319 |
    320 | 321 |
    322 | hxl.classes.CountFilter(source, patterns, aggregate) 323 |
    324 | 325 |
    326 | HXL filter to count and aggregate data. 327 | 328 | By default, this filter put out a dataset with the selected tags 329 | and a new tag #meta+count giving the number of times each 330 | combination of values appears. If the aggregate tag pattern is 331 | present, the filter will also produce a column with the sum, 332 | average (mean), minimum, and maximum values for the tag, attaching 333 | the attributes +sum, +avg, +min, and +max to the core tag. 334 | 335 |
    336 | 337 | 338 | 339 | 340 | 341 |
    342 |
    Parameters:
    343 | 344 |
    345 | source 346 | 347 |
    348 |
    the HXL data source (may be another filter).
    349 | 350 |
    351 | patterns 352 | 353 |
    354 |
    a list of tag patterns (strings or hxl.classes.TagPattern 355 | objects) whose values make up a shared key.
    356 | 357 |
    358 | aggregate 359 | 360 |
    361 |
    362 | 363 |
    364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 |
    373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 |
    381 | Method Detail 382 |
    383 | 384 | 385 |
    386 | 387 | 388 | getColumns() 389 | 390 |
    391 |
    392 | Override hxl.classes.BaseFilter.getColumns to return only the columns for the aggregation report. 393 | 394 | Will list the tags that match the patterns provided in the 395 | constructor, as well as a #meta+count tag, and aggregation tags if 396 | the aggregation parameter was included. 397 | 398 | 399 |
    400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 |
    409 |
    Returns:
    410 | 411 |
    a list of hxl.classes.Column objects
    412 | 413 |
    414 | 415 | 416 | 417 | 418 |
    419 | 420 | 421 |
    422 | 423 | 424 | iterator() 425 | 426 |
    427 |
    428 | Override hxl.classes.BaseFilter.iterator to return a set of rows with aggregated values. 429 | 430 | Each row represents a unique set of values and the number of times 431 | it occurs. 432 | 433 | 434 |
    435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 |
    444 |
    Returns:
    445 | 446 |
    an iterator over the aggregated data.
    447 | 448 |
    449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 |
    461 |
    462 | 463 | 464 | 465 |
    466 | 467 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 468 |
    469 | 470 | 471 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.Row.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.Row 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.Row 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes.Row(values, columns) 262 |
    263 |
    Wrapper for a row of HXL data.
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 294 | 295 | 296 | 297 | 298 | 303 | 304 | 305 | 306 | 307 | 312 | 313 | 314 | 315 |
    Method Summary
    Method AttributesMethod Name and Description
      290 |
    clone() 291 |
    292 |
    Make a deep copy of a row's values (not the columns).
    293 |
      299 |
    get(pattern) 300 |
    301 |
    Look up the first value that matches a tag pattern.
    302 |
      308 |
    getAll(pattern) 309 |
    310 |
    Look up all values that match a tag pattern.
    311 |
    316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 |
    326 |
    327 | Class Detail 328 |
    329 | 330 |
    331 | hxl.classes.Row(values, columns) 332 |
    333 | 334 |
    335 | Wrapper for a row of HXL data. 336 | 337 |
    338 | 339 | 340 | 341 | 342 | 343 |
    344 |
    Parameters:
    345 | 346 |
    347 | values 348 | 349 |
    350 |
    351 | 352 |
    353 | columns 354 | 355 |
    356 |
    357 | 358 |
    359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 |
    368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 |
    376 | Method Detail 377 |
    378 | 379 | 380 |
    381 | 382 | {hxl.classes.Row} 383 | clone() 384 | 385 |
    386 |
    387 | Make a deep copy of a row's values (not the columns). 388 | 389 | This method is especially useful for filters. 390 | 391 | 392 |
    393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 |
    402 |
    Returns:
    403 | 404 |
    {hxl.classes.Row} a new row object.
    405 | 406 |
    407 | 408 | 409 | 410 | 411 |
    412 | 413 | 414 |
    415 | 416 | 417 | get(pattern) 418 | 419 |
    420 |
    421 | Look up the first value that matches a tag pattern. 422 | 423 | 424 |
    425 | 426 | 427 | 428 | 429 |
    430 |
    Parameters:
    431 | 432 |
    433 | pattern 434 | 435 |
    436 |
    The tag pattern to use.
    437 | 438 |
    439 | 440 | 441 | 442 | 443 | 444 |
    445 |
    Returns:
    446 | 447 |
    a string value, or null if none found.
    448 | 449 |
    450 | 451 | 452 | 453 | 454 |
    455 | 456 | 457 |
    458 | 459 | 460 | getAll(pattern) 461 | 462 |
    463 |
    464 | Look up all values that match a tag pattern. 465 | 466 | 467 |
    468 | 469 | 470 | 471 | 472 |
    473 |
    Parameters:
    474 | 475 |
    476 | pattern 477 | 478 |
    479 |
    The tag pattern to use.
    480 | 481 |
    482 | 483 | 484 | 485 | 486 | 487 |
    488 |
    Returns:
    489 | 490 |
    a possibly-empty array of string values (or nulls).
    491 | 492 |
    493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 |
    505 |
    506 | 507 | 508 | 509 |
    510 | 511 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 512 |
    513 | 514 | 515 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.Column.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.Column 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.Column 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes.Column(tag, attributes, header) 262 |
    263 |
    Wrapper for a HXL column definition.
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 294 | 295 | 296 | 297 | 298 | 303 | 304 | 305 | 306 | 307 | 312 | 313 | 314 | 315 |
    Method Summary
    Method AttributesMethod Name and Description
      290 |
    clone() 291 |
    292 |
    Create a deep copy of this column spec.
    293 |
      299 |
    getDisplayTag() 300 |
    301 |
    Create a display tagspec for the column.
    302 |
    <static>   308 |
    hxl.classes.Column.parse(spec, header, useException) 309 |
    310 |
    Parse a tag spec into its parts.
    311 |
    316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 |
    326 |
    327 | Class Detail 328 |
    329 | 330 |
    331 | hxl.classes.Column(tag, attributes, header) 332 |
    333 | 334 |
    335 | Wrapper for a HXL column definition. 336 | 337 |
    338 | 339 | 340 | 341 | 342 | 343 |
    344 |
    Parameters:
    345 | 346 |
    347 | tag 348 | 349 |
    350 |
    351 | 352 |
    353 | attributes 354 | 355 |
    356 |
    357 | 358 |
    359 | header 360 | 361 |
    362 |
    363 | 364 |
    365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 |
    373 |
    See:
    374 | 375 |
    hxl.classes.TagPattern
    376 | 377 |
    378 | 379 | 380 |
    381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 |
    389 | Method Detail 390 |
    391 | 392 | 393 |
    394 | 395 | {hxl.classes.Column} 396 | clone() 397 | 398 |
    399 |
    400 | Create a deep copy of this column spec. 401 | 402 | This method is mainly useful for filters that want to modify a column. 403 | 404 | 405 |
    406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 |
    415 |
    Returns:
    416 | 417 |
    {hxl.classes.Column} A deep copy of this columns spec.
    418 | 419 |
    420 | 421 | 422 | 423 | 424 |
    425 | 426 | 427 |
    428 | 429 | 430 | getDisplayTag() 431 | 432 |
    433 |
    434 | Create a display tagspec for the column. 435 | 436 | 437 |
    438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 |
    450 | 451 | 452 |
    <static> 453 | 454 | 455 | hxl.classes.Column.parse(spec, header, useException) 456 | 457 |
    458 |
    459 | Parse a tag spec into its parts. 460 | 461 | 462 |
    463 | 464 | 465 | 466 | 467 |
    468 |
    Parameters:
    469 | 470 |
    471 | spec 472 | 473 |
    474 |
    475 | 476 |
    477 | header 478 | 479 |
    480 |
    481 | 482 |
    483 | useException 484 | 485 |
    486 |
    487 | 488 |
    489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 |
    505 |
    506 | 507 | 508 | 509 |
    510 | 511 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 512 |
    513 | 514 | 515 | -------------------------------------------------------------------------------- /jsdoc/symbols/hxl.classes.Dataset.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.Dataset 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 |
    Class Index 187 | | File Index
    188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.Dataset 232 |

    233 | 234 | 235 |

    236 | 237 |
    Extends 238 | hxl.classes.Source.
    239 | 240 | 241 | 242 | 243 | 244 |
    Defined in: hxl.js. 245 | 246 |

    247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 268 | 269 | 270 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      262 |
    263 | hxl.classes.Dataset(rawData) 264 |
    265 |
    An original HXL dataset (including the raw data) 266 | Derived from hxl.classes.Source
    267 |
    271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 |
    280 |
    Fields borrowed from class hxl.classes.Source:
    columns, displayTags, headers, rows, tags
    281 |
    282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 306 | 307 | 308 | 309 | 310 | 315 | 316 | 317 | 318 |
    Method Summary
    Method AttributesMethod Name and Description
      302 |
    getColumns() 303 |
    304 |
    Get an array of column definitions.
    305 |
      311 |
    iterator() 312 |
    313 |
    Get an iterator through all the rows in the dataset.
    314 |
    319 | 320 | 321 | 322 |
    323 |
    Methods borrowed from class hxl.classes.Source:
    cache, count, each, forEach, getDisplayTags, getHeaders, getMatchingColumns, getMax, getMin, getRows, getTags, getValues, hasColumn, index, isNumbery, rename, withColumns, withoutColumns, withoutRows, withRows
    324 |
    325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 |
    333 |
    334 | Class Detail 335 |
    336 | 337 |
    338 | hxl.classes.Dataset(rawData) 339 |
    340 | 341 |
    342 | An original HXL dataset (including the raw data) 343 | Derived from hxl.classes.Source 344 | 345 |
    346 | 347 | 348 | 349 | 350 | 351 |
    352 |
    Parameters:
    353 | 354 |
    355 | {array} rawData 356 | 357 |
    358 |
    An array of arrays of raw strings (tabular).
    359 | 360 |
    361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 |
    370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 |
    378 | Method Detail 379 |
    380 | 381 | 382 |
    383 | 384 | 385 | getColumns() 386 | 387 |
    388 |
    389 | Get an array of column definitions. 390 | 391 | 392 |
    393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 |
    405 | 406 | 407 |
    408 | 409 | 410 | iterator() 411 | 412 |
    413 |
    414 | Get an iterator through all the rows in the dataset. 415 | 416 | 417 |
    418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 |
    437 |
    438 | 439 | 440 | 441 |
    442 | 443 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 444 |
    445 | 446 | 447 | -------------------------------------------------------------------------------- /test/test-filters.js: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////// 2 | // Test various HXL filters 3 | //////////////////////////////////////////////////////////////////////// 4 | 5 | // 6 | // hxl.classes.BaseFilter 7 | // 8 | 9 | QUnit.module("hxl.classes.BaseFilters", { 10 | setup: function () { 11 | this.test_data = [ 12 | ['Pointless header'], 13 | ['Organisation', 'Second organisation', 'Sector', 'Province', 'Targeted'], 14 | ['#org', '#org', '#sector+cluster', '#adm1+name', '#population+num'], 15 | ['Org 1', 'Org 1a', 'WASH', 'Coastal Province', '300'], 16 | ['Org 2', '', 'Health', 'Mountain Province', '400'], 17 | ['Org 3', '', 'Protection', 'Coastal Province', '500'] 18 | ]; 19 | this.dataset = hxl.wrap(this.test_data); 20 | } 21 | }); 22 | 23 | QUnit.test("identity filter", function(assert) { 24 | var filter = new hxl.classes.BaseFilter(this.dataset); 25 | assert.deepEqual(filter.columns, this.dataset.columns); 26 | assert.deepEqual(filter.rows, this.dataset.rows); 27 | }); 28 | 29 | 30 | // 31 | // hxl.classes.RowFilter 32 | // 33 | 34 | QUnit.test("row filter value string predicate", function(assert) { 35 | var predicates = [ 36 | { pattern: '#adm1-code', test: 'Coastal Province'} 37 | ]; 38 | var filter = new hxl.classes.RowFilter(this.dataset, predicates); 39 | assert.deepEqual(filter.columns, this.dataset.columns); 40 | assert.equal(filter.rows.length, 2); 41 | assert.deepEqual(filter.getValues('#adm1'), ['Coastal Province']); 42 | 43 | // test convenience methods 44 | assert.deepEqual(filter.columns, this.dataset.withRows(predicates).columns); 45 | assert.deepEqual(filter.rows, this.dataset.withRows(predicates).rows); 46 | }); 47 | 48 | QUnit.test("row filter predicate parsing", function(assert) { 49 | assert.deepEqual( 50 | this.dataset.withRows(' #adm1-foo =Coastal Province').getValues('#adm1'), 51 | ['Coastal Province'] 52 | ); 53 | assert.deepEqual( 54 | this.dataset.withRows('#adm1+name!=Coastal Province').getValues('#adm1'), 55 | ['Mountain Province'] 56 | ); 57 | assert.deepEqual( 58 | this.dataset.withRows('#population<400').getValues('#org'), 59 | ['Org 1'] 60 | ); 61 | assert.deepEqual( 62 | this.dataset.withRows('#population<=400').getValues('#org'), 63 | ['Org 1', 'Org 2'] 64 | ); 65 | assert.deepEqual( 66 | this.dataset.withRows('#population>400').getValues('#org'), 67 | ['Org 3'] 68 | ); 69 | assert.deepEqual( 70 | this.dataset.withRows('#population>=400').getValues('#org'), 71 | ['Org 2', 'Org 3'] 72 | ); 73 | assert.deepEqual( 74 | this.dataset.withRows('#adm1~^Coast').getValues('#org'), 75 | ['Org 1', 'Org 3'] 76 | ); 77 | assert.deepEqual( 78 | this.dataset.withRows('#adm1!~^Coast').getValues('#org'), 79 | ['Org 2'] 80 | ); 81 | }); 82 | 83 | QUnit.test("row filter invert", function(assert) { 84 | var predicates = [ 85 | { pattern: '#adm1', test: 'Coastal Province'} 86 | ]; 87 | var filter = new hxl.classes.RowFilter(this.dataset, predicates, true); 88 | assert.deepEqual(filter.columns, this.dataset.columns); 89 | assert.equal(filter.rows.length, 1); 90 | assert.deepEqual(filter.getValues('#adm1'), ['Mountain Province']); 91 | 92 | // test convenience methods 93 | assert.deepEqual(filter.columns, this.dataset.withoutRows(predicates).columns); 94 | assert.deepEqual(filter.rows, this.dataset.withoutRows(predicates).rows); 95 | }); 96 | 97 | QUnit.test("row filter normalised strings", function(assert) { 98 | assert.deepEqual(this.dataset.withRows('#adm1= coastal province ').getValues('#org'), ['Org 1', 'Org 3']); 99 | }); 100 | 101 | QUnit.test("row filter value function predicate", function(assert) { 102 | var test_function = function(value) { return value != 'Protection'; }; 103 | var predicates = [ 104 | { 105 | pattern: '#sector+cluster', 106 | test: test_function 107 | } 108 | ]; 109 | var filter = new hxl.classes.RowFilter(this.dataset, predicates); 110 | assert.equal(filter.rows.length, 2); 111 | assert.deepEqual(filter.getValues('#sector'), ['WASH', 'Health']); 112 | 113 | // test convenience methods 114 | assert.deepEqual(filter.columns, this.dataset.withRows(predicates).columns); 115 | assert.deepEqual(filter.rows, this.dataset.withRows(predicates).rows); 116 | }); 117 | 118 | QUnit.test("row filter row predicate", function(assert) { 119 | var test_function = function(row) { return (row.get('#org') == 'Org 1' && row.get('#adm1') == 'Coastal Province'); }; 120 | var predicates = [ 121 | { 122 | test: test_function 123 | } 124 | ]; 125 | var filter = new hxl.classes.RowFilter(this.dataset, predicates); 126 | assert.equal(filter.rows.length, 1); 127 | 128 | // test convenience methods 129 | assert.deepEqual(filter.columns, this.dataset.withRows(predicates).columns); 130 | assert.deepEqual(filter.rows, this.dataset.withRows(predicates).rows); 131 | assert.deepEqual(filter.columns, this.dataset.withRows(test_function).columns); 132 | assert.deepEqual(filter.rows, this.dataset.withRows(test_function).rows); 133 | }); 134 | 135 | 136 | // 137 | // hxl.classes.ColumnFilter 138 | // 139 | 140 | QUnit.test("column filter whitelist", function(assert) { 141 | var patterns = ['#sector']; 142 | var filter = new hxl.classes.ColumnFilter(this.dataset, patterns); 143 | assert.deepEqual(filter.columns.map(function (col) { 144 | return col.displayTag; 145 | }), ['#sector+cluster']); 146 | assert.deepEqual(filter.rows.map(function (row) { 147 | return row.values; 148 | }), this.test_data.slice(3).map(function (data) { 149 | return [data[2]]; 150 | })); 151 | 152 | // test that the convenience methods work 153 | assert.deepEqual(filter.columns, this.dataset.withColumns(patterns).columns); 154 | assert.deepEqual(filter.values, this.dataset.withColumns(patterns).values); 155 | assert.deepEqual(filter.values, this.dataset.withColumns('#sector').values); 156 | }); 157 | 158 | QUnit.test("column filter blacklist", function(assert) { 159 | var patterns = ['#sector']; 160 | var filter = new hxl.classes.ColumnFilter(this.dataset, patterns, true); 161 | assert.deepEqual(filter.columns.map(function (col) { 162 | return col.displayTag; 163 | }), ['#org', '#org', '#adm1+name', '#population+num']); 164 | assert.deepEqual(filter.rows.map(function (row) { 165 | return row.values; 166 | }), this.test_data.slice(3).map(function (data) { 167 | return [data[0], data[1], data[3], data[4]]; 168 | })); 169 | 170 | // test that the convenience methods work 171 | assert.deepEqual(filter.columns, this.dataset.withoutColumns(patterns).columns); 172 | assert.deepEqual(filter.rows, this.dataset.withoutColumns(patterns).rows); 173 | assert.deepEqual(filter.rows, this.dataset.withoutColumns('#sector').rows); 174 | }); 175 | 176 | 177 | // 178 | // hxl.classes.CountFilter 179 | // 180 | 181 | QUnit.test("count filter single column", function(assert) { 182 | var patterns = ['#adm1']; 183 | var filter = new hxl.classes.CountFilter(this.dataset, patterns); 184 | assert.equal(filter.rows.length, 2); 185 | assert.deepEqual(filter.columns.map( 186 | function (col) { return col.displayTag; } 187 | ), ['#adm1+name', '#meta+count']); 188 | 189 | // test that the convenience methods work 190 | assert.deepEqual(filter.displayTags, this.dataset.count(patterns).displayTags); 191 | assert.deepEqual(filter.rawData, this.dataset.count(patterns).rawData); 192 | assert.deepEqual(filter.rawData, this.dataset.count('#adm1').rawData); 193 | }); 194 | 195 | QUnit.test("count filter multiple columns", function(assert) { 196 | var patterns = ['#sector', '#adm1']; 197 | var filter = new hxl.classes.CountFilter(this.dataset, patterns); 198 | assert.equal(filter.rows.length, 3); 199 | assert.deepEqual(filter.columns.map( 200 | function (col) { return col.displayTag; } 201 | ), ['#sector+cluster', '#adm1+name', '#meta+count']); 202 | 203 | // test that the convenience methods work 204 | assert.deepEqual(filter.displayTags, this.dataset.count(patterns).displayTags); 205 | assert.deepEqual(filter.rawValues, this.dataset.count(patterns).rawValues); 206 | }); 207 | 208 | QUnit.test("test numeric aggregation", function(assert) { 209 | var source = new hxl.classes.CountFilter(this.dataset, ['#sector', '#adm1']); 210 | var patterns = ['#adm1']; 211 | var aggregate = '#meta+count'; 212 | var filter = new hxl.classes.CountFilter(source, patterns, aggregate); 213 | assert.equal(filter.rows.length, 2); 214 | assert.deepEqual(filter.rows.map(function (row) { return row.values; }), [ 215 | ['Coastal Province', 2, 2, 1, 1, 1], 216 | ['Mountain Province', 1, 1, 1, 1, 1] 217 | ]); 218 | assert.deepEqual(filter.columns.map( 219 | function (col) { return col.displayTag; } 220 | ), ['#adm1+name', '#meta+count', '#meta+sum', '#meta+avg', '#meta+min', '#meta+max']); 221 | 222 | // test that the convenience methods work 223 | assert.deepEqual(filter.displayTags, source.count(patterns, aggregate).displayTags); 224 | assert.deepEqual(filter.rawValues, source.count(patterns, aggregate).rawValues); 225 | }); 226 | 227 | 228 | // 229 | // HXL.classes.RenameFilter 230 | // 231 | 232 | QUnit.test("replace all matches", function(assert) { 233 | var expectedTags = ['#org+foo', '#org+foo', '#sector+cluster', '#adm1+name', '#population+num']; 234 | // test class directly 235 | var filter = new hxl.classes.RenameFilter(this.dataset, '#org', '#org+foo'); 236 | assert.deepEqual(filter.displayTags, expectedTags); 237 | // test filter function 238 | filter = this.dataset.rename('#org', '#org+foo'); 239 | assert.deepEqual(filter.displayTags, expectedTags); 240 | }); 241 | 242 | QUnit.test("confirm changed columns set in rows", function(assert) { 243 | var expectedTags = ['#org+foo', '#org+foo', '#sector+cluster', '#adm1+name', '#population+num']; 244 | var actualTags = [] 245 | filter = this.dataset.rename('#org', '#org+foo'); 246 | filter.forEach(function (row) { 247 | actualTags = []; 248 | row.columns.forEach(function (col) { 249 | actualTags.push(col.displayTag); 250 | }); 251 | assert.deepEqual(actualTags, expectedTags); 252 | }); 253 | }); 254 | 255 | QUnit.test("replace only one match", function(assert) { 256 | var expectedTags = ['#org', '#org+foo', '#sector+cluster', '#adm1+name', '#population+num']; 257 | // test class directly 258 | var filter = new hxl.classes.RenameFilter(this.dataset, '#org', '#org+foo', undefined, 1); 259 | assert.deepEqual(filter.displayTags, expectedTags); 260 | // test filter function 261 | filter = this.dataset.rename('#org', '#org+foo', undefined, 1); 262 | assert.deepEqual(filter.displayTags, expectedTags); 263 | }); 264 | 265 | 266 | // 267 | // HXL.classes.SortFilter 268 | // 269 | 270 | QUnit.test("basic sort", function(assert) { 271 | var filter = new hxl.classes.SortFilter(this.dataset, "#sector"); 272 | assert.equal("Health", filter.getRows()[0].get("#sector")); 273 | }); 274 | 275 | QUnit.test("inverse sort", function(assert) { 276 | var filter = this.dataset.sort("#population", true); 277 | assert.equal("500", filter.getRows()[0].get("#population")); 278 | }); 279 | 280 | QUnit.test("multi-column sort", function(assert) { 281 | var filter = this.dataset.sort(["#sector", "#population"]); 282 | assert.equal("Health", filter.getRows()[0].get("#sector")); 283 | assert.equal("400", filter.getRows()[0].get("#population")); 284 | 285 | // flip order of key columns 286 | filter = this.dataset.sort(["#population", "#sector"]); 287 | assert.equal("300", filter.getRows()[0].get("#population")); 288 | assert.equal("WASH", filter.getRows()[0].get("#sector")); 289 | }); 290 | 291 | 292 | // 293 | // HXL.classes.PreviewFilter 294 | // 295 | 296 | QUnit.test("preview the initial rows", function(assert) { 297 | var filter = new hxl.classes.PreviewFilter(this.dataset, 2); 298 | assert.equal(2, filter.getRows().length); 299 | 300 | filter = this.dataset.preview(1); 301 | assert.equal(1, filter.getRows().length); 302 | }); 303 | 304 | 305 | // 306 | // HXL.classes.CacheFilter 307 | // 308 | 309 | QUnit.test("cache the parsing stream", function(assert) { 310 | // not testing for actual caching; just that the filter passes through 311 | var filter = new hxl.classes.CacheFilter(this.dataset.withColumns('#sector')); 312 | assert.deepEqual(filter.displayTags, ['#sector+cluster']) 313 | filter = this.dataset.withColumns('#sector').cache(); 314 | assert.deepEqual(filter.displayTags, ['#sector+cluster']); 315 | }); 316 | 317 | 318 | // 319 | // HXL.classes.IndexFilter 320 | // 321 | 322 | QUnit.test("Add index attributes to repeated tags", function(assert) { 323 | var expectedTags = ['#org+i0', '#org+i1', '#sector+cluster', '#adm1+name', '#population+num']; 324 | var filter = new hxl.classes.IndexFilter(this.dataset, '#org'); 325 | assert.deepEqual(filter.displayTags, expectedTags); 326 | filter = this.dataset.index('org'); 327 | assert.deepEqual(filter.displayTags, expectedTags); 328 | }); 329 | 330 | // end 331 | -------------------------------------------------------------------------------- /lib/papaparse.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Papa Parse 3 | v4.1.0 4 | https://github.com/mholt/PapaParse 5 | */ 6 | !(function(e){"use strict";function u(t,n){n=n||{};if(n.worker&&Papa.WORKERS_SUPPORTED){var r=m();r.userStep=n.step;r.userChunk=n.chunk;r.userComplete=n.complete;r.userError=n.error;n.step=x(n.step);n.chunk=x(n.chunk);n.complete=x(n.complete);n.error=x(n.error);delete n.worker;r.postMessage({input:t,config:n,workerId:r.id});return}var i=null;if(typeof t==="string"){if(n.download)i=new l(n);else i=new h(n)}else if(e.File&&t instanceof File||t instanceof Object)i=new c(n);return i.stream(t)}function a(t,n){function a(){if(typeof n!=="object")return;if(typeof n.delimiter==="string"&&n.delimiter.length==1&&e.Papa.BAD_DELIMITERS.indexOf(n.delimiter)==-1){o=n.delimiter}if(typeof n.quotes==="boolean"||n.quotes instanceof Array)s=n.quotes;if(typeof n.newline==="string")u=n.newline}function f(e){if(typeof e!=="object")return[];var t=[];for(var n in e)t.push(n);return t}function l(e,t){var n="";if(typeof e==="string")e=JSON.parse(e);if(typeof t==="string")t=JSON.parse(t);var r=e instanceof Array&&e.length>0;var i=!(t[0]instanceof Array);if(r){for(var s=0;s0)n+=o;n+=c(e[s],s)}if(t.length>0)n+=u}for(var a=0;a0)n+=o;var h=r&&i?e[l]:l;n+=c(t[a][h],l)}if(a-1||t.charAt(0)==" "||t.charAt(t.length-1)==" ";return r?'"'+t+'"':t}function h(e,t){for(var n=0;n-1)return true;return false}var r="";var i=[];var s=false;var o=",";var u="\r\n";a();if(typeof t==="string")t=JSON.parse(t);if(t instanceof Array){if(!t.length||t[0]instanceof Array)return l(null,t);else if(typeof t[0]==="object")return l(f(t[0]),t)}else if(typeof t==="object"){if(typeof t.data==="string")t.data=JSON.parse(t.data);if(t.data instanceof Array){if(!t.fields)t.fields=t.data[0]instanceof Array?t.fields:f(t.data[0]);if(!(t.data[0]instanceof Array)&&typeof t.data[0]!=="object")t.data=[t.data]}return l(t.fields||[],t.data||[])}throw"exception: Unable to serialize unrecognized input"}function f(n){function r(e){var t=E(e);t.chunkSize=parseInt(t.chunkSize);this._handle=new p(t);this._handle.streamer=this;this._config=t}this._handle=null;this._paused=false;this._finished=false;this._input=null;this._baseIndex=0;this._partialLine="";this._rowCount=0;this._start=0;this._nextChunk=null;r.call(this,n);this.parseChunk=function(n){var r=this._partialLine+n;this._partialLine="";var i=this._handle.parse(r,this._baseIndex,!this._finished);if(this._handle.paused())return;var s=i.meta.cursor;if(!this._finished){this._partialLine=r.substring(s-this._baseIndex);this._baseIndex=s}if(i&&i.data)this._rowCount+=i.data.length;var o=this._finished||this._config.preview&&this._rowCount>=this._config.preview;if(t){e.postMessage({results:i,workerId:Papa.WORKER_ID,finished:o})}else if(x(this._config.chunk)){this._config.chunk(i,this._handle);if(this._paused)return;i=undefined}if(o&&x(this._config.complete)&&(!i||!i.meta.aborted))this._config.complete(i);if(!o&&(!i||!i.meta.paused))this._nextChunk();return i};this._sendError=function(n){if(x(this._config.error))this._config.error(n);else if(t&&this._config.error){e.postMessage({workerId:Papa.WORKER_ID,error:n,finished:false})}}}function l(e){function r(e){var t=e.getResponseHeader("Content-Range");return parseInt(t.substr(t.lastIndexOf("/")+1))}e=e||{};if(!e.chunkSize)e.chunkSize=Papa.RemoteChunkSize;f.call(this,e);var n;if(t){this._nextChunk=function(){this._readChunk();this._chunkLoaded()}}else{this._nextChunk=function(){this._readChunk()}}this.stream=function(e){this._input=e;this._nextChunk()};this._readChunk=function(){if(this._finished){this._chunkLoaded();return}n=new XMLHttpRequest;if(!t){n.onload=S(this._chunkLoaded,this);n.onerror=S(this._chunkError,this)}n.open("GET",this._input,!t);if(this._config.step||this._config.chunk){var e=this._start+this._config.chunkSize-1;n.setRequestHeader("Range","bytes="+this._start+"-"+e);n.setRequestHeader("If-None-Match","webkit-no-cache")}try{n.send()}catch(r){this._chunkError(r.message)}if(t&&n.status==0)this._chunkError();else this._start+=this._config.chunkSize};this._chunkLoaded=function(){if(n.readyState!=4)return;if(n.status<200||n.status>=400){this._chunkError();return}this._finished=!this._config.step&&!this._config.chunk||this._start>r(n);this.parseChunk(n.responseText)};this._chunkError=function(e){var t=n.statusText||e;this._sendError(t)}}function c(e){e=e||{};if(!e.chunkSize)e.chunkSize=Papa.LocalChunkSize;f.call(this,e);var t,n;var r=typeof FileReader!=="undefined";this.stream=function(e){this._input=e;n=e.slice||e.webkitSlice||e.mozSlice;if(r){t=new FileReader;t.onload=S(this._chunkLoaded,this);t.onerror=S(this._chunkError,this)}else t=new FileReaderSync;this._nextChunk()};this._nextChunk=function(){if(!this._finished&&(!this._config.preview||this._rowCount=this._input.size;this.parseChunk(e.target.result)};this._chunkError=function(){this._sendError(t.error)}}function h(e){e=e||{};f.call(this,e);var t;var n;this.stream=function(e){t=e;n=e;return this._nextChunk()};this._nextChunk=function(){if(this._finished)return;var e=this._config.chunkSize;var t=e?n.substr(0,e):n;n=e?n.substr(e):"";this._finished=!n;return this.parseChunk(t)}}function p(e){function c(){if(f&&u){b("Delimiter","UndetectableDelimiter","Unable to auto-detect delimiting character; defaulted to '"+Papa.DefaultDelimiter+"'");u=false}if(e.skipEmptyLines){for(var t=0;t=a.length){if(!n["__parsed_extra"])n["__parsed_extra"]=[];n["__parsed_extra"].push(f.data[t][r])}else n[a[r]]=f.data[t][r]}}if(e.header){f.data[t]=n;if(r>a.length)b("FieldMismatch","TooManyFields","Too many fields: expected "+a.length+" fields but parsed "+r,t);else if(r1){a+=Math.abs(h-s);s=h}}f/=l.data.length;if((typeof i==="undefined"||a1.99){i=a;r=u}}e.delimiter=r;return{successful:!!r,bestDelimiter:r}}function g(e){e=e.substr(0,1024*1024);var t=e.split("\r");if(t.length==1)return"\n";var n=0;for(var r=0;r=t.length/2?"\r\n":"\r"}function y(e){var n=t.test(e);return n?parseFloat(e):e}function b(e,t,n,r){f.errors.push({type:e,code:t,message:n,row:r})}var t=/^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i;var n=this;var r=0;var i;var s;var o=false;var u;var a=[];var f={data:[],errors:[],meta:{}};if(x(e.step)){var l=e.step;e.step=function(t){f=t;if(h())c();else{c();if(f.data.length==0)return;r+=t.data.length;if(e.preview&&r>e.preview)s.abort();else l(f,n)}}}this.parse=function(t,n,r){if(!e.newline)e.newline=g(t);u=false;if(!e.delimiter){var a=m(t);if(a.successful)e.delimiter=a.bestDelimiter;else{u=true;e.delimiter=Papa.DefaultDelimiter}f.meta.delimiter=e.delimiter}var l=E(e);if(e.preview&&e.header)l.preview++;i=t;s=new d(l);f=s.parse(i,n,r);c();return o?{meta:{paused:true}}:f||{meta:{paused:false}}};this.paused=function(){return o};this.pause=function(){o=true;s.abort();i=i.substr(s.getCharIndex())};this.resume=function(){o=false;n.streamer.parseChunk(i)};this.abort=function(){s.abort();if(x(e.complete))e.complete(f);i=""}}function d(e){e=e||{};var t=e.delimiter;var n=e.newline;var r=e.comments;var i=e.step;var s=e.preview;var o=e.fastMode;if(typeof t!=="string"||t.length!=1||Papa.BAD_DELIMITERS.indexOf(t)>-1)t=",";if(r===t)throw"Comment character same as delimiter";else if(r===true)r="#";else if(typeof r!=="string"||Papa.BAD_DELIMITERS.indexOf(r)>-1)r=false;if(n!="\n"&&n!="\r"&&n!="\r\n")n="\n";var u=0;var a=false;this.parse=function(e,f,l){function C(e){m.push(e);b=u}function k(t){if(l)return A();if(!t)t=e.substr(u);y.push(t);u=c;C(y);if(v)O();return A()}function L(t){u=t;C(y);y=[];x=e.indexOf(n,u)}function A(e){return{data:m,errors:g,meta:{delimiter:t,linebreak:n,aborted:a,truncated:!!e,cursor:b+(f||0)}}}function O(){i(A());m=[],g=[]}if(typeof e!=="string")throw"Input must be a string";var c=e.length,h=t.length,p=n.length,d=r.length;var v=typeof i==="function";u=0;var m=[],g=[],y=[],b=0;if(!e)return A();if(o||o!==false&&e.indexOf('"')===-1){var w=e.split(n);for(var E=0;E=s){m=m.slice(0,s);return A(true)}}return A()}var S=e.indexOf(t,u);var x=e.indexOf(n,u);for(;;){if(e[u]=='"'){var T=u;u++;for(;;){var T=e.indexOf('"',T+1);if(T===-1){if(!l){g.push({type:"Quotes",code:"MissingQuotes",message:"Quoted field unterminated",row:m.length,index:u})}return k()}if(T===c-1){var N=e.substring(u,T).replace(/""/g,'"');return k(N)}if(e[T+1]=='"'){T++;continue}if(e[T+1]==t){y.push(e.substring(u,T).replace(/""/g,'"'));u=T+1+h;S=e.indexOf(t,u);x=e.indexOf(n,u);break}if(e.substr(T+1,p)===n){y.push(e.substring(u,T).replace(/""/g,'"'));L(T+1+p);S=e.indexOf(t,u);if(v){O();if(a)return A()}if(s&&m.length>=s)return A(true);break}}continue}if(r&&y.length===0&&e.substr(u,d)===r){if(x==-1)return A();u=x+p;x=e.indexOf(n,u);S=e.indexOf(t,u);continue}if(S!==-1&&(S=s)return A(true);continue}break}return k()};this.abort=function(){a=true};this.getCharIndex=function(){return u}}function v(){var e=document.getElementsByTagName("script");return e.length?e[e.length-1].src:""}function m(){if(!Papa.WORKERS_SUPPORTED)return false;if(!n&&Papa.SCRIPT_PATH===null)throw new Error("Script path cannot be determined automatically when Papa Parse is loaded asynchronously. "+"You need to set Papa.SCRIPT_PATH manually.");var t=new e.Worker(Papa.SCRIPT_PATH||r);t.onmessage=g;t.id=s++;i[t.id]=t;return t}function g(e){var t=e.data;var n=i[t.workerId];var r=false;if(t.error)n.userError(t.error,t.file);else if(t.results&&t.results.data){var s=function(){r=true;y(t.workerId,{data:[],errors:[],meta:{aborted:true}})};var o={abort:s,pause:b,resume:b};if(x(n.userStep)){for(var u=0;u 3 | 4 | 5 | 6 | 7 | 8 | JsDoc Reference - hxl.classes.TagPattern 9 | 10 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 |
    185 | 186 | 188 |
    189 |

    Classes

    190 | 223 |
    224 | 225 |
    226 | 227 |
    228 | 229 |

    230 | 231 | Class hxl.classes.TagPattern 232 |

    233 | 234 | 235 |

    236 | 237 | 238 | 239 | 240 | 241 | 242 |
    Defined in: hxl.js. 243 | 244 |

    245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 265 | 266 | 267 |
    Class Summary
    Constructor AttributesConstructor Name and Description
      260 |
    261 | hxl.classes.TagPattern(tag, includeAttributes, excludeAttributes, isAbsolute) 262 |
    263 |
    A compiled pattern for matching HXL columns.
    264 |
    268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 294 | 295 | 296 | 297 | 298 | 303 | 304 | 305 | 306 | 307 | 312 | 313 | 314 | 315 |
    Method Summary
    Method AttributesMethod Name and Description
      290 |
    match(column) 291 |
    292 |
    Test if a column matches this pattern.
    293 |
      299 |
    matchList(columns) 300 |
    301 |
    Test if a tag pattern matches any columns in a list.
    302 |
    <static>   308 |
    hxl.classes.TagPattern.parse(pattern, useException) 309 |
    310 |
    Parse a string into a tag pattern.
    311 |
    316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 |
    326 |
    327 | Class Detail 328 |
    329 | 330 |
    331 | hxl.classes.TagPattern(tag, includeAttributes, excludeAttributes, isAbsolute) 332 |
    333 | 334 |
    335 | A compiled pattern for matching HXL columns. 336 | 337 |

    You should not normally call this constructor directly. All 338 | functions that use a pattern compile it as needed, so you can stick 339 | with strings. If you want to precompile a pattern, use the static 340 | #parse method.

    341 | 342 |

    The other useful method in this class is #match, with 343 | tests the pattern against a hxl.classes.Column.

    344 | 345 |

    A pattern specification looks like a normal HXL hashtag and 346 | attributes, except that it can contain "-" attributes as well as 347 | "+" attributes. For example, the following pattern matches any 348 | column with the tag "#org", the attribute "+funder", and *not* the 349 | attribute "+impl" (any other attributes are ignored):

    350 | 351 |
    352 | #org+funder-impl
    353 | 
    354 | 355 |

    More examples:

    356 | 357 |

    #adm1 will match the following: #adm1, #adm1+code, #adm1+fr, 358 | #adm1+name, etc.

    359 | 360 |

    #adm1-code will match #adm1, #adm1+fr, and #adm1+name, 361 | but *not* #adm1+code (because the +code attribute is explicitly 362 | forbidden).

    363 | 364 |

    #adm1+name-fr will match #adm1+name or #adm1+name+en, but 365 | not #adm1+name+fr

    366 | 367 |
    368 | 369 | 370 | 371 | 372 | 373 |
    374 |
    Parameters:
    375 | 376 |
    377 | {string} tag 378 | 379 |
    380 |
    The basic tag to use in the pattern, with the 381 | leading '#'
    382 | 383 |
    384 | {array} includeAttributes 385 | 386 |
    387 |
    A (possibly-empty) list of 388 | attribute names that must be present, without the leading '+'
    389 | 390 |
    391 | {array} excludeAttributes 392 | 393 |
    394 |
    A (possibly-empty) list of 395 | attribute names that must *not* be present, without the leading '+'
    396 | 397 |
    398 | isAbsolute 399 | 400 |
    401 |
    402 | 403 |
    404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 |
    412 |
    See:
    413 | 414 |
    hxl.classes.Column
    415 | 416 |
    417 | 418 | 419 |
    420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 |
    428 | Method Detail 429 |
    430 | 431 | 432 |
    433 | 434 | {boolean} 435 | match(column) 436 | 437 |
    438 |
    439 | Test if a column matches this pattern. 440 | 441 |
    442 | data.columns.forEach(function(col) {
    443 |   if (pattern.match(col)) {
    444 |     console.log("Found a match: " + col.displayTag);
    445 |   }
    446 | });
    447 | 
    448 | 449 | This method is used heavily in the filter classes. 450 | 451 | 452 |
    453 | 454 | 455 | 456 | 457 |
    458 |
    Parameters:
    459 | 460 |
    461 | {hxl.classes.Column} column 462 | 463 |
    464 |
    The column to test.
    465 | 466 |
    467 | 468 | 469 | 470 | 471 | 472 |
    473 |
    Returns:
    474 | 475 |
    {boolean} true on match, false otherwise.
    476 | 477 |
    478 | 479 | 480 | 481 | 482 |
    483 | 484 | 485 |
    486 | 487 | 488 | matchList(columns) 489 | 490 |
    491 |
    492 | Test if a tag pattern matches any columns in a list. 493 | 494 | 495 |
    496 | 497 | 498 | 499 | 500 |
    501 |
    Parameters:
    502 | 503 |
    504 | columns 505 | 506 |
    507 |
    508 | 509 |
    510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 |
    519 | 520 | 521 |
    <static> 522 | 523 | 524 | hxl.classes.TagPattern.parse(pattern, useException) 525 | 526 |
    527 |
    528 | Parse a string into a tag pattern. 529 | 530 |
    531 | var pattern = hxl.classes.TagPattern.parse('#org+funder-impl');
    532 | 
    533 | 534 | It is safe to pass an already-compiled hxl.classes.TagPattern 535 | to this method; it will simple be returned as-is. 536 | 537 | 538 |
    539 | 540 | 541 | 542 | 543 |
    544 |
    Parameters:
    545 | 546 |
    547 | {string} pattern 548 | 549 |
    550 |
    a tag-pattern string, like "#org+funder-impl"
    551 | 552 |
    553 | useException 554 | 555 |
    556 |
    (optional) throw an exception on failure.
    557 | 558 |
    559 | 560 | 561 | 562 | 563 | 564 |
    565 |
    Returns:
    566 | 567 |
    a hxl.classes.TagPattern, or null if parsing fails (and useException is false).
    568 | 569 |
    570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 |
    582 |
    583 | 584 | 585 | 586 |
    587 | 588 | Documentation generated by JsDoc Toolkit 2.4.0 on Sat Jun 30 2018 17:05:53 GMT-0400 (EDT) 589 |
    590 | 591 | 592 | --------------------------------------------------------------------------------