File size: 2,487 Bytes
f5f3483
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
 * @fileoverview Tree manager.
 */

/**
 * Load the inner html of a node.
 * @param {string} id_ HTML id of the node
 */
async function load_content(id_) {
  const root = document.getElementById(id_);

  // Guard to only load the content once
  if (!root.classList.contains('etils-loaded')) {
    root.classList.add('etils-loaded');

    // Compute the HTML content in Python
    const html_content = await call_python('get_html_content', [root.id]);

    // Insert at the end, without destroying the one-line content
    root.insertAdjacentHTML('beforeend', html_content);

    // Register listeners for all newly added children
    registerChildrenEvent(root);
  }
}

/**
 * Function which execute the callback.
 * @typedef {function():void} EventCallback
 */

/**
 * Register listerner for all element matching the class name.
 *
 * @param {!HTMLElement} elem Root element to which add the listener
 * @param {string} class_name Class for which add the listener
 * @param {!EventCallback} callback Function to call.
 */
function registerClickListenerOnAll(elem, class_name, callback) {
  const children = elem.querySelectorAll(`.${class_name}`);
  for (const child of children) {
    child.classList.remove(class_name);
    child.addEventListener('click', function(event) {
      // Only one click processed if multiple (nested) listener
      event.stopPropagation();

      // Do not process the click if text is selected
      const selection = document.getSelection();
      if (selection.type === 'Range') {
        return;
      }

      callback.bind(this)();
    });
  }
}

/**
 * Register all listerners for all children.
 * @param {!HTMLElement} elem Root element to which add the listener
 */
function registerChildrenEvent(elem) {
  registerClickListenerOnAll(
      elem, 'etils-register-onclick-expand', async function() {
        // TODO(epot): As optimization, it's not required to query the id
        // each time, but instead use closure.
        // TODO(epot): Is there a way to only call this once ?
        await load_content(this.parentElement.id);

        // Toogle the collapsible section
        this.parentElement.querySelector('.etils-collapsible')
            .classList.toggle('etils-collapsible-active');
        this.classList.toggle('etils-caret-down');
      });

  registerClickListenerOnAll(elem, 'etils-register-onclick-switch', function() {
    this.closest('.etils-content-switch')
        .classList.toggle('etils-switch-active');
  });
}