@@ -184,6 +184,81 @@ function toggle(a, recursive) {
184
184
return true;
185
185
};
186
186
187
+ function collapse(a, recursive) {
188
+ var s = a.nextSibling || {}, oldClass = s.className;
189
+
190
+ if ('sf-dump-expanded' == oldClass) {
191
+ toggle(a, recursive);
192
+
193
+ return true;
194
+ }
195
+
196
+ return false;
197
+ };
198
+
199
+ function expand(a, recursive) {
200
+ var s = a.nextSibling || {}, oldClass = s.className;
201
+
202
+ if ('sf-dump-compact' == oldClass) {
203
+ toggle(a, recursive);
204
+
205
+ return true;
206
+ }
207
+
208
+ return false;
209
+ };
210
+
211
+ function collapseAll(root) {
212
+ var a = root.querySelector('a.sf-dump-toggle');
213
+ if (a) {
214
+ collapse(a, true);
215
+ expand(a);
216
+
217
+ return true;
218
+ }
219
+
220
+ return false;
221
+ }
222
+
223
+ function reveal(node) {
224
+ var previous, parents = [];
225
+
226
+ while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) {
227
+ parents.push(previous);
228
+ }
229
+
230
+ if (0 !== parents.length) {
231
+ parents.forEach(function (parent) {
232
+ expand(parent);
233
+ });
234
+
235
+ return true;
236
+ }
237
+
238
+ return false;
239
+ }
240
+
241
+ function highlight(root, activeNode, nodes) {
242
+ resetHighlightedNodes(root);
243
+
244
+ Array.from(nodes||[]).forEach(function (node) {
245
+ if (!/\bsf-dump-highlight\b/.test(node.className)) {
246
+ node.className = node.className + ' sf-dump-highlight';
247
+ }
248
+ });
249
+
250
+ if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) {
251
+ activeNode.className = activeNode.className + ' sf-dump-highlight-active';
252
+ }
253
+ }
254
+
255
+ function resetHighlightedNodes(root) {
256
+ Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) {
257
+ strNode.className = strNode.className.replace(/\b sf-dump-highlight\b/, '');
258
+ strNode.className = strNode.className.replace(/\b sf-dump-highlight-active\b/, '');
259
+ });
260
+ }
261
+
187
262
return function (root, x) {
188
263
root = doc.getElementById(root);
189
264
@@ -214,6 +289,20 @@ function a(e, f) {
214
289
function isCtrlKey(e) {
215
290
return e.ctrlKey || e.metaKey;
216
291
}
292
+ function xpathString(str) {
293
+ var parts = str.match(/[^'"]+|['"]/g).map(function (part) {
294
+ if ("'" == part) {
295
+ return '"\'"';
296
+ }
297
+ if ('"' == part) {
298
+ return "'\"'";
299
+ }
300
+
301
+ return "'" + part + "'";
302
+ });
303
+
304
+ return "concat(" + parts.join(",") + ", '')";
305
+ }
217
306
addEventListener(root, 'mouseover', function (e) {
218
307
if ('' != refStyle.innerHTML) {
219
308
refStyle.innerHTML = '';
@@ -324,6 +413,134 @@ function isCtrlKey(e) {
324
413
}
325
414
}
326
415
416
+ if (doc.evaluate && Array.from && root.children.length > 1) {
417
+ root.setAttribute('tabindex', 0);
418
+
419
+ SearchState = function () {
420
+ this.nodes = [];
421
+ this.idx = 0;
422
+ };
423
+ SearchState.prototype = {
424
+ next: function () {
425
+ if (this.isEmpty()) {
426
+ return this.current();
427
+ }
428
+ this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : this.idx;
429
+
430
+ return this.current();
431
+ },
432
+ previous: function () {
433
+ if (this.isEmpty()) {
434
+ return this.current();
435
+ }
436
+ this.idx = this.idx > 0 ? this.idx - 1 : this.idx;
437
+
438
+ return this.current();
439
+ },
440
+ isEmpty: function () {
441
+ return 0 === this.count();
442
+ },
443
+ current: function () {
444
+ if (this.isEmpty()) {
445
+ return null;
446
+ }
447
+ return this.nodes[this.idx];
448
+ },
449
+ reset: function () {
450
+ this.nodes = [];
451
+ this.idx = 0;
452
+ },
453
+ count: function () {
454
+ return this.nodes.length;
455
+ },
456
+ };
457
+
458
+ function showCurrent(state)
459
+ {
460
+ var currentNode = state.current();
461
+ if (currentNode) {
462
+ reveal(currentNode);
463
+ highlight(root, currentNode, state.nodes);
464
+ }
465
+ counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' on ' + state.count();
466
+ }
467
+
468
+ var search = doc.createElement('div');
469
+ search.className = 'sf-dump-search-wrapper sf-dump-search-hidden';
470
+ search.innerHTML = '
471
+ <input type="text" class="sf-dump-search-input">
472
+ <span class="sf-dump-search-count">0 on 0<\/span>
473
+ <button type="button" class="sf-dump-search-input-previous" tabindex="-1">
474
+ <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
475
+ <path d="M1683 1331l-166 165q-19 19-45 19t-45-19l-531-531-531 531q-19 19-45 19t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19 45-19t45 19l742 741q19 19 19 45.5t-19 45.5z"\/>
476
+ <\/svg>
477
+ <\/button>
478
+ <button type="button" class="sf-dump-search-input-next" tabindex="-1">
479
+ <svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
480
+ <path d="M1683 808l-742 741q-19 19-45 19t-45-19l-742-741q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z"\/>
481
+ <\/svg>
482
+ <\/button>
483
+ ';
484
+ root.insertBefore(search, root.firstChild);
485
+
486
+ var state = new SearchState();
487
+ var searchInput = search.querySelector('.sf-dump-search-input');
488
+ var counter = search.querySelector('.sf-dump-search-count');
489
+ var searchInputTimer = 0;
490
+
491
+ addEventListener(searchInput, 'keydown', function (e) {
492
+ /* Don't intercept escape key in order to not start a search */
493
+ if (27 === e.keyCode) {
494
+ return;
495
+ }
496
+
497
+ clearTimeout(searchInputTimer);
498
+ searchInputTimer = setTimeout(function () {
499
+ state.reset();
500
+ collapseAll(root);
501
+ resetHighlightedNodes(root);
502
+ var searchQuery = e.target.value;
503
+ if ('' === searchQuery) {
504
+ counter.textContent = '0 on 0';
505
+
506
+ return;
507
+ }
508
+
509
+ var xpathResult = doc.evaluate('//pre[@id="' + root.id + '"]//span[@class="sf-dump-str" or @class="sf-dump-key" or @class="sf-dump-public" or @class="sf-dump-protected" or @class="sf-dump-private"][contains(child::text(), ' + xpathString(searchQuery) + ')]', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
510
+
511
+ while (node = xpathResult.iterateNext()) state.nodes.push(node);
512
+
513
+ showCurrent(state);
514
+ }, 400);
515
+ });
516
+
517
+ Array.from(search.querySelectorAll('.sf-dump-search-input-next, .sf-dump-search-input-previous')).forEach(function (btn) {
518
+ addEventListener(btn, 'click', function (e) {
519
+ e.preventDefault();
520
+ var direction = -1 !== e.target.className.indexOf('next') ? 'next' : 'previous';
521
+ 'next' === direction ? state.next() : state.previous();
522
+ searchInput.focus();
523
+ collapseAll(root);
524
+ showCurrent(state);
525
+ })
526
+ });
527
+
528
+ addEventListener(root, 'keydown', function (e) {
529
+ if (114 === e.keyCode || (isCtrlKey(e) && 70 === e.keyCode)) {
530
+ /* CTRL + F or CMD + F */
531
+ e.preventDefault();
532
+ search.className = search.className.replace(/\bsf-dump-search-hidden\b/, '');
533
+ searchInput.focus();
534
+ } else if (27 === e.keyCode && !/\bsf-dump-search-hidden\b/.test(search.className)) {
535
+ /* ESC key */
536
+ search.className += ' sf-dump-search-hidden';
537
+ e.preventDefault();
538
+ resetHighlightedNodes(root);
539
+ searchInput.value = '';
540
+ }
541
+ });
542
+ }
543
+
327
544
if (0 >= options.maxStringLength) {
328
545
return;
329
546
}
@@ -359,6 +576,13 @@ function isCtrlKey(e) {
359
576
white-space: pre;
360
577
padding: 5px;
361
578
}
579
+ pre.sf-dump:after {
580
+ content: "";
581
+ visibility: hidden;
582
+ display: block;
583
+ height: 0;
584
+ clear: both;
585
+ }
362
586
pre.sf-dump span {
363
587
display: inline;
364
588
}
@@ -397,6 +621,80 @@ function isCtrlKey(e) {
397
621
.sf-dump-str-expand .sf-dump-str-expand {
398
622
display: none;
399
623
}
624
+ .sf-dump-public.sf-dump-highlight,
625
+ .sf-dump-protected.sf-dump-highlight,
626
+ .sf-dump-private.sf-dump-highlight,
627
+ .sf-dump-str.sf-dump-highlight,
628
+ .sf-dump-key.sf-dump-highlight {
629
+ background: rgba(111, 172, 204, 0.3);
630
+ border: 1px solid #7DA0B1;
631
+ border-radius: 3px;
632
+ }
633
+ .sf-dump-public.sf-dump-highlight-active,
634
+ .sf-dump-protected.sf-dump-highlight-active,
635
+ .sf-dump-private.sf-dump-highlight-active,
636
+ .sf-dump-str.sf-dump-highlight-active,
637
+ .sf-dump-key.sf-dump-highlight-active {
638
+ background: rgba(253, 175, 0, 0.4);
639
+ border: 1px solid #ffa500;
640
+ border-radius: 3px;
641
+ }
642
+ .sf-dump-search-hidden {
643
+ display: none;
644
+ }
645
+ .sf-dump-search-wrapper {
646
+ float: right;
647
+ font-size: 0;
648
+ white-space: nowrap;
649
+ max-width: 100%;
650
+ text-align: right;
651
+ }
652
+ .sf-dump-search-wrapper > * {
653
+ vertical-align: top;
654
+ box-sizing: border-box;
655
+ height: 21px;
656
+ font-weight: normal;
657
+ border-radius: 0;
658
+ background: #FFF;
659
+ color: #757575;
660
+ border: 1px solid #BBB;
661
+ }
662
+ .sf-dump-search-wrapper > input.sf-dump-search-input {
663
+ padding: 3px;
664
+ height: 21px;
665
+ font-size: 12px;
666
+ border-right: none;
667
+ width: 140px;
668
+ border-top-left-radius: 3px;
669
+ border-bottom-left-radius: 3px;
670
+ color: #000;
671
+ }
672
+ .sf-dump-search-wrapper > .sf-dump-search-input-next,
673
+ .sf-dump-search-wrapper > .sf-dump-search-input-previous {
674
+ background: #F2F2F2;
675
+ outline: none;
676
+ border-left: none;
677
+ font-size: 0;
678
+ line-height: 0;
679
+ }
680
+ .sf-dump-search-wrapper > .sf-dump-search-input-next {
681
+ border-top-right-radius: 3px;
682
+ border-bottom-right-radius: 3px;
683
+ }
684
+ .sf-dump-search-wrapper > .sf-dump-search-input-next > svg,
685
+ .sf-dump-search-wrapper > .sf-dump-search-input-previous > svg {
686
+ pointer-events: none;
687
+ width: 12px;
688
+ height: 12px;
689
+ }
690
+ .sf-dump-search-wrapper > .sf-dump-search-count {
691
+ display: inline-block;
692
+ padding: 0 5px;
693
+ margin: 0;
694
+ border-left: none;
695
+ line-height: 21px;
696
+ font-size: 12px;
697
+ }
400
698
EOHTML
401
699
);
402
700
0 commit comments