dom.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. let $ = s => document.querySelector(s);
  2. let $$ = s => document.querySelectorAll(s);
  3. function clearSelector(selector) {
  4. for (let section of $$(selector)) {
  5. $('#offscreen').appendChild(section);
  6. }
  7. }
  8. function create(elementType) {
  9. let newElement = document.createElement(elementType);
  10. for (let i = 1; i < arguments.length; i++) {
  11. let currentArgument = arguments[i];
  12. if (typeof(currentArgument) === 'string') {
  13. newElement.innerHTML += currentArgument;
  14. } else if (Array.isArray(currentArgument)) {
  15. for (let j = 0; j < arguments[i].length; j++) {
  16. if (typeof(arguments[i][j]) === 'string') {
  17. newElement.innerHTML += currentArgument[j];
  18. } else {
  19. newElement.appendChild(currentArgument[j]);
  20. }
  21. }
  22. } else if (currentArgument instanceof Element) {
  23. newElement.appendChild(currentArgument);
  24. } else if (typeof(currentArgument) === 'function') {
  25. currentArgument(newElement);
  26. } else {
  27. Object.getOwnPropertyNames(currentArgument).forEach(
  28. function (val, idx, array) {
  29. newElement.setAttribute(val, currentArgument[val]);
  30. }
  31. );
  32. }
  33. }
  34. return newElement;
  35. }
  36. for (let e of ['div', 'span', 'img', 'canvas', 'svg', 'option', 'button']) {
  37. window[e] = function() {
  38. let args = [e].concat(Array.from(arguments));
  39. return create.apply(null, args);
  40. }
  41. }
  42. function downloadFile(content, title) {
  43. create('a', { download : title, href : content }).click();
  44. }
  45. class StateManager {
  46. constructor() {
  47. this.state = {}
  48. }
  49. init(key, value) {
  50. this.state[key] = {'value' : value, 'updaters' : []}
  51. }
  52. checkKey(key) {
  53. if (!this.state.hasOwnProperty(key)) {
  54. throw `Key '${key}' does not exist in state object.`
  55. }
  56. }
  57. update(key) {
  58. for (let updater of this.state[key].updaters) {
  59. let current = {};
  60. for (let updaterKey of updater.keys) {
  61. current[updaterKey] = this.state[updaterKey].value
  62. }
  63. updater.callback(current);
  64. }
  65. }
  66. set(key, value) {
  67. this.checkKey(key);
  68. this.state[key].value = value;
  69. this.update(key);
  70. }
  71. mutate(key, callback) {
  72. this.checkKey(key);
  73. callback(this.state[key].value);
  74. this.update(key);
  75. }
  76. // This should be used for immutable access,
  77. // but actually making a copy each time would probably be inefficient,
  78. // so just be disciplined for now.
  79. get(key) {
  80. this.checkKey(key);
  81. return this.state[key].value;
  82. }
  83. render(keys, callback) {
  84. let current = {}
  85. for (let key of keys) {
  86. this.checkKey(key);
  87. this.state[key].updaters.push({
  88. "callback": callback,
  89. "keys": keys
  90. });
  91. current[key] = this.state[key].value;
  92. }
  93. callback(current);
  94. }
  95. sync(stateKey, element, key) {
  96. this.init(stateKey, element[key]);
  97. let thisState = this;
  98. element.addEventListener('change', evt => {
  99. thisState.set(stateKey, evt.target[key]);
  100. });
  101. this.render([stateKey], current => {
  102. element[key] = current[stateKey];
  103. });
  104. this.set(stateKey, element[key]);
  105. }
  106. }