Version 1
[yaffs-website] / web / modules / contrib / devel / kint / kint / view / base.js
1 /**
2  java -jar compiler.jar --js $FileName$ --js_output_file ../inc/kint.js --compilation_level ADVANCED_OPTIMIZATIONS --output_wrapper "(function(){%output%})()"
3  */
4
5 if ( typeof kintInitialized === 'undefined' ) {
6         kintInitialized = 1;
7         var kint = {
8                 visiblePluses : [], // all visible toggle carets
9                 currentPlus   : -1, // currently selected caret
10
11                 selectText : function( element ) {
12                         var selection = window.getSelection(),
13                             range = document.createRange();
14
15                         range.selectNodeContents(element);
16                         selection.removeAllRanges();
17                         selection.addRange(range);
18                 },
19
20                 each : function( selector, callback ) {
21                         Array.prototype.slice.call(document.querySelectorAll(selector), 0).forEach(callback)
22                 },
23
24                 hasClass : function( target, className ) {
25                         if ( !target.classList ) return false;
26
27                         if ( typeof className === 'undefined' ) {
28                                 className = 'kint-show';
29                         }
30                         return target.classList.contains(className);
31                 },
32
33                 addClass : function( target, className ) {
34                         if ( typeof className === 'undefined' ) {
35                                 className = 'kint-show';
36                         }
37                         target.classList.add(className);
38                 },
39
40                 removeClass : function( target, className ) {
41                         if ( typeof className === 'undefined' ) {
42                                 className = 'kint-show';
43                         }
44                         target.classList.remove(className);
45                         return target;
46                 },
47
48                 next : function( element ) {
49                         do {
50                                 element = element.nextElementSibling;
51                         } while ( element.nodeName.toLowerCase() !== 'dd' );
52
53                         return element;
54                 },
55
56                 toggle : function( element, hide ) {
57                         var parent = kint.next(element);
58
59                         if ( typeof hide === 'undefined' ) {
60                                 hide = kint.hasClass(element);
61                         }
62
63                         if ( hide ) {
64                                 kint.removeClass(element);
65                         } else {
66                                 kint.addClass(element);
67                         }
68
69                         if ( parent.childNodes.length === 1 ) {
70                                 parent = parent.childNodes[0].childNodes[0]; // reuse variable cause I can
71
72                                 // parent is checked in case of empty <pre> when array("\n") is dumped
73                                 if ( parent && kint.hasClass(parent, 'kint-parent') ) {
74                                         kint.toggle(parent, hide)
75                                 }
76                         }
77                 },
78
79                 toggleChildren : function( element, hide ) {
80                         var parent = kint.next(element)
81                                 , nodes = parent.getElementsByClassName('kint-parent')
82                                 , i = nodes.length;
83
84                         if ( typeof hide === 'undefined' ) {
85                                 hide = kint.hasClass(element);
86                         }
87
88                         while ( i-- ) {
89                                 kint.toggle(nodes[i], hide);
90                         }
91                         kint.toggle(element, hide);
92                 },
93
94                 toggleAll : function( caret ) {
95                         var elements = document.getElementsByClassName('kint-parent')
96                                 , i = elements.length
97                                 , visible = kint.hasClass(caret.parentNode);
98
99                         while ( i-- ) {
100                                 kint.toggle(elements[i], visible);
101                         }
102                 },
103
104                 switchTab : function( target ) {
105                         var lis, el = target, index = 0;
106
107                         target.parentNode.getElementsByClassName('kint-active-tab')[0].className = '';
108                         target.className = 'kint-active-tab';
109
110                         // take the index of clicked title tab and make the same n-th content tab visible
111                         while ( el = el.previousSibling ) el.nodeType === 1 && index++;
112                         lis = target.parentNode.nextSibling.childNodes;
113                         for ( var i = 0; i < lis.length; i++ ) {
114                                 if ( i === index ) {
115                                         lis[i].style.display = 'block';
116
117                                         if ( lis[i].childNodes.length === 1 ) {
118                                                 el = lis[i].childNodes[0].childNodes[0];
119
120                                                 if ( kint.hasClass(el, 'kint-parent') ) {
121                                                         kint.toggle(el, false)
122                                                 }
123                                         }
124                                 } else {
125                                         lis[i].style.display = 'none';
126                                 }
127                         }
128                 },
129
130                 isSibling : function( el ) {
131                         for ( ; ; ) {
132                                 el = el.parentNode;
133                                 if ( !el || kint.hasClass(el, 'kint') ) break;
134                         }
135
136                         return !!el;
137                 },
138
139                 fetchVisiblePluses : function() {
140                         kint.visiblePluses = [];
141                         kint.each('.kint nav, .kint-tabs>li:not(.kint-active-tab)', function( el ) {
142                                 if ( el.offsetWidth !== 0 || el.offsetHeight !== 0 ) {
143                                         kint.visiblePluses.push(el)
144                                 }
145                         });
146                 },
147
148                 openInNewWindow : function( kintContainer ) {
149                         var newWindow;
150
151                         if ( newWindow = window.open() ) {
152                                 newWindow.document.open();
153                                 newWindow.document.write(
154                                         '<html>'
155                                         + '<head>'
156                                         + '<title>Kint (' + new Date().toISOString() + ')</title>'
157                                         + '<meta charset="utf-8">'
158                                         + document.getElementsByClassName('-kint-js')[0].outerHTML
159                                         + document.getElementsByClassName('-kint-css')[0].outerHTML
160                                         + '</head>'
161                                         + '<body>'
162                                         + '<input style="width: 100%" placeholder="Take some notes!">'
163                                         + '<div class="kint">'
164                                         + kintContainer.parentNode.outerHTML
165                                         + '</div></body>'
166                                 );
167                                 newWindow.document.close();
168                         }
169                 },
170
171                 sortTable : function( table, column ) {
172                         var tbody = table.tBodies[0];
173
174                         var format = function( s ) {
175                                 var n = column === 1 ? s.replace(/^#/, '') : s;
176                                 if ( isNaN(n) ) {
177                                         return s.trim().toLocaleLowerCase();
178                                 } else {
179                                         n = parseFloat(n);
180                                         return isNaN(n) ? s.trim() : n;
181                                 }
182                         };
183
184
185                         [].slice.call(table.tBodies[0].rows)
186                                 .sort(function( a, b ) {
187                                         a = format(a.cells[column].textContent);
188                                         b = format(b.cells[column].textContent);
189                                         if ( a < b ) return -1;
190                                         if ( a > b ) return 1;
191
192                                         return 0;
193                                 })
194                                 .forEach(function( el ) {
195                                         tbody.appendChild(el);
196                                 });
197                 },
198
199                 keyCallBacks : {
200                         cleanup : function( i ) {
201                                 var focusedClass = 'kint-focused';
202                                 var prevElement = document.querySelector('.' + focusedClass);
203                                 prevElement && kint.removeClass(prevElement, focusedClass);
204
205                                 if ( i !== -1 ) {
206                                         var el = kint.visiblePluses[i];
207                                         kint.addClass(el, focusedClass);
208
209
210                                         var offsetTop = function( el ) {
211                                                 return el.offsetTop + ( el.offsetParent ? offsetTop(el.offsetParent) : 0 );
212                                         };
213
214                                         var top = offsetTop(el) - (window.innerHeight / 2 );
215                                         window.scrollTo(0, top);
216                                 }
217
218                                 kint.currentPlus = i;
219                         },
220
221                         moveCursor : function( up, i ) {
222                                 // todo make the first VISIBLE plus active
223                                 if ( up ) {
224                                         if ( --i < 0 ) {
225                                                 i = kint.visiblePluses.length - 1;
226                                         }
227                                 } else {
228                                         if ( ++i >= kint.visiblePluses.length ) {
229                                                 i = 0;
230                                         }
231                                 }
232
233                                 kint.keyCallBacks.cleanup(i);
234                                 return false;
235                         }
236                 }
237         };
238
239         window.addEventListener("click", function( e ) {
240                 var target = e.target
241                         , nodeName = target.nodeName.toLowerCase();
242
243                 if ( !kint.isSibling(target) ) return;
244
245                 // auto-select name of variable
246                 if ( nodeName === 'dfn' ) {
247                         kint.selectText(target);
248                         target = target.parentNode;
249                 } else if ( nodeName === 'var' ) { // stupid workaround for misc elements
250                         target = target.parentNode;    // to not stop event from further propagating
251                         nodeName = target.nodeName.toLowerCase()
252                 } else if ( nodeName === 'th' ) {
253                         if ( !e.ctrlKey ) {
254                                 kint.sortTable(target.parentNode.parentNode.parentNode, target.cellIndex)
255                         }
256                         return false;
257                 }
258
259                 // switch tabs
260                 if ( nodeName === 'li' && target.parentNode.className === 'kint-tabs' ) {
261                         if ( target.className !== 'kint-active-tab' ) {
262                                 kint.switchTab(target);
263                                 if ( kint.currentPlus !== -1 ) kint.fetchVisiblePluses();
264                         }
265                         return false;
266                 }
267
268                 // handle clicks on the navigation caret
269                 if ( nodeName === 'nav' ) {
270                         // special case for nav in footer
271                         if ( target.parentNode.nodeName.toLowerCase() === 'footer' ) {
272                                 target = target.parentNode;
273                                 if ( kint.hasClass(target) ) {
274                                         kint.removeClass(target)
275                                 } else {
276                                         kint.addClass(target)
277                                 }
278                         } else {
279                                 // ensure doubleclick has different behaviour, see below
280                                 setTimeout(function() {
281                                         var timer = parseInt(target.kintTimer, 10);
282                                         if ( timer > 0 ) {
283                                                 target.kintTimer--;
284                                         } else {
285                                                 kint.toggleChildren(target.parentNode); // <dt>
286                                                 if ( kint.currentPlus !== -1 ) kint.fetchVisiblePluses();
287                                         }
288                                 }, 300);
289                         }
290
291                         e.stopPropagation();
292                         return false;
293                 } else if ( kint.hasClass(target, 'kint-parent') ) {
294                         kint.toggle(target);
295                         if ( kint.currentPlus !== -1 ) kint.fetchVisiblePluses();
296                         return false;
297                 } else if ( kint.hasClass(target, 'kint-ide-link') ) {
298                         e.preventDefault();
299                         var ajax = new XMLHttpRequest(); // add ajax call to contact editor but prevent link default action
300                         ajax.open('GET', target.href);
301                         ajax.send(null);
302                         return false;
303                 } else if ( kint.hasClass(target, 'kint-popup-trigger') ) {
304                         var kintContainer = target.parentNode;
305                         if ( kintContainer.nodeName.toLowerCase() === 'footer' ) {
306                                 kintContainer = kintContainer.previousSibling;
307                         } else {
308                                 while ( kintContainer && !kint.hasClass(kintContainer, 'kint-parent') ) {
309                                         kintContainer = kintContainer.parentNode;
310                                 }
311                         }
312
313                         kint.openInNewWindow(kintContainer);
314                 } else if ( nodeName === 'pre' && e.detail === 3 ) { // triple click pre to select it all
315                         kint.selectText(target);
316                 }
317         }, false);
318
319         window.addEventListener("dblclick", function( e ) {
320                 var target = e.target;
321                 if ( !kint.isSibling(target) ) return;
322
323                 if ( target.nodeName.toLowerCase() === 'nav' ) {
324                         target.kintTimer = 2;
325                         kint.toggleAll(target);
326                         if ( kint.currentPlus !== -1 ) kint.fetchVisiblePluses();
327                         e.stopPropagation();
328                 }
329         }, false);
330
331         // keyboard navigation
332         window.onkeydown = function( e ) { // direct assignment is used to have priority over ex FAYT
333
334                 // do nothing if alt/ctrl key is pressed or if we're actually typing somewhere
335                 if ( e.target !== document.body || e.altKey || e.ctrlKey ) return;
336
337                 var keyCode = e.keyCode
338                         , shiftKey = e.shiftKey
339                         , i = kint.currentPlus;
340
341
342                 if ( keyCode === 68 ) { // 'd' : toggles navigation on/off
343                         if ( i === -1 ) {
344                                 kint.fetchVisiblePluses();
345                                 return kint.keyCallBacks.moveCursor(false, i);
346                         } else {
347                                 kint.keyCallBacks.cleanup(-1);
348                                 return false;
349                         }
350                 } else {
351                         if ( i === -1 ) return;
352
353                         if ( keyCode === 9 ) { // TAB : moves up/down depending on shift key
354                                 return kint.keyCallBacks.moveCursor(shiftKey, i);
355                         } else if ( keyCode === 38 ) { // ARROW UP : moves up
356                                 return kint.keyCallBacks.moveCursor(true, i);
357                         } else if ( keyCode === 40 ) { // ARROW DOWN : down
358                                 return kint.keyCallBacks.moveCursor(false, i);
359                         }
360                 }
361
362
363                 var kintNode = kint.visiblePluses[i];
364                 if ( kintNode.nodeName.toLowerCase() === 'li' ) { // we're on a trace tab
365                         if ( keyCode === 32 || keyCode === 13 ) { // SPACE/ENTER
366                                 kint.switchTab(kintNode);
367                                 kint.fetchVisiblePluses();
368                                 return kint.keyCallBacks.moveCursor(true, i);
369                         } else if ( keyCode === 39 ) { // arrows
370                                 return kint.keyCallBacks.moveCursor(false, i);
371                         } else if ( keyCode === 37 ) {
372                                 return kint.keyCallBacks.moveCursor(true, i);
373                         }
374                 }
375
376                 kintNode = kintNode.parentNode; // simple dump
377                 if ( keyCode === 32 || keyCode === 13 ) { // SPACE/ENTER : toggles
378                         kint.toggle(kintNode);
379                         kint.fetchVisiblePluses();
380                         return false;
381                 } else if ( keyCode === 39 || keyCode === 37 ) { // ARROW LEFT/RIGHT : respectively hides/shows and traverses
382                         var visible = kint.hasClass(kintNode);
383                         var hide = keyCode === 37;
384
385                         if ( visible ) {
386                                 kint.toggleChildren(kintNode, hide); // expand/collapse all children if immediate ones are showing
387                         } else {
388                                 if ( hide ) { // LEFT
389                                         // traverse to parent and THEN hide
390                                         do {kintNode = kintNode.parentNode} while ( kintNode && kintNode.nodeName.toLowerCase() !== 'dd' );
391
392                                         if ( kintNode ) {
393                                                 kintNode = kintNode.previousElementSibling;
394
395                                                 i = -1;
396                                                 var parentPlus = kintNode.querySelector('nav');
397                                                 while ( parentPlus !== kint.visiblePluses[++i] ) {}
398                                                 kint.keyCallBacks.cleanup(i)
399                                         } else { // we are at root
400                                                 kintNode = kint.visiblePluses[i].parentNode;
401                                         }
402                                 }
403                                 kint.toggle(kintNode, hide);
404                         }
405                         kint.fetchVisiblePluses();
406                         return false;
407                 }
408         };
409
410         window.addEventListener("load", function( e ) { // colorize microtime results relative to others
411                 var elements = Array.prototype.slice.call(document.querySelectorAll('.kint-microtime'), 0);
412                 elements.forEach(function( el ) {
413                         var value = parseFloat(el.innerHTML)
414                                 , min = Infinity
415                                 , max = -Infinity
416                                 , ratio;
417
418                         elements.forEach(function( el ) {
419                                 var val = parseFloat(el.innerHTML);
420
421                                 if ( min > val ) min = val;
422                                 if ( max < val ) max = val;
423                         });
424
425                         ratio = 1 - (value - min) / (max - min);
426
427                         el.style.background = 'hsl(' + Math.round(ratio * 120) + ',60%,70%)';
428                 });
429         });
430 }
431
432 // debug purposes only, removed in minified source
433 function clg( i ) {
434         if ( !window.console )return;
435         var l = arguments.length, o = 0;
436         while ( o < l )console.log(arguments[o++])
437 }