Files
notifications-admin/app/assets/javascripts/copyToClipboard.js
Alex Janousek 6f5750f095 Removed all govuk css (#2814)
* Removed all govuk css

* Updated reference files

* Removing govuk js

* Fixed casing for modules, removed unused page

* Got more reference images

* Updated template page

* Removed govuk padding util

* Updated hint to uswds hint

* More govuk cleanup

* Commiting backstopjs ref files

* Fixed all unit tests that broke due to brittleness around govuk styling

* Added new ref images

* Final removal of govuk

* Officially removed all govuk references

* Updated reference file

* Updated link to button

* UI modernization

* Cleanup

* removed govuk escaping tests since they are no longer needed

* Fix CodeQL security issue in escapeElementName function

- Escape backslashes first before other special characters
- Prevents potential double-escaping vulnerability
- Addresses CodeQL alert about improper string escaping

* Found more govuk removal. Fixed unit tests

* Add missing pipeline check to pre-commit

* updated test

* Updated e2e test

* More update to e2e test

* Fixed another e2e test

* Simple PR comments addressed

* More updates

* Updated backstop ref files

* Refactored folder selection for non-admins

* Updated redundant line

* Updated tests to include correct mocks

* Added more ref files

* Addressing carlos comments

* Addressing Carlo comments, cleanup of window initing

* More cleanup and addressing carlo comments

* Fixing a11 scan

* Fixed a few issues with javascript

* Fixed for pr

* Fixing e2e tests

* Tweaking e2e test

* Added more ref files and cleaned up urls.js

* Fixed bug with creating new template

* Removed brittle test - addressed code ql comment

* e2e race condition fix

* More e2e test fixes

* Updated e2e tests to not wait for text sent

* Updated test to not wait for button click response

* Made tear down more resilent if staging is down

* reverted e2e test to what was working before main merge

* Updated backstopRef images

* Updated gulp to include job-polling differently
2025-10-06 09:38:54 -04:00

101 lines
3.6 KiB
JavaScript

(function(window) {
"use strict";
if (!document.queryCommandSupported('copy')) return;
window.NotifyModules['copy-to-clipboard'] = function() {
const states = {
'valueVisible': (options) => `
<span class="copy-to-clipboard__value margin-bottom-1">${options.valueLabel ? '<span class="usa-sr-only">' + options.thing + ': </span>' : ''}${options.value}</span>
<span class="copy-to-clipboard__notice" aria-live="assertive">
${options.onload ? '' : options.thing + ' returned to page, press button to copy to clipboard'}
</span>
<button class="usa-button usa-button--outline copy-to-clipboard__button--copy">
Copy ${options.thing} to clipboard${options.name ? '<span class="usa-sr-only"> for ' + options.name + '</span>' : ''}
</button>
`,
'valueCopied': (options) => `
<span class="copy-to-clipboard__notice" aria-live="assertive">
<span class="usa-sr-only">${options.thing} </span>Copied to clipboard<span class="usa-sr-only">, press button to show in page</span>
</span>
<button class="usa-button copy-to-clipboard__button--show">
Show ${options.thing}${options.name ? '<span class="usa-sr-only"> for ' + options.name + '</span>' : ''}
</button>
`
};
this.getRangeFromElement = function (copyableElement) {
const range = document.createRange();
const childNodes = Array.prototype.slice.call(copyableElement.childNodes);
let prefixIndex = -1;
childNodes.forEach((el, idx) => {
if ((el.nodeType === 1) && el.classList.contains('usa-sr-only')) {
prefixIndex = idx;
}
});
range.selectNodeContents(copyableElement);
if (prefixIndex !== -1) { range.setStart(copyableElement, prefixIndex + 1); }
return range;
};
this.copyValueToClipboard = function(copyableElement, callback) {
var selection = window.getSelection ? window.getSelection() : document.selection,
range = this.getRangeFromElement(copyableElement);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
selection.removeAllRanges();
callback();
};
this.start = function(component) {
const $component = $(component),
stateOptions = {
value: $component.data('value'),
thing: $component.data('thing')
},
name = $component.data('name');
// if the name is distinct from the thing:
// - it will be used in the rendering
// - the value won't be identified by a heading so needs its own label
if (name !== stateOptions.thing) {
stateOptions.name = name;
stateOptions.valueLabel = true;
}
$component
.addClass('copy-to-clipboard')
.css('min-height', $component.height())
.html(states.valueVisible($.extend({ 'onload': true }, stateOptions)))
.on(
'click', '.copy-to-clipboard__button--copy', () =>
this.copyValueToClipboard(
$('.copy-to-clipboard__value', component)[0], () =>
$component
.html(states.valueCopied(stateOptions))
.find('.usa-button').focus()
)
)
.on(
'click', '.copy-to-clipboard__button--show', () =>
$component
.html(states.valueVisible(stateOptions))
.find('.usa-button').focus()
);
if ('stickAtBottomWhenScrolling' in window.NotifyModules) {
window.NotifyModules.stickAtBottomWhenScrolling.recalculate();
}
};
};
})(window);