PluginProbe
Contact Forms by Cimatti / 2.3.5
Contact Forms by Cimatti v2.3.5
2.3.6 2.3.5 2.3.0 2.2.32 2.2.4 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.2.1 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 All 62 releases
contact-forms / assets / js / admin / expandable-cells.js

expandable-cells.js in Contact Forms by Cimatti 2.3.5, at assets/js/admin/expandable-cells.js

88 lines 3.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global document */
2 ( function () {
3 'use strict';
4
5 /**
6 * For CSS-truncated columns (overflow:hidden + text-overflow:ellipsis) -
7 * the URL columns and every field-value column - detect which cells
8 * actually overflow after layout (or hold multi-line values) and add a
9 * [+]/[−] toggle that expands the cell to the full wrapped content.
10 * Cells that fit on one line are left untouched - no [+] clutter.
11 *
12 * The widget keeps a SINGLE copy of the text (the cell content itself,
13 * CSS-truncated while collapsed). The previous <details>/<summary>
14 * structure duplicated the text (truncated preview + full content), and
15 * browser find-in-page searches collapsed content too, so Ctrl+F counted
16 * every match twice.
17 */
18 function initExpandableCells() {
19 var selectors = [
20 '#accua_dashboard_page td.column-afs_referrer',
21 '#accua_dashboard_page td.column-afs_uri',
22 '#accua_forms_submissions_list_page td.column-referrer',
23 '#accua_forms_submissions_list_page td.column-uri',
24 '#accua_forms_submissions_list_page .wp-list-table td[class*="column-_field_"]',
25 ].join( ',' );
26
27 document.querySelectorAll( selectors ).forEach( function ( td ) {
28 if ( td.textContent.trim() === '' || td.querySelector( '.accua-expandable-cell' ) ) {
29 return;
30 }
31
32 // td.scrollWidth === td.clientWidth for table cells even when clipped,
33 // so measure the content's natural width via a text Range instead.
34 var range = document.createRange();
35 range.selectNodeContents( td );
36 var naturalWidth = range.getBoundingClientRect().width;
37
38 // Multi-line values (textarea fields) always get the widget: the
39 // collapsed nowrap preview flattens their line breaks, the expanded
40 // state renders them as paragraphs again.
41 var hasLineBreak = td.textContent.indexOf( '\n' ) !== -1;
42
43 if ( naturalWidth <= td.clientWidth && ! hasLineBreak ) {
44 return; // Content fits - no expandable needed.
45 }
46
47 var wrap = document.createElement( 'span' );
48 wrap.className = 'accua-expandable-cell';
49
50 var text = document.createElement( 'span' );
51 text.className = 'accua-expandable-text';
52
53 var toggle = document.createElement( 'button' );
54 toggle.type = 'button';
55 toggle.className = 'accua-expandable-toggle';
56 toggle.setAttribute( 'aria-expanded', 'false' );
57 toggle.textContent = '[+]';
58
59 toggle.addEventListener( 'click', function () {
60 var open = wrap.classList.toggle( 'open' );
61 toggle.setAttribute( 'aria-expanded', open ? 'true' : 'false' );
62 toggle.textContent = open ? '[−]' : '[+]';
63 } );
64
65 // Move the cell's entire content - links keep href/target/title.
66 while ( td.firstChild ) {
67 text.appendChild( td.firstChild );
68 }
69 wrap.appendChild( text );
70 wrap.appendChild( toggle );
71 td.appendChild( wrap );
72 } );
73 }
74
75 // The script runs in the footer. By then 'load' may already have fired,
76 // so check readyState and fall through immediately if so.
77 // setTimeout(0) defers until after the current rendering cycle.
78 function scheduleInit() {
79 setTimeout( initExpandableCells, 0 );
80 }
81
82 if ( document.readyState === 'complete' ) {
83 scheduleInit();
84 } else {
85 window.addEventListener( 'load', scheduleInit );
86 }
87 }() );
88