PageSourceSearch

https://www.nhft.nhs.uk/js/reporttree.js

js nhft.nhs.uk collected 2026-09-26 01:08:48 UTC 8,638 bytes, 280 lines download raw bytes

1(function (app) {
2
3  "use strict";
4
5  var handler = '/handlers/report-tree.cfm';
6  var rxNodeInURL = /rtnode=([a-zA-Z0-9\-\_]+)&?/g;
7  var rxPageURL = /page=([a-zA-Z0-9\-]+)&?/g;
8  var rxFindHeaderId = /headerid/gi;
9  var rxCleanString = /[^A-Za-z0-9\-\_]/gi;
10  var slug;
11  var canNavigateNodes = window.location.search.toLowerCase().indexOf("headerid") < 0;
12
13  app.reporttree = (function () {
14    //pagename could be in url
15    if(window.location.pathname.length > 1){
16      slug = window.location.pathname.substr(1);
17    }else{
18      var tempslug = rxPageURL.exec(window.location.href);
19      if(tempslug && tempslug.length > 0){
20        slug = tempslug[1];
21      }
22    }
23
24    //we have to look for the node in the URL becuase of forms
25    var nodeInURL = rxNodeInURL.exec(window.location.search);
26    if(nodeInURL && nodeInURL.length > 0){
27      var newURL = window.location.href.replace("rtnode=" + nodeInURL[1], "&") + '#' + nodeInURL[1];
28      newURL = newURL.replace('?&&','?');
29      window.location.replace(newURL);
30      // Add scroll position after URL replacement
31      setTimeout(function() {
32        const $targetNode = $('#' + nodeInURL[1]);
33        if ($targetNode.length) {
34          const nodeOffset = $targetNode[0].getBoundingClientRect().top + window.scrollY - 200;
35          window.scrollTo({ top: nodeOffset, behavior: 'smooth' });
36        }
37      }, 300); // Increased timeout to ensure page has loaded
38      return;
39    }
40
41    $('[data-rtroot]').each(function(){
42      new Tree($(this));
43    });
44  }());
45
46
47  function addHashToFormActions(){
48    $('form#classic-form-0').each(function(){
49      var formAction = $(this).attr("action");
50      if(formAction.indexOf("#")>=0){
51        formAction = formAction.split('#')[0];
52      }
53      formAction = formAction+window.location.hash;
54      $(this).attr("action",formAction);
55    });
56
57  }
58
59
60  function cleanString(s){
61    if(!s){
62      return "";
63    }
64    return s.replace(rxCleanString,"");
65  }
66
67  function Tree($tree){
68    var tree = this;
69    var treeName = cleanString($tree.data('rttreename')) + '-';
70
71    addHashToFormActions();
72
73    $tree.find('[data-rtnodehead]').click(clickedNode);
74    $tree.find('[data-rtbackup]').click(clickedBack);
75    
76    $( ".rt-node-back" ).click(function(e) {
77      e.preventDefault();
78      goToTopLevelParent();
79    });
80
81    if(window.location.hash && window.location.hash.length > 0){
82      var temphash = window.location.hash.split('#').pop();
83      setTimeout(function() {
84        findNode('#' + temphash);
85        const $targetNode = $('#' + temphash);
86        if ($targetNode.length) {
87          const nodeOffset = $targetNode[0].getBoundingClientRect().top + window.scrollY - 200;
88          window.scrollTo({ top: nodeOffset, behavior: 'smooth' });
89        }
90      }, 100);
91    }
92
93    function findNode(id){
94      var $node = $(id);
95      var path = getPath($node);
96      path.path.forEach(function(v){
97        expandNode(path.nodes[v]);
98      });
99      while($node.length == 1){
100        $node = $node.parent().closest('[data-rtnode]');
101      }
102    }
103
104    function getFormWrapper($node){
105      return $node.children('[data-rtnodebody]').first().children('[data-rtnodeform]')
106    }
107
108    function clickedNode(ev){
109      ev.preventDefault();
110      ev.stopPropagation();
111      if(!canNavigateNodes){ return false; }
112      var $node = $(this).closest('[data-rtnode]');
113      if($node.hasClass('rt-node-expanded')){
114          goBack($node);
115      }else{
116        expandNode($node);
117      }
118    }
119
120    function clickedBack(ev){
121      ev.preventDefault();
122      ev.stopPropagation();
123      if(!canNavigateNodes){ return false; }
124      goBack($(this).closest('[data-rtnode]'));
125    }
126
127    function goBack($node){
128      collapseOthers($node);
129      $node
130        .find('[data-rtnode]')
131        .each(function(ev){
132        collapseNode($(this));
133      });
134      collapseNode($node);
135      var $parent =$node.parent().closest('[data-rtnode]');
136      if($parent.length > 0){
137        expandNode($parent);
138      }else{
139        history.pushState(null,null," ");
140        addHashToFormActions();
141      }
142    }
143
144    function goToTopLevelParent() {
145      var $topLevelNode = $('[data-rtroot]');
146
147      if ($topLevelNode.length > 0) {
148        collapseOthers($topLevelNode);
149        expandNode($topLevelNode);
150        history.pushState(null, null, " ");
151        addHashToFormActions();
152      }
153    }
154
155    function expandNode($node){
156      collapseOthers($node);
157      hideSiblings($node);
158      if(history.pushState){
159        history.pushState(null,null,"#" + $node.attr('id'));
160        addHashToFormActions();
161      }
162      $node.parent('li').addClass('expanded');
163      $node.addClass('rt-node-expanded');
164      $node.children('[data-rtnodebody].hidden').removeClass('hidden');
165      var $formWrapper = getFormWrapper($node);
166      if($formWrapper.length == 1){
167        fetchClassicForm($formWrapper);
168      }
169      $node.focus();
170      const nodeOffset = $node[0].getBoundingClientRect().top + window.scrollY - 200;
171      window.scrollTo({ top: nodeOffset, behavior: 'smooth' });
172    }
173
174    function collapseNode($node){
175      $node.children('[data-rtnodebody]').addClass('hidden');
176      $node.parent('li').removeClass('expanded');
177      $node.removeClass('rt-node-expanded');
178      getFormWrapper($node).empty();
179      showSiblings($node);
180    }
181
182    function hideSiblings($node){
183      $node.parent().siblings().addClass('hidden');
184    }
185    function showSiblings($node){
186      $node.parent().siblings().removeClass('hidden');
187    }
188
189    function collapseOthers($node){
190      var allowed
191      , $n
192      , $expanded = $tree.find('[data-rtnodebody]:not(hidden)').closest('[data-rtnode]');
193
194      if($expanded.length==0){ return; }
195
196      allowed = getPath($node).nodes;
197      $expanded.each(function(){
198        $n = $(this);
199        if(allowed[$n.data['rtkey']]){
200          collapseNode($n)
201        }
202      });
203    }
204
205    function getPath($node){
206      var path={path:[],nodes:{}};
207      var key = $node.data('rtkey');
208      path.path.push(key);
209      path.nodes[key]=$node;
210      var $parent = $node.parent().closest('[data-rtnode]');
211      while($parent.length > 0){
212        key = $parent.data('rtkey');
213        path.path.unshift(key);
214        path.nodes[key]=$parent;
215        $parent = $parent.parent().closest('[data-rtnode]');
216      }
217      return path;
218    }
219
220    function fetchClassicForm($wrapper){
221      var toURL = handler + '?act=fetchClassicForm&';
222
223      // convert node to url as classicforms cant handle hashurls :@
224      var targetNode = cleanString(window.location.hash.substring(1));
225      var nodeAsURLVar = 'rtnode=' + targetNode;
226      toURL += nodeAsURLVar;
227      rxFindHeaderId.lastIndex=0;
228      if(rxFindHeaderId.exec(window.location.search)){
229        toURL += '&' + window.location.search.substring(1); // add current urlstate
230      }else{
231        toURL += '&form=' + $wrapper.data('rtnodeform') + '&';
232      }
233
234      var reportTreeFieldValue = window.location.origin + '/' + slug + '#' + targetNode;
235
236      //var urlPath = window.location.pathname;
237      //var qs = JSON.parse('{"' + decodeURI(window.location.search.substring(1)).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}');
238
239      $.ajax({
240        dataType:"json"
241        , method:"GET"
242        , url:toURL
243        , success: function(json){
244          $wrapper
245            .empty()
246            .append(json.body);
247          $wrapper
248            .find('[data-rtbuttonrestart]')
249            .attr('href',window.location.origin + '/' + slug);
250          $wrapper
251            .find('[data-rtformfield]')
252            .val(reportTreeFieldValue);
253          $wrapper
254            .find('input[name=Referer]')
255            .val(window.location.origin + '/' + slug + '?' + nodeAsURLVar + "&");
256
257          //post forms to the handler
258          var $form = $wrapper.find('form');
259          if(!$form.attr('action')){
260            // form assumes we post back here!
261            var slugAsURLVar = "page=" + slug;
262            var search = window.location.search.substr(1).replace(slugAsURLVar,'').replace(nodeAsURLVar) + "&";
263            search += nodeAsURLVar + '&' + slugAsURLVar;
264            $form.append('<input name="referrer_override" value="/?'+search+'" type="hidden"/>');
265            search += "&act=forwardClassicform";
266            search = search.replace('&&','&');
267            $form.attr('action',handler + "?" + search);
268            addHashToFormActions();
269          }
270
271          // call for the form to be initialised on classic-forms.js
272          app.FormsValidation.initForm($form);
273
274        }
275      });
276    }
277
278  }// end Tree
279
280}(Atlas));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.