Created
April 21, 2015 05:34
-
-
Save mwdchang/fe01ddeeea4c9d9d0eda to your computer and use it in GitHub Desktop.
Scroll Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> | |
</head> | |
<body> | |
<span> Mouse over letters to hightlight list, unviewable items are indicated with top/bottom bar:</span><br> | |
<svg id="blahblah" width="200" height="50"></svg> | |
<div id="list1"></div> | |
</body> | |
<script> | |
// This product includes color specifications and designs developed by Cynthia Brewer (http://colorbrewer.org/). | |
var colorbrewer = {YlGn: { | |
3: ["#f7fcb9","#addd8e","#31a354"], | |
4: ["#ffffcc","#c2e699","#78c679","#238443"], | |
5: ["#ffffcc","#c2e699","#78c679","#31a354","#006837"], | |
6: ["#ffffcc","#d9f0a3","#addd8e","#78c679","#31a354","#006837"], | |
7: ["#ffffcc","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#005a32"], | |
8: ["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#005a32"], | |
9: ["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"] | |
},YlGnBu: { | |
3: ["#edf8b1","#7fcdbb","#2c7fb8"], | |
4: ["#ffffcc","#a1dab4","#41b6c4","#225ea8"], | |
5: ["#ffffcc","#a1dab4","#41b6c4","#2c7fb8","#253494"], | |
6: ["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#2c7fb8","#253494"], | |
7: ["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"], | |
8: ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"], | |
9: ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"] | |
},GnBu: { | |
3: ["#e0f3db","#a8ddb5","#43a2ca"], | |
4: ["#f0f9e8","#bae4bc","#7bccc4","#2b8cbe"], | |
5: ["#f0f9e8","#bae4bc","#7bccc4","#43a2ca","#0868ac"], | |
6: ["#f0f9e8","#ccebc5","#a8ddb5","#7bccc4","#43a2ca","#0868ac"], | |
7: ["#f0f9e8","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#08589e"], | |
8: ["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#08589e"], | |
9: ["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"] | |
},BuGn: { | |
3: ["#e5f5f9","#99d8c9","#2ca25f"], | |
4: ["#edf8fb","#b2e2e2","#66c2a4","#238b45"], | |
5: ["#edf8fb","#b2e2e2","#66c2a4","#2ca25f","#006d2c"], | |
6: ["#edf8fb","#ccece6","#99d8c9","#66c2a4","#2ca25f","#006d2c"], | |
7: ["#edf8fb","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#005824"], | |
8: ["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#005824"], | |
9: ["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"] | |
},PuBuGn: { | |
3: ["#ece2f0","#a6bddb","#1c9099"], | |
4: ["#f6eff7","#bdc9e1","#67a9cf","#02818a"], | |
5: ["#f6eff7","#bdc9e1","#67a9cf","#1c9099","#016c59"], | |
6: ["#f6eff7","#d0d1e6","#a6bddb","#67a9cf","#1c9099","#016c59"], | |
7: ["#f6eff7","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016450"], | |
8: ["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016450"], | |
9: ["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"] | |
},PuBu: { | |
3: ["#ece7f2","#a6bddb","#2b8cbe"], | |
4: ["#f1eef6","#bdc9e1","#74a9cf","#0570b0"], | |
5: ["#f1eef6","#bdc9e1","#74a9cf","#2b8cbe","#045a8d"], | |
6: ["#f1eef6","#d0d1e6","#a6bddb","#74a9cf","#2b8cbe","#045a8d"], | |
7: ["#f1eef6","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#034e7b"], | |
8: ["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#034e7b"], | |
9: ["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"] | |
},BuPu: { | |
3: ["#e0ecf4","#9ebcda","#8856a7"], | |
4: ["#edf8fb","#b3cde3","#8c96c6","#88419d"], | |
5: ["#edf8fb","#b3cde3","#8c96c6","#8856a7","#810f7c"], | |
6: ["#edf8fb","#bfd3e6","#9ebcda","#8c96c6","#8856a7","#810f7c"], | |
7: ["#edf8fb","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#6e016b"], | |
8: ["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#6e016b"], | |
9: ["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"] | |
},RdPu: { | |
3: ["#fde0dd","#fa9fb5","#c51b8a"], | |
4: ["#feebe2","#fbb4b9","#f768a1","#ae017e"], | |
5: ["#feebe2","#fbb4b9","#f768a1","#c51b8a","#7a0177"], | |
6: ["#feebe2","#fcc5c0","#fa9fb5","#f768a1","#c51b8a","#7a0177"], | |
7: ["#feebe2","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177"], | |
8: ["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177"], | |
9: ["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"] | |
},PuRd: { | |
3: ["#e7e1ef","#c994c7","#dd1c77"], | |
4: ["#f1eef6","#d7b5d8","#df65b0","#ce1256"], | |
5: ["#f1eef6","#d7b5d8","#df65b0","#dd1c77","#980043"], | |
6: ["#f1eef6","#d4b9da","#c994c7","#df65b0","#dd1c77","#980043"], | |
7: ["#f1eef6","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"], | |
8: ["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"], | |
9: ["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"] | |
},OrRd: { | |
3: ["#fee8c8","#fdbb84","#e34a33"], | |
4: ["#fef0d9","#fdcc8a","#fc8d59","#d7301f"], | |
5: ["#fef0d9","#fdcc8a","#fc8d59","#e34a33","#b30000"], | |
6: ["#fef0d9","#fdd49e","#fdbb84","#fc8d59","#e34a33","#b30000"], | |
7: ["#fef0d9","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#990000"], | |
8: ["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#990000"], | |
9: ["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"] | |
},YlOrRd: { | |
3: ["#ffeda0","#feb24c","#f03b20"], | |
4: ["#ffffb2","#fecc5c","#fd8d3c","#e31a1c"], | |
5: ["#ffffb2","#fecc5c","#fd8d3c","#f03b20","#bd0026"], | |
6: ["#ffffb2","#fed976","#feb24c","#fd8d3c","#f03b20","#bd0026"], | |
7: ["#ffffb2","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#b10026"], | |
8: ["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#b10026"], | |
9: ["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"] | |
},YlOrBr: { | |
3: ["#fff7bc","#fec44f","#d95f0e"], | |
4: ["#ffffd4","#fed98e","#fe9929","#cc4c02"], | |
5: ["#ffffd4","#fed98e","#fe9929","#d95f0e","#993404"], | |
6: ["#ffffd4","#fee391","#fec44f","#fe9929","#d95f0e","#993404"], | |
7: ["#ffffd4","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#8c2d04"], | |
8: ["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#8c2d04"], | |
9: ["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"] | |
},Purples: { | |
3: ["#efedf5","#bcbddc","#756bb1"], | |
4: ["#f2f0f7","#cbc9e2","#9e9ac8","#6a51a3"], | |
5: ["#f2f0f7","#cbc9e2","#9e9ac8","#756bb1","#54278f"], | |
6: ["#f2f0f7","#dadaeb","#bcbddc","#9e9ac8","#756bb1","#54278f"], | |
7: ["#f2f0f7","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#4a1486"], | |
8: ["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#4a1486"], | |
9: ["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"] | |
},Blues: { | |
3: ["#deebf7","#9ecae1","#3182bd"], | |
4: ["#eff3ff","#bdd7e7","#6baed6","#2171b5"], | |
5: ["#eff3ff","#bdd7e7","#6baed6","#3182bd","#08519c"], | |
6: ["#eff3ff","#c6dbef","#9ecae1","#6baed6","#3182bd","#08519c"], | |
7: ["#eff3ff","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"], | |
8: ["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"], | |
9: ["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"] | |
},Greens: { | |
3: ["#e5f5e0","#a1d99b","#31a354"], | |
4: ["#edf8e9","#bae4b3","#74c476","#238b45"], | |
5: ["#edf8e9","#bae4b3","#74c476","#31a354","#006d2c"], | |
6: ["#edf8e9","#c7e9c0","#a1d99b","#74c476","#31a354","#006d2c"], | |
7: ["#edf8e9","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#005a32"], | |
8: ["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#005a32"], | |
9: ["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"] | |
},Oranges: { | |
3: ["#fee6ce","#fdae6b","#e6550d"], | |
4: ["#feedde","#fdbe85","#fd8d3c","#d94701"], | |
5: ["#feedde","#fdbe85","#fd8d3c","#e6550d","#a63603"], | |
6: ["#feedde","#fdd0a2","#fdae6b","#fd8d3c","#e6550d","#a63603"], | |
7: ["#feedde","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#8c2d04"], | |
8: ["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#8c2d04"], | |
9: ["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"] | |
},Reds: { | |
3: ["#fee0d2","#fc9272","#de2d26"], | |
4: ["#fee5d9","#fcae91","#fb6a4a","#cb181d"], | |
5: ["#fee5d9","#fcae91","#fb6a4a","#de2d26","#a50f15"], | |
6: ["#fee5d9","#fcbba1","#fc9272","#fb6a4a","#de2d26","#a50f15"], | |
7: ["#fee5d9","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#99000d"], | |
8: ["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#99000d"], | |
9: ["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"] | |
},Greys: { | |
3: ["#f0f0f0","#bdbdbd","#636363"], | |
4: ["#f7f7f7","#cccccc","#969696","#525252"], | |
5: ["#f7f7f7","#cccccc","#969696","#636363","#252525"], | |
6: ["#f7f7f7","#d9d9d9","#bdbdbd","#969696","#636363","#252525"], | |
7: ["#f7f7f7","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525"], | |
8: ["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525"], | |
9: ["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"] | |
},PuOr: { | |
3: ["#f1a340","#f7f7f7","#998ec3"], | |
4: ["#e66101","#fdb863","#b2abd2","#5e3c99"], | |
5: ["#e66101","#fdb863","#f7f7f7","#b2abd2","#5e3c99"], | |
6: ["#b35806","#f1a340","#fee0b6","#d8daeb","#998ec3","#542788"], | |
7: ["#b35806","#f1a340","#fee0b6","#f7f7f7","#d8daeb","#998ec3","#542788"], | |
8: ["#b35806","#e08214","#fdb863","#fee0b6","#d8daeb","#b2abd2","#8073ac","#542788"], | |
9: ["#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788"], | |
10: ["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"], | |
11: ["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"] | |
},BrBG: { | |
3: ["#d8b365","#f5f5f5","#5ab4ac"], | |
4: ["#a6611a","#dfc27d","#80cdc1","#018571"], | |
5: ["#a6611a","#dfc27d","#f5f5f5","#80cdc1","#018571"], | |
6: ["#8c510a","#d8b365","#f6e8c3","#c7eae5","#5ab4ac","#01665e"], | |
7: ["#8c510a","#d8b365","#f6e8c3","#f5f5f5","#c7eae5","#5ab4ac","#01665e"], | |
8: ["#8c510a","#bf812d","#dfc27d","#f6e8c3","#c7eae5","#80cdc1","#35978f","#01665e"], | |
9: ["#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e"], | |
10: ["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"], | |
11: ["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"] | |
},PRGn: { | |
3: ["#af8dc3","#f7f7f7","#7fbf7b"], | |
4: ["#7b3294","#c2a5cf","#a6dba0","#008837"], | |
5: ["#7b3294","#c2a5cf","#f7f7f7","#a6dba0","#008837"], | |
6: ["#762a83","#af8dc3","#e7d4e8","#d9f0d3","#7fbf7b","#1b7837"], | |
7: ["#762a83","#af8dc3","#e7d4e8","#f7f7f7","#d9f0d3","#7fbf7b","#1b7837"], | |
8: ["#762a83","#9970ab","#c2a5cf","#e7d4e8","#d9f0d3","#a6dba0","#5aae61","#1b7837"], | |
9: ["#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837"], | |
10: ["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"], | |
11: ["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"] | |
},PiYG: { | |
3: ["#e9a3c9","#f7f7f7","#a1d76a"], | |
4: ["#d01c8b","#f1b6da","#b8e186","#4dac26"], | |
5: ["#d01c8b","#f1b6da","#f7f7f7","#b8e186","#4dac26"], | |
6: ["#c51b7d","#e9a3c9","#fde0ef","#e6f5d0","#a1d76a","#4d9221"], | |
7: ["#c51b7d","#e9a3c9","#fde0ef","#f7f7f7","#e6f5d0","#a1d76a","#4d9221"], | |
8: ["#c51b7d","#de77ae","#f1b6da","#fde0ef","#e6f5d0","#b8e186","#7fbc41","#4d9221"], | |
9: ["#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221"], | |
10: ["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"], | |
11: ["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"] | |
},RdBu: { | |
3: ["#ef8a62","#f7f7f7","#67a9cf"], | |
4: ["#ca0020","#f4a582","#92c5de","#0571b0"], | |
5: ["#ca0020","#f4a582","#f7f7f7","#92c5de","#0571b0"], | |
6: ["#b2182b","#ef8a62","#fddbc7","#d1e5f0","#67a9cf","#2166ac"], | |
7: ["#b2182b","#ef8a62","#fddbc7","#f7f7f7","#d1e5f0","#67a9cf","#2166ac"], | |
8: ["#b2182b","#d6604d","#f4a582","#fddbc7","#d1e5f0","#92c5de","#4393c3","#2166ac"], | |
9: ["#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac"], | |
10: ["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"], | |
11: ["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"] | |
},RdGy: { | |
3: ["#ef8a62","#ffffff","#999999"], | |
4: ["#ca0020","#f4a582","#bababa","#404040"], | |
5: ["#ca0020","#f4a582","#ffffff","#bababa","#404040"], | |
6: ["#b2182b","#ef8a62","#fddbc7","#e0e0e0","#999999","#4d4d4d"], | |
7: ["#b2182b","#ef8a62","#fddbc7","#ffffff","#e0e0e0","#999999","#4d4d4d"], | |
8: ["#b2182b","#d6604d","#f4a582","#fddbc7","#e0e0e0","#bababa","#878787","#4d4d4d"], | |
9: ["#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d"], | |
10: ["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"], | |
11: ["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"] | |
},RdYlBu: { | |
3: ["#fc8d59","#ffffbf","#91bfdb"], | |
4: ["#d7191c","#fdae61","#abd9e9","#2c7bb6"], | |
5: ["#d7191c","#fdae61","#ffffbf","#abd9e9","#2c7bb6"], | |
6: ["#d73027","#fc8d59","#fee090","#e0f3f8","#91bfdb","#4575b4"], | |
7: ["#d73027","#fc8d59","#fee090","#ffffbf","#e0f3f8","#91bfdb","#4575b4"], | |
8: ["#d73027","#f46d43","#fdae61","#fee090","#e0f3f8","#abd9e9","#74add1","#4575b4"], | |
9: ["#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4"], | |
10: ["#a50026","#d73027","#f46d43","#fdae61","#fee090","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"], | |
11: ["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"] | |
},Spectral: { | |
3: ["#fc8d59","#ffffbf","#99d594"], | |
4: ["#d7191c","#fdae61","#abdda4","#2b83ba"], | |
5: ["#d7191c","#fdae61","#ffffbf","#abdda4","#2b83ba"], | |
6: ["#d53e4f","#fc8d59","#fee08b","#e6f598","#99d594","#3288bd"], | |
7: ["#d53e4f","#fc8d59","#fee08b","#ffffbf","#e6f598","#99d594","#3288bd"], | |
8: ["#d53e4f","#f46d43","#fdae61","#fee08b","#e6f598","#abdda4","#66c2a5","#3288bd"], | |
9: ["#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd"], | |
10: ["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"], | |
11: ["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"] | |
},RdYlGn: { | |
3: ["#fc8d59","#ffffbf","#91cf60"], | |
4: ["#d7191c","#fdae61","#a6d96a","#1a9641"], | |
5: ["#d7191c","#fdae61","#ffffbf","#a6d96a","#1a9641"], | |
6: ["#d73027","#fc8d59","#fee08b","#d9ef8b","#91cf60","#1a9850"], | |
7: ["#d73027","#fc8d59","#fee08b","#ffffbf","#d9ef8b","#91cf60","#1a9850"], | |
8: ["#d73027","#f46d43","#fdae61","#fee08b","#d9ef8b","#a6d96a","#66bd63","#1a9850"], | |
9: ["#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850"], | |
10: ["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"], | |
11: ["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"] | |
},Accent: { | |
3: ["#7fc97f","#beaed4","#fdc086"], | |
4: ["#7fc97f","#beaed4","#fdc086","#ffff99"], | |
5: ["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0"], | |
6: ["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f"], | |
7: ["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17"], | |
8: ["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"] | |
},Dark2: { | |
3: ["#1b9e77","#d95f02","#7570b3"], | |
4: ["#1b9e77","#d95f02","#7570b3","#e7298a"], | |
5: ["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e"], | |
6: ["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02"], | |
7: ["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d"], | |
8: ["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"] | |
},Paired: { | |
3: ["#a6cee3","#1f78b4","#b2df8a"], | |
4: ["#a6cee3","#1f78b4","#b2df8a","#33a02c"], | |
5: ["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99"], | |
6: ["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c"], | |
7: ["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f"], | |
8: ["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00"], | |
9: ["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6"], | |
10: ["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a"], | |
11: ["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99"], | |
12: ["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"] | |
},Pastel1: { | |
3: ["#fbb4ae","#b3cde3","#ccebc5"], | |
4: ["#fbb4ae","#b3cde3","#ccebc5","#decbe4"], | |
5: ["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6"], | |
6: ["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc"], | |
7: ["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd"], | |
8: ["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec"], | |
9: ["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"] | |
},Pastel2: { | |
3: ["#b3e2cd","#fdcdac","#cbd5e8"], | |
4: ["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4"], | |
5: ["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9"], | |
6: ["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae"], | |
7: ["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc"], | |
8: ["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"] | |
},Set1: { | |
3: ["#e41a1c","#377eb8","#4daf4a"], | |
4: ["#e41a1c","#377eb8","#4daf4a","#984ea3"], | |
5: ["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00"], | |
6: ["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33"], | |
7: ["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628"], | |
8: ["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf"], | |
9: ["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"] | |
},Set2: { | |
3: ["#66c2a5","#fc8d62","#8da0cb"], | |
4: ["#66c2a5","#fc8d62","#8da0cb","#e78ac3"], | |
5: ["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854"], | |
6: ["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f"], | |
7: ["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494"], | |
8: ["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"] | |
},Set3: { | |
3: ["#8dd3c7","#ffffb3","#bebada"], | |
4: ["#8dd3c7","#ffffb3","#bebada","#fb8072"], | |
5: ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3"], | |
6: ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462"], | |
7: ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69"], | |
8: ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5"], | |
9: ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9"], | |
10: ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd"], | |
11: ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5"], | |
12: ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"] | |
}}; | |
//////////////////////////////////////////////////////////////////////////////// | |
// Constructor | |
// id - name/id of the widget, this need to be unique | |
// w - width | |
// h - height | |
// label - text label for the widget | |
//////////////////////////////////////////////////////////////////////////////// | |
function ListWidget(container, id, w, h, label) { | |
// Data | |
this.selectedTermsList = []; | |
// Position and size attributes | |
this.width = w; | |
this.height = h; | |
// Identifier attributes | |
this.container = container; | |
this.widgetId = id; | |
this.widgetLabelId = id + "_label"; | |
// Label | |
this.labelName = label; | |
this.label = null; | |
// Reference to the widget and widget components | |
this.widget = null; | |
this.topIndicator = null; | |
this.bottomIndicator = null; | |
this.upArrow = null; | |
this.downArrow = null; | |
this.scrollbar = null; | |
this.scrollbarIndicator = null; | |
// Calculate the widget offsets, refer to | |
// ListWidget schematics...you are unlikely going to understand this. | |
// DO NOT CHANGE THE ORDER !!!! | |
this.rightMarginW = this.width * 0.1; | |
this.rightMarginH = this.height; | |
this.leftMarginW = this.width * 0.1; | |
this.leftMarginH = this.height; | |
this.topMarginH = this.height*0.15; | |
this.topMarginW = this.width - (this.rightMarginW + this.leftMarginW); | |
this.bottomMarginH = this.height*0.15; | |
this.bottomMarginW = this.width - (this.rightMarginW + this.leftMarginW); | |
this.topIndicatorH = this.height*0.015; | |
this.topIndicatorW = this.topMarginW; | |
this.bottomIndicatorH = this.height*0.015; | |
this.bottomIndicatorW = this.bottomMarginW; | |
this.contentW = this.width - (this.leftMarginW + this.rightMarginW); | |
this.contentH = this.height - (this.topMarginH + this.bottomMarginH + this.topIndicatorH + this.bottomIndicatorH); | |
this.upArrowW = this.rightMarginW; | |
this.upArrowH = this.rightMarginH*0.1; | |
this.downArrowW = this.rightMarginW; | |
this.downArrowH = this.rightMarginH*0.1; | |
this.scrollW = this.rightMarginW; | |
this.scrollH = this.contentH; | |
// Element attributes | |
this.barHeight = 20; | |
this.offset = 0; | |
this.barFont = "10px Verdana"; | |
// Data used for display | |
this.displayData = []; | |
this.dataLength = 0; | |
// Function objects, these should be implemented by the controller | |
// Each components should get its own set of listeners, | |
// do not share unless there is a reason to | |
this.nothing = function() { console.log("Not implemented"); }; // DO NOT OVERRIDE THIS !!! | |
this.mouseoverFunc = this.nothing; | |
this.mouseoutFunc = this.nohintg; | |
this.mouseclickFunc = this.nothing; | |
this.root_action = this.nothing; | |
// Colours | |
this.colourIndicatorOff = d3.rgb(68, 68, 68); | |
this.colourIndicatorOn = d3.rgb(0, 170, 255); | |
this.colourCoordHighlight = d3.rgb(44, 127, 184); | |
this.colourText = d3.rgb(35, 35, 35); | |
this.colourArrow = d3.rgb(188, 188, 188); | |
this.colourArrowOutline = d3.rgb(222, 222, 222); | |
this.colourArrowHighlight = d3.rgb(0, 170, 255); | |
this.colourNormal = d3.rgb(245, 245, 245); | |
this.colourOutline = d3.rgb(55, 55, 55); | |
//this.colourNormal = d3.rgb(132, 77, 199); | |
this.colourSelected = d3.rgb(66, 132, 198); | |
// Chop off the first one (white) ... because it looks weird | |
this.colourHighlight = d3.scale.ordinal().domain([0, 1]).range(colorbrewer.Reds[8].slice(1)); | |
//this.colourHighlight = d3.scale.ordinal().domain([0, 1]).range(colorbrewer.Purples[8]); | |
//this.colourHighlight = d3.scale.ordinal().domain([0, 1]).range(colorbrewer.YlOrRd[9]); | |
//this.colourHighlight = d3.rgb(255, 127, 0); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Prototype functions | |
//////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
// Initializes a container group and setup a scrollable transformation | |
// based on the number of items in displayData | |
//////////////////////////////////////////////////////////////////////////////// | |
ListWidget.prototype.init = function() { | |
// Selft-reference | |
var myRef = this; | |
// Initialize the main container | |
this.widget = d3.select("#"+myRef.container).append("svg") | |
.attr("id", myRef.widgetId) | |
.attr("class", "taglist") | |
.attr("height", myRef.contentH+60) | |
.append("g") | |
.attr("transform", "translate(" + myRef.leftMarginW + "," + (myRef.topMarginH + myRef.topIndicatorH) + ")") | |
.append("g") | |
.append("svg") | |
.attr("width", myRef.contentW) | |
.attr("height", myRef.contentH) | |
.append("g") | |
.call( | |
d3.behavior.drag() | |
.on("drag", function(d, i) { | |
myRef.offset += d3.event.dy; | |
if (myRef.offset > 0) | |
myRef.offset = 0; | |
if (myRef.offset < -(myRef.displayData.length*myRef.barHeight)+myRef.contentH) | |
myRef.offset = Math.min(0, -(myRef.displayData.length*myRef.barHeight)+myRef.contentH); | |
d3.select(this).attr("transform", "translate(0," + myRef.offset +")"); | |
var show = -myRef.offset / myRef.barHeight; // Number of items shown | |
var unit = myRef.contentH/myRef.displayData.length; | |
myRef.scrollbarIndicator.attr("y", show*unit + (myRef.topMarginH+myRef.topIndicatorH)); | |
}) | |
) | |
; | |
// Create a data-scroll indicator at the top of the widget | |
this.topIndicator = d3.select("#"+myRef.widgetId) | |
.append("rect") | |
.attr("class", "nav_indicator") | |
.attr("x", myRef.leftMarginW) | |
.attr("y", myRef.topMarginH) | |
.attr("width", myRef.contentW) | |
.attr("height", myRef.topIndicatorH) | |
.attr("fill", myRef.colourIndicatorOff) | |
; | |
// Create a data-scroll indicator at the bottom of the widget | |
this.bottomIndicator = d3.select("#"+myRef.widgetId) | |
.append("rect") | |
.attr("class", "nav_indicator") | |
.attr("x", myRef.leftMarginW) | |
.attr("y", (myRef.topMarginH+myRef.topIndicatorH+myRef.contentH)) | |
.attr("width", myRef.contentW) | |
.attr("height", myRef.bottomIndicatorH) | |
.attr("fill", myRef.colourIndicatorOff) | |
; | |
// Create arrows | |
this.upArrow = d3.select("#"+myRef.widgetId) | |
.append("svg:path") | |
.attr("fill", this.colourArrow) | |
.attr("stroke", this.colourArrowOutline) | |
.attr("id", "upArrow") | |
.attr("transform", "translate(" + (myRef.width-0.5*myRef.rightMarginW) + "," + myRef.topMarginH + ")") | |
.attr("d", d3.svg.symbol().type("triangle-up").size(50)) | |
.on("mouseover", function(d) { d3.select(this).attr("fill", myRef.colourArrowHighlight); }) | |
.on("mouseout", function(d) { d3.select(this).attr("fill", myRef.colourArrow); }) | |
.on("mousedown", function(d) { | |
d3.event.preventDefault(); | |
d3.event.stopPropagation(); | |
myRef.offset += myRef.barHeight; | |
if (myRef.offset > 0) | |
myRef.offset = 0; | |
if (myRef.offset < -(myRef.displayData.length*myRef.barHeight)+myRef.contentH) | |
myRef.offset = Math.min(0, -(myRef.displayData.length*myRef.barHeight)+myRef.contentH); | |
myRef.widget.attr("transform", "translate(0," + myRef.offset +")"); | |
var show = -myRef.offset / myRef.barHeight; // Number of items shown | |
var unit = myRef.contentH/myRef.displayData.length; | |
myRef.scrollbarIndicator.attr("y", show*unit+(myRef.topMarginH+myRef.topIndicatorH)); | |
}) | |
; | |
this.downArrow = d3.select("#" + myRef.widgetId) | |
.append("svg:path") | |
.attr("fill", this.colourArrow) | |
.attr("stroke", this.colourArrowOutline) | |
.attr("id", "downArrow") | |
.attr("transform", "translate(" + (myRef.width-0.5*myRef.rightMarginW) + "," + (myRef.height-myRef.bottomMarginH) + ")") | |
.attr("d", d3.svg.symbol().type("triangle-down").size(50)) | |
.on("mouseover", function(d) { d3.select(this).attr("fill", myRef.colourArrowHighlight); }) | |
.on("mouseout", function(d) { d3.select(this).attr("fill", myRef.colourArrow); }) | |
.on("mousedown", function(d) { | |
d3.event.preventDefault(); | |
d3.event.stopPropagation(); | |
myRef.offset -= myRef.barHeight; | |
if (myRef.offset > 0) | |
myRef.offset = 0; | |
if (myRef.offset < -(myRef.displayData.length*myRef.barHeight)+myRef.contentH) | |
myRef.offset = Math.min(0, -(myRef.displayData.length*myRef.barHeight)+myRef.contentH); | |
myRef.widget.attr("transform", "translate(0," + myRef.offset +")"); | |
var show = -myRef.offset / myRef.barHeight; // Number of items shown | |
var unit = myRef.contentH/myRef.displayData.length; | |
myRef.scrollbarIndicator.attr("y", show*unit + (myRef.topMarginH+myRef.topIndicatorH)); | |
}) | |
; | |
this.scrollbar = d3.select("#" + myRef.widgetId) | |
.append("rect") | |
//.attr("transform", "translate(" + (20+this.width) + "," + 30 + ")") | |
.attr("x", (myRef.leftMarginW+myRef.contentW+0.5*myRef.rightMarginW)-1) | |
.attr("y", (myRef.topMarginH+myRef.topIndicatorH)+1) | |
.attr("width", 1) | |
.attr("height", myRef.scrollH-1) | |
.attr("fill", "#222222") | |
.style("opacity", 0.5) | |
; | |
this.scrollbarIndicator = d3.select("#" + myRef.widgetId) | |
.append("rect") | |
//.attr("transform", "translate(" + (19+this.width) + "," + 30 + ")") | |
.attr("x", (myRef.leftMarginW+myRef.contentW+0.5*myRef.rightMarginW) - 3) | |
.attr("y", (myRef.topMarginH+myRef.topIndicatorH)) | |
.attr("width", 5) | |
.attr("height", 0) | |
.attr("fill", "#FFAA00") | |
.style("opacity", 0.8) | |
.call( | |
d3.behavior.drag() | |
.on("drag", function(d, i) { | |
var y1 = parseFloat(myRef.scrollbarIndicator.attr("y")) - (myRef.topMarginH+myRef.topIndicatorH); | |
var y2 = d3.event.dy; | |
var y3 = y1+y2; | |
var h = parseFloat(myRef.scrollbarIndicator.attr("height")); | |
y3 = Math.max(0, y3); | |
y3 = Math.min( (myRef.contentH-h), y3); | |
myRef.scrollbarIndicator.attr("y", y3 + (myRef.topMarginH+myRef.topIndicatorH)); | |
var offset = (-y3/myRef.contentH)*myRef.barHeight*myRef.displayData.length; | |
myRef.offset = offset; | |
myRef.widget.attr("transform", "translate(0," + myRef.offset +")"); | |
}) | |
) | |
; | |
// Text tends to be a little quirky, we need a way to | |
// find out how tall they are, they are also not centred | |
// at the corner... | |
this.label = d3.select("#"+this.widgetId) | |
.append("g") | |
.attr("transform", "translate(" + myRef.leftMarginW + "," + 10 + ")") | |
; | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Render | |
// | |
// We expect that the data is of the following format: | |
// [ {name:xxx, freq:xxx}, {name:xxx, freq:xxx} ] | |
//////////////////////////////////////////////////////////////////////////////// | |
ListWidget.prototype.render = function( vdata ) { | |
// Reset the transformation | |
this.widget.attr("transform", "translate(0,0)"); | |
this.offset = 0; | |
this.displayData = vdata; | |
this.dataLength = this.displayData.length; | |
var myRef = this; | |
var show = this.contentH / this.barHeight; // Number of items shown | |
var unit = this.contentH /this.displayData.length; | |
// TODO: Fix Sort | |
myRef.displayData = _.sortBy(myRef.displayData, function(item) { | |
var a_idx = myRef.selectedTermsList.indexOf(item.name); | |
if (a_idx === -1) return 1; | |
return 0; | |
}); | |
/* | |
myRef.displayData = myRef.displayData.sort(function(a, b) { | |
var a_idx = myRef.selectedTermsList.indexOf(a.name); | |
var b_idx = myRef.selectedTermsList.indexOf(b.name); | |
if (a_idx === -1 && b_idx === -1) return b.freq-a.freq; | |
if (a_idx === -1 && b.idx !== -1) return -1; | |
if (a_idx !== -1 && b.idx === -1) return 1; | |
return b.freq-a.freq; | |
}); | |
*/ | |
// Remove the data nodes | |
this.widget.data([this.displayData] ).selectAll("rect").remove(); | |
this.widget.data([this.displayData] ).selectAll("text").remove(); | |
this.widget.data([this.displayData] ).selectAll("circle").remove(); | |
this.label.selectAll("#label").remove(); | |
// Calculate the max and min frequencies | |
var freqMax = Number.MIN_VALUE; | |
var freqMin = Number.MAX_VALUE; | |
for (var i=0; i < this.displayData.length; i++) { | |
if (this.displayData[i].freq > freqMax) freqMax = this.displayData[i].freq; | |
if (this.displayData[i].freq < freqMin) freqMin = this.displayData[i].freq; | |
} | |
//console.log("Max value = " + freqMax + " Min Value = " + freqMin); | |
this.label.append("text") | |
.attr("id", "label") | |
.attr("y", function(d,i) { return 10; }) | |
.attr("dy", ".35em") | |
.style("fill", myRef.colourText) | |
.style("font", "16px sans-serif") | |
.text(this.labelName + this.dataLength) | |
; | |
// Render horizontal rectangle bars | |
this.widget.selectAll("rect") | |
.data(this.displayData.map(function(d,i) { | |
//if (typeof d == "object") return {val:d.name, freq:d.freq, idx:i}; | |
if (typeof d == "object") return {val:d.name, freq:d.freq, idx:i}; | |
return {val:d, freq:0, idx:i}; | |
})) | |
.enter() | |
.append("rect") | |
.attr("id", "rectBar") | |
.attr("x", 20) | |
.attr("y", function(d, i) { return 1+i*myRef.barHeight; }) | |
.attr("rx", 3) | |
.attr("ry", 3) | |
//.attr("width", function(d, i) { return 0; }) | |
.attr("width", function(d, i) { return (myRef.contentW-30); }) | |
.attr("height", myRef.barHeight-2) | |
.style("stroke", myRef.colourOutline) | |
.style("strke-width", "0.5") | |
.style("fill", function(d) { | |
if (myRef.selectedTermsList.indexOf(d.val) !== -1) { | |
d.c = myRef.colourSelected; | |
} else { | |
d.c = myRef.colourNormal; | |
} | |
return d.c; | |
}) | |
.style("opacity", function(d) { | |
return 1.0; | |
/* | |
if (myRef.filter && d.val in myRef.filter) { | |
d.opacity = 1; | |
} else { | |
d.opacity = 0; | |
} | |
return d.opacity; | |
*/ | |
}) | |
.style("pointer-events", "none") | |
.style("cursor", "pointer") | |
.on("mouseover", myRef.mouseoverFunc) | |
.on("mouseout", myRef.mouseoutFunc) | |
.on("click", myRef.mouseclickFunc) | |
.transition() | |
.duration(1000) | |
.each("end", function(d, i) { | |
d3.select(this).style("pointer-events", "all") | |
; | |
}) | |
; | |
// Render list of circles beside the bar that is sized with | |
// respect to the frequency | |
this.widget.selectAll("circle") | |
.data(this.displayData.map(function(d,i) { | |
if (typeof d == "object") return {val:d.name, freq:d.freq?d.freq:0, idx:i}; | |
return {val:d, freq:0, idx:i}; | |
})) | |
.enter() | |
.append("circle") | |
.attr("cy", function(d, i) { return i*myRef.barHeight+0.5*myRef.barHeight; }) | |
.attr("cx", 10) | |
.attr("r", function(d, i) { | |
return 0; | |
/* | |
if (d.freq > 0) return 1 + 5*Math.sqrt( d.freq / freqMax); | |
else return 0; | |
*/ | |
}) | |
.attr("fill", function(d, i) { | |
return d3.rgb(0, 0, 0) | |
}) | |
.style("opacity", function(d, i) { | |
if ( d.freq > 0) return 1; | |
return 0; | |
}) | |
; | |
// Render text for bar | |
this.widget.selectAll("text") | |
.data(this.displayData.map(function(d,i) { | |
//if (typeof d == "object") return {val:d.name}; | |
if (typeof d == "object") { | |
var tmp = d.name; | |
if (tmp.length > 20) tmp = tmp.substring(0,18) + "..."; | |
return {val:tmp, freq:d.freq}; | |
} | |
return {val:d}; | |
})) | |
.enter() | |
.append("text") | |
.attr("y", function(d,i) { return i*myRef.barHeight+0.5*myRef.barHeight; }) | |
.attr("x", 25) | |
.attr("dy", ".35em") | |
.style("fill", myRef.colourText) | |
//.style("font", compute_font(13)) | |
.style("font", myRef.barFont) | |
.style("pointer-events", "none") | |
.text(function(d) { return d.val + " (" + d.freq + ")";}) | |
; | |
this.scrollbarIndicator.attr("y", (myRef.topMarginH+myRef.topIndicatorH)).attr("height", Math.min(myRef.contentH, show*unit)); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Highlight | |
//////////////////////////////////////////////////////////////////////////////// | |
ListWidget.prototype.highlight = function( termList, termFreqList, selected ) { | |
var myRef = this; | |
var termMax = _.max(termFreqList); | |
myRef.widget.selectAll("rect") | |
.filter(function(d, i) { | |
var contained = termList.indexOf(d.val) !== -1; | |
if (contained === true) { | |
if (i*myRef.barHeight + myRef.offset < 0) | |
myRef.topIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOn); | |
if (i*myRef.barHeight + myRef.offset > myRef.contentH) | |
myRef.bottomIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOn); | |
} | |
return contained; | |
}) | |
.transition() | |
.duration(300) | |
.style("fill", function(d, i) { | |
if (d.val === selected) return myRef.colourSelected; | |
var idx = termList.indexOf(d.val); | |
var freq = termFreqList[idx]; | |
var power = freq / termMax; | |
return myRef.colourHighlight(power); | |
}); | |
/* | |
.style("opacity", function(d, i) { | |
if (d.val === selected) return 1.0; | |
var idx = termList.indexOf(d.val); | |
var freq = termFreqList[idx]; | |
var ratio = freq / termMax; | |
return 0.5 + 0.5*ratio; | |
}); | |
*/ | |
}; | |
ListWidget.prototype.unHighlight = function() { | |
var myRef = this; | |
myRef.widget.selectAll("rect") | |
.style("fill", function(d) { return d.c; }) | |
.style("opacity", 1); | |
myRef.topIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOff); | |
myRef.bottomIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOff); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Highlight the list widget with respect to a corresponding | |
// artifact | |
// | |
// ar - an artifact node | |
//////////////////////////////////////////////////////////////////////////////// | |
ListWidget.prototype.highlight2 = function( ar ) { | |
var myRef = this; | |
// Pre-compute whether each entity will take part, this way | |
// we can reuse it for various elements in the widget rather | |
// than re-calculating | |
// Check if list item is in artifact(ar)'s entity list | |
// if yes then push in true, else false | |
var flags = []; | |
for (var i = 0; i < this.displayData.length; i ++) { | |
flags.push( DataParser.containsEntity(ar, this.displayData[i].name)); | |
} | |
// High light the circles | |
this.widget.selectAll("circle") | |
.transition() | |
.duration(300) | |
.attr("fill", function(d, i) { | |
if ( flags[i] ) return d3.rgb(255, 128, 0); | |
return d3.rgb(0, 0, 0); | |
}) | |
; | |
// High light the bars | |
this.widget.selectAll("#rectBar") | |
.transition() | |
.duration(300) | |
.attr("fill", function(d, i) { | |
if (flags[i]) { | |
//top | |
if (i*myRef.barHeight + myRef.offset < 0) | |
myRef.topIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOn); | |
//bottom | |
if (i*myRef.barHeight + myRef.offset > myRef.contentH) | |
myRef.bottomIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOn); | |
return d.c; | |
} | |
//return null; | |
return d.c; | |
}) | |
.style("opacity", function(d, i) { | |
if (flags[i]) { | |
return 1.0; | |
} | |
return d.opacity; | |
}) | |
; | |
this.widget.selectAll("text") | |
.transition() | |
.duration(300) | |
.style("fill", function(d, i) { | |
if (flags[i]) { | |
return myRef.colourText; | |
} | |
return myRef.colourText; | |
}) | |
; | |
// Reset the indicators on mouse out | |
if ( ar == null) { | |
myRef.topIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOff); | |
myRef.bottomIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOff); | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Highlight the coordianted brushing stuff | |
// | |
// selected - An associated array containing the currently selected | |
// filters | |
// coord - An associated array or the related entities in | |
// the form { entity1:occ, entity2:occ, ...} | |
//////////////////////////////////////////////////////////////////////////////// | |
ListWidget.prototype.coordHighlight = function( selected, coord ) { | |
var myRef = this; | |
// Pre-compute the max and min for the co-occurring entities | |
var coordMax = Number.MIN_VALUE; | |
var coordMin = Number.MAX_VALUE; | |
if (coord != null) { | |
for (var e in coord) { | |
if (coord[e].freq > coordMax) { coordMax = coord[e].freq; } | |
if (coord[e].freq < coordMin) { coordMin = coord[e].freq; } | |
} | |
} else { | |
// Just in case...don't want a divide by zero here | |
coordMax = 1; | |
coordMin = 1; | |
} | |
//console.log("max : " + coordMax); | |
//console.log("min : " + coordMin); | |
this.widget.selectAll("circle") | |
.transition() | |
.duration(300) | |
.attr("fill", function(d, i) { | |
if (selected == null && coord == null) return d.c; | |
if (selected[ d.val ] ) { | |
return d3.rgb(255, 128, 0); | |
} else if (coord[ d.val ] && ! selected[ d.val ]) { | |
//top | |
if (i*myRef.barHeight + myRef.offset < 0) { | |
myRef.topIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOn); | |
} | |
//bottom | |
if (i*myRef.barHeight + myRef.offset > myRef.contentH) { | |
myRef.bottomIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOn); | |
} | |
return myRef.colourCoordHighlight; | |
} | |
return d.c; | |
}) | |
.style("opacity", function(d, i) { | |
if ( coord != null && coord[ d.val ] ) { | |
return (coord[d.val].freq - coordMin + 1)/( coordMax - coordMin + 1); | |
} | |
return 1; | |
}) | |
; | |
this.widget.selectAll("#rectBar") | |
.transition() | |
.duration(300) | |
.attr("fill", function(d, i) { | |
if (selected == null && coord == null) return d.c; | |
if (selected[ d.val ] || (myRef.filter && d.val in myRef.filter) ) { | |
return d.c; | |
} else if (coord[ d.val ] && ! selected[ d.val ]) { | |
//top | |
if (i*myRef.barHeight + myRef.offset < 0) { | |
myRef.topIndicator.attr("fill", myRef.colourIndicatorOn); | |
} | |
//bottom | |
if (i*myRef.barHeight + myRef.offset > myRef.contentH) { | |
myRef.bottomIndicator.attr("fill", myRef.colourIndicatorOn); | |
} | |
return myRef.colourCoordHighlight; | |
} | |
return d.c; | |
}) | |
.style("opacity", function(d, i) { | |
if (myRef.filter && d.val in myRef.filter) return d.opacity; | |
if (selected == null && coord == null) return d.opacity; | |
if (selected[d.val]) { | |
return 1.0; | |
} | |
// Intensity Formula | |
// Linear : I = (freq - min + 1)/ (max - min + 1) | |
if (coord[ d.val ] ) { | |
return (coord[d.val].freq - coordMin + 1)/( coordMax - coordMin + 1); | |
} | |
return d.opacity; | |
}) | |
; | |
this.widget.selectAll("text") | |
.transition() | |
.duration(300) | |
.style("fill", function(d, i) { | |
if (selected == null && coord == null) return myRef.colourText; | |
if (coord[ d.val ] || selected[ d.val ] ) { | |
return myRef.colourText; | |
} | |
return myRef.colourText; | |
}) | |
; | |
// Reset the indicators on mouse out | |
if (selected == null && coord == null) { | |
myRef.topIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOff); | |
myRef.bottomIndicator.transition().duration(300).attr("fill", myRef.colourIndicatorOff); | |
} | |
} | |
var widget = new ListWidget("list1", "Test", 200, 300, "# items: "); | |
widget.init(); | |
widget.render( [ | |
{ name:'a', freq:1 }, | |
{ name:'b', freq:1 }, | |
{ name:'c', freq:1 }, | |
{ name:'d', freq:1 }, | |
{ name:'e', freq:1 }, | |
{ name:'f', freq:1 }, | |
{ name:'g', freq:1 }, | |
{ name:'h', freq:1 }, | |
{ name:'i', freq:1 }, | |
{ name:'j', freq:1 }, | |
{ name:'k', freq:1 }, | |
{ name:'l', freq:1 }, | |
{ name:'m', freq:1 }, | |
{ name:'n', freq:1 }, | |
{ name:'o', freq:1 }, | |
{ name:'p', freq:1 }, | |
{ name:'q', freq:1 }, | |
{ name:'r', freq:1 } | |
]) | |
var x = d3.select('#blahblah').append('g'); | |
x.append('text').attr('x', 20).attr('y', 35).style('font-size', 30).text('a').on('mouseover', function() { | |
widget.highlight( ['a'], [100], null); | |
}).on('mouseout', function() { | |
widget.unHighlight(); | |
}); | |
x.append('text').attr('x', 40).attr('y', 35).style('font-size', 30).text('q').on('mouseover', function() { | |
widget.highlight( ['q'], [100], null); | |
}).on('mouseout', function() { | |
widget.unHighlight(); | |
}); | |
// widget.highlight( ['q'], [100], null); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment