This is some exercise code on the problem of populating a <ul> element subject to constraints and other criteria. It uses an "out-of-sight" dummy list to compute the dimensions it needs to lay out the actual list.
Last active
December 27, 2015 21:39
-
-
Save kynnjo/7393028 to your computer and use it in GitHub Desktop.
exercise: populating a list
This file contains hidden or 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
| <!DOCTYPE html> | |
| <html> | |
| <meta charset="utf-8"> | |
| <title>populating a list</title> | |
| <style> | |
| *{ | |
| -webkit-box-sizing: border-box; | |
| -moz-box-sizing: border-box; | |
| box-sizing: border-box; | |
| } | |
| html, body, div, ol, ul, li, br, img, hr{ | |
| margin:0; | |
| padding:0; | |
| border:0; | |
| outline:0; | |
| } | |
| *{ | |
| /* font-family: "Gill Sans", "Gill Sans MT", sans-serif; */ | |
| font-family: Consolas, Monaco, "Andale Mono WT", "Andale Mono", "Nimbus Mono L", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Courier New", Courier, monospace; | |
| } | |
| .list-container{ | |
| cursor:default; | |
| } | |
| .list-container li{ | |
| white-space:nowrap; | |
| overflow:hidden; | |
| text-overflow:ellipsis; | |
| } | |
| .list-container ul{ | |
| list-style:none; | |
| } | |
| .list-container li{ | |
| -webkit-background-clip: padding-box; | |
| background-clip: padding-box; | |
| } | |
| .list-container li{ | |
| border-style:solid; | |
| border-color:rgb(255, 255, 255); | |
| border-color:rgba(0, 0, 0, 0); | |
| } | |
| .list-container li:hover{ | |
| font-weight:bold; | |
| border-color:rgb(0, 0, 0); | |
| border-color:rgba(0, 0, 0, 1); | |
| } | |
| /* TBD = to be determined (dynamically, that is) */ | |
| /* | |
| #the-list ul, #the-list ol{ | |
| width: TBD; | |
| } | |
| #the-list li{ | |
| width: TBD; | |
| } | |
| */ | |
| .list-container li{ | |
| float: left; | |
| } | |
| .list-container br:last-child{ | |
| clear: left; | |
| } | |
| .list-container { | |
| margin-bottom: 1em; | |
| } | |
| #out-of-sight { | |
| position:relative; | |
| } | |
| #out-of-sight .list-container{ | |
| left:-999999px; | |
| position:absolute; | |
| } | |
| </style> | |
| <body> | |
| <button>next</button> | |
| <div id="main"> | |
| <div id="the-list" class="list-container"> | |
| <ul></ul> | |
| <br/> | |
| </div> | |
| </div> | |
| <div id="out-of-sight"> | |
| <div id="dummy-list" class="list-container"> | |
| <ul></ul> | |
| <br/> | |
| </div> | |
| </div> | |
| <script src="//code.jquery.com/jquery-1.10.2.min.js"></script> | |
| <script src="//d3js.org/d3.v3.min.js"></script> | |
| <script> | |
| var lists = [ | |
| "<00>+<01>+<02>+<03>+<04>+<05>+<06>+<07>+<08>+<09>+<10>+<11>+<12>", | |
| "entity-00+entity-01+entity-02+entity-03+entity-04+entity-05+ent" + | |
| "ity-06+entity-07+entity-08+entity-09+entity-10+entity-11+enti" + | |
| "ty-12", | |
| "item-00+item-01+item-02+item-03+item-04+item-05+item-06+item-07" + | |
| "+item-08+item-09+item-10+item-11+item-12", | |
| "Aruba+China+Iraq+Peru+Benin+Cuba+Mali+Togo+Chad+Fiji+Niue+Chile" + | |
| "+Guam+Oman", | |
| "Canada+India+Niue+Dominica+Kazakhstan+Slovenia+Ghana+Kyrgyzstan" + | |
| "+Sri Lanka+Grenada+Morocco+Thailand+Guinea+Namibia", | |
| "Aruba+Mayotte+Bermuda+Mexico+Czech Republic+Morocco+Egypt+Qatar" + | |
| "+Estonia+Trinidad and Tobago+Gibraltar", | |
| "Benin+Chile+Monaco+Montenegro+Niger+Tajikistan+Tokelau+Tunisia+" + | |
| "Ukraine+United States Minor Outlying Islands+Yemen" | |
| ].map(split_pre_list), | |
| loremipsum = split_pre_list( | |
| "01. Lorem+02. ipsum+03. dolor+04. sit+05. amet+06. consectetur+07. adipiscing+08. elit+09. Nunc+10. accumsan+11. nec+12. tellus+13. eleifend+14. pellentesque+15. Donec+16. eu+17. posuere+18. massa+19. Vestibulum+20. ut+21. dui+22. a+23. mauris+24. imperdiet+25. vulputate+26. ac+27. vitae+28. sem+29. Cum+30. sociis+31. natoque+32. penatibus+33. et+34. magnis+35. dis+36. parturient+37. montes+38. nascetur+39. ridiculus+40. mus+41. Proin+42. leo+43. quam+44. pellentesque+45. id+46. convallis+47. sed+48. tempus+49. ac+50. lorem+51. Donec+52. accumsan+53. sem+54. nec+55. eros+56. aliquet+57. egestas+58. Aenean+59. elementum+60. aliquet+61. rhoncus+62. Integer+63. tristique+64. varius+65. nulla+66. vitae+67. suscipit"), | |
| current_index = 0, | |
| sentinel = String.fromCharCode(29); | |
| d3.range(1, loremipsum.length + 1) | |
| .forEach(function (i) { lists.push(loremipsum.slice(0, i)); }); | |
| $('button').click(function () { | |
| populate_list(lists[current_index]); | |
| current_index = ((current_index + 1) % lists.length); | |
| }).click(); | |
| function populate_list (data) { | |
| _populate_list_0(d3.select('#out-of-sight ul'), data); | |
| function get_width (t) { | |
| return t.getBoundingClientRect().width | |
| } | |
| var all_widths = d3.select('#out-of-sight') | |
| .selectAll('li') | |
| .filter(function () { | |
| return d3.select(this).style('display') !== 'none'; | |
| })[0] | |
| .map(get_width) | |
| .sort(d3.ascending), | |
| unpadded_colwidth = Math.round(d3.quantile(all_widths, 0.9)), | |
| hpadding = 10, | |
| borderwidth = 1, | |
| colwidth = unpadded_colwidth + (2 * borderwidth) + hpadding, | |
| hmargin = 10, | |
| min_rows = 4, | |
| max_ncols = ~~((data.length - 1)/(min_rows - 1)), | |
| max_width = 450, | |
| ncols = Math.max(1, Math.min(max_ncols, ~~(max_width/(colwidth + hmargin)))); | |
| // console.log(max_ncols, ~~(max_width/(colwidth + hmargin)), ncols); | |
| _populate_list('the-list', data, ncols, colwidth, hpadding, hmargin, borderwidth); | |
| } | |
| function _populate_list_0(list, data) { | |
| var lis0 = list.selectAll('li'), | |
| lis = lis0.data(data); | |
| enter = lis.enter(), | |
| exit = lis.exit(); | |
| exit.style('display', 'none'); | |
| enter.append('li'); | |
| lis.text(String) | |
| .style('display', '') | |
| .style('visibility', | |
| function (d) { return d === sentinel ? 'hidden' : 'visible'; }); | |
| } | |
| function _populate_list(which, data, ncols, colwidth, hpadding, hmargin, borderwidth) { | |
| var ul = d3.select('#' + which + ' ul'); | |
| _populate_list_0(ul, d3.merge(columnate(data, ncols))); | |
| // _populate_list_0(ul, data); | |
| ul.style('width', (ncols * (colwidth + hmargin)) + 'px'); | |
| ul.selectAll('li') | |
| .style('width', colwidth + 'px') | |
| .style('border-width', borderwidth + 'px') | |
| .style('padding', '0 ' + (hpadding/2) + 'px') | |
| .style('margin', '0 ' + (hmargin/2) + 'px'); | |
| } | |
| function columnate (array, ncols) { | |
| var nrows = Math.ceil(array.length/ncols); | |
| return d3.transpose(chunk(pad_array(array, nrows * ncols), nrows)); | |
| } | |
| function pad_array (array, n) { | |
| return array.concat(d3.range(n - array.length) | |
| .map(function () { return sentinel; })); | |
| } | |
| function chunk (array, chunksize) { | |
| return d3.range(array.length/chunksize) | |
| .map(function (i) { | |
| var s = i * chunksize; | |
| return array.slice(s, s + chunksize); | |
| }); | |
| } | |
| function split_pre_list (array) { | |
| return array.split('+').sort(); | |
| } | |
| </script> | |
| </body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment