styling.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. /**
  4. * A namespace for node styling.
  5. */
  6. export
  7. namespace Styling {
  8. /**
  9. * Style a node and its child elements with the default tag names.
  10. *
  11. * @param node - The base node.
  12. *
  13. * @param className - The optional CSS class to add to styled nodes.
  14. */
  15. export
  16. function styleNode(node: HTMLElement, className=''): void {
  17. styleNodeByTag(node, 'select', className);
  18. styleNodeByTag(node, 'input', className);
  19. styleNodeByTag(node, 'button', className);
  20. }
  21. /**
  22. * Style a node and its elements that have a given tag name.
  23. *
  24. * @param node - The base node.
  25. *
  26. * @param tagName - The html tag name to style.
  27. *
  28. * @param className - The optional CSS class to add to styled nodes.
  29. */
  30. export
  31. function styleNodeByTag(node: HTMLElement, tagName: string, className=''): void {
  32. if (node.localName === tagName) {
  33. node.classList.add('jp-mod-styled');
  34. }
  35. if (node.localName === 'select') {
  36. wrapSelect(node as HTMLSelectElement);
  37. }
  38. let nodes = node.getElementsByTagName(tagName);
  39. for (let i = 0; i < nodes.length; i++) {
  40. let child = nodes[i];
  41. child.classList.add('jp-mod-styled');
  42. if (className) {
  43. child.classList.add(className);
  44. }
  45. if (tagName === 'select') {
  46. wrapSelect(child as HTMLSelectElement);
  47. }
  48. }
  49. }
  50. /**
  51. * Wrap a select node.
  52. */
  53. export
  54. function wrapSelect(node: HTMLSelectElement): HTMLElement {
  55. let wrapper = document.createElement('div');
  56. wrapper.classList.add('jp-select-wrapper');
  57. node.addEventListener('focus', Private.onFocus);
  58. node.addEventListener('blur', Private.onFocus);
  59. node.classList.add('jp-mod-styled');
  60. if (node.parentElement) {
  61. node.parentElement.replaceChild(wrapper, node);
  62. }
  63. wrapper.appendChild(node);
  64. return wrapper;
  65. }
  66. }
  67. /**
  68. * The namespace for module private data.
  69. */
  70. namespace Private {
  71. /**
  72. * Handle a focus event on a styled select.
  73. */
  74. export
  75. function onFocus(event: FocusEvent): void {
  76. let target = event.target as Element;
  77. let parent = target.parentElement;
  78. if (event.type === 'focus') {
  79. parent.classList.add('jp-mod-focused');
  80. } else {
  81. parent.classList.remove('jp-mod-focused');
  82. }
  83. }
  84. }