StrictDoc Documentation
strictdoc/export/html/_static/diff.js
Source file coverage
Path:
strictdoc/export/html/_static/diff.js
Lines:
159
Non-empty lines:
129
Non-empty lines covered with requirements:
129 / 129 (100.0%)
Functions:
0
Functions covered by requirements:
0 / 0 (0.0%)
1
//
2
// @relation(SDOC-SRS-111, scope=file)
3
//
4
 
5
(function () {
6
window.addEventListener("load",function(){
7
 
8
    const mutatingFrame = document.querySelector('#diff_result');
9
 
10
    var observer = new MutationObserver(function (mutationsList, observer) {
11
 
12
      const diffTabRoot = mutatingFrame.querySelector('.diff');
13
      if (diffTabRoot) {
14
        // triggers on the diff tab
15
        prepareBulkButtons(diffTabRoot);
16
        syncDiff(diffTabRoot);
17
      }
18
 
19
      // Disable the observer after the first trigger
20
      // because the functions modify the elements inside the #diff_result.
21
      observer.disconnect();
22
    });
23
 
24
    observer.observe(
25
      mutatingFrame,
26
      {
27
        childList: true,
28
        subtree: true
29
      }
30
    );
31
 
32
},false);
33
 
34
function prepareBulkButtons(root) {
35
 
36
  const leftColumn = root.querySelector('.diff_column[left]');
37
  const rightColumn = root.querySelector('.diff_column[right]');
38
 
39
  const leftOpenBtn = root.querySelector('#diff_left_open');
40
  const leftCloseBtn = root.querySelector('#diff_left_close');
41
  const rightOpenBtn = root.querySelector('#diff_right_open');
42
  const rightCloseBtn = root.querySelector('#diff_right_close');
43
 
44
  const detailsLeftAll = [...leftColumn.querySelectorAll('details')];
45
  const detailsRightAll = [...rightColumn.querySelectorAll('details')];
46
  const detailsLeft = [...leftColumn.querySelectorAll('details[modified]')];
47
  const detailsRight = [...rightColumn.querySelectorAll('details[modified]')];
48
 
49
  leftOpenBtn.addEventListener("click", (event) => {
50
    event.preventDefault();
51
    _openAll(detailsLeft);
52
  });
53
  leftCloseBtn.addEventListener("click", (event) => {
54
    event.preventDefault();
55
    _closeAll(detailsLeftAll);
56
    leftColumn.scrollTo(0, 0);
57
  });
58
  rightOpenBtn.addEventListener("click", (event) => {
59
    event.preventDefault();
60
    _openAll(detailsRight);
61
  });
62
  rightCloseBtn.addEventListener("click", (event) => {
63
    event.preventDefault();
64
    _closeAll(detailsRightAll);
65
    rightColumn.scrollTo(0, 0);
66
  });
67
}
68
 
69
function syncDiff(root) {
70
 
71
  const sync = [...root.querySelectorAll('button[uid]')]
72
  .reduce((acc, curr) => {
73
    const uid = curr.getAttribute('uid');
74
    const side = curr.getAttribute('side');
75
    acc[uid] = {
76
      [side]: curr,
77
      ...acc[uid]
78
    }
79
    return acc
80
  },{});
81
 
82
  Object.entries(sync).forEach(([uid, obj]) => {
83
    if (!obj.left) {
84
      obj.right.remove()
85
      return
86
    };
87
 
88
    if (!obj.right) {
89
      obj.left.remove()
90
      return
91
    };
92
 
93
    obj.left.addEventListener("click", (event) => {
94
      event.preventDefault();
95
 
96
      // _openAll(detailsLeftAll);
97
      _openAncestors(obj.left, root);
98
      _scrollTo(obj.left);
99
 
100
      setTimeout(() => {
101
        // _openAll(detailsRightAll);
102
        _openAncestors(obj.right, root);
103
        _scrollTo(obj.right);
104
      }, 900);
105
    });
106
 
107
    obj.right.addEventListener("click", (event) => {
108
      event.preventDefault();
109
 
110
      // _openAll(detailsRightAll);
111
      _openAncestors(obj.right, root);
112
      _scrollTo(obj.right);
113
 
114
      setTimeout(() => {
115
        // _openAll(detailsLeftAll);
116
        _openAncestors(obj.left, root);
117
        _scrollTo(obj.left);
118
      }, 900);
119
    });
120
  })
121
};
122
 
123
function _openAncestors(element, root) {
124
 
125
  let currentElement = element;
126
 
127
  while (currentElement && currentElement !== root) {
128
    currentElement = currentElement.parentElement;
129
 
130
    if (currentElement && currentElement.tagName === 'DETAILS') {
131
      currentElement.setAttribute('open', '');
132
    }
133
  }
134
};
135
 
136
function _scrollTo(target) {
137
  // We insert a special element into the button ('button[uid]')
138
  // that compensates by 40 pixels
139
  // for the height of the sticky header
140
  // at the top of the scroll container:
141
  // ***
142
  // <a-a style="position:absolute;top:-40px;"></a-a>
143
 
144
  const a = target.querySelector('a-a') || target;
145
  a.scrollIntoView({ behavior: "smooth" });
146
};
147
 
148
function _closeAll(details) {
149
  details.forEach(detail => {
150
    detail.removeAttribute("open")
151
  });
152
};
153
 
154
function _openAll(details) {
155
  details.forEach(detail => {
156
    detail.setAttribute("open", "")
157
  });
158
};
159
})();