-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OEL-3343: Copyright overlay. #430
base: EPIC/OEL-3442
Are you sure you want to change the base?
Changes from 24 commits
ca889ba
953dee4
e42fa6c
fd86819
6cb6883
8d84145
c1f9e94
9f3b5e3
e94a2b7
30e0bd9
5a19126
96480b2
848ade3
9254952
fddda35
531fe2e
dc58ec7
2b124ba
ebe82c3
ac82f43
c6cf835
6ddfe8e
225cffe
f81998d
815722c
6495de2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/** | ||
* @file | ||
* Attaches behaviors to copy text to clipboard for elements with data-copy-target attribute. | ||
*/ | ||
(function (Drupal) { | ||
|
||
const handleClick = function (event) { | ||
const element = event.currentTarget; | ||
const targetSelector = element.getAttribute('data-copy-target'); | ||
const targetElement = document.querySelector(targetSelector); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we decided to go for the approach where is the user that needs to ensure to pass a selector that triggers one element only? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, i think it's better because we let the user make extended selectors and it's up to them to provide the correct one. |
||
|
||
if (targetElement) { | ||
const copyText = targetElement.innerText || targetElement.value; | ||
navigator.clipboard.writeText(copyText); | ||
} | ||
}; | ||
|
||
Drupal.behaviors.copyClipboard = { | ||
attach: function (context) { | ||
once('oebt-clipcopy', '[data-copy-target]', context).forEach(function (element) { | ||
element.addEventListener('click', handleClick); | ||
}); | ||
}, | ||
|
||
detach: function (context, settings, trigger) { | ||
once.remove('oebt-clipcopy', '[data-copy-target]', context).forEach(function (element) { | ||
element.removeEventListener('click', handleClick); | ||
}); | ||
} | ||
}; | ||
|
||
})(Drupal); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
.copyright-overlay { | ||
background-color: rgba(var(--bs-white-rgb),var(--bs-bg-opacity)); | ||
color: var(--bs-gray-700); | ||
padding: 0 0.5rem; | ||
display: inline-flex; | ||
.copyright-preview { | ||
display: inline-block; | ||
overflow: hidden; | ||
text-overflow: ellipsis; | ||
white-space: nowrap; | ||
max-width: 7rem; | ||
font-size: 0.875rem; | ||
} | ||
.copyright-trigger { | ||
font-size: 0.875rem; | ||
} | ||
.copyright-header { | ||
font-size: 1.25rem; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
copyright_overlay: | ||
label: 'Copyright overlay' | ||
description: 'A component to show copyright information.' | ||
fields: | ||
trigger_label: | ||
type: text | ||
label: 'Trigger label' | ||
description: 'The label of the modal trigger. Optional.' | ||
preview: 'View more' | ||
modal_title: | ||
type: text | ||
label: 'Modal title' | ||
description: 'The title of the modal header. Optional.' | ||
preview: 'Copyright' | ||
content: | ||
type: render | ||
label: 'Content' | ||
description: 'Copyright overlay content.' | ||
preview: '© Copyright ipsum amet <a href="#">John Doe</a> on <a href="#">Doe Images</a>.' | ||
settings: | ||
drishu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
trigger_attributes: | ||
type: attributes | ||
label: Trigger attributes | ||
description: Extra attributes for the modal trigger | ||
drishu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
allow_token: true | ||
attributes: | ||
type: attributes | ||
label: Copyright overlay attributes | ||
description: Extra attributes for the copyright overlay | ||
allow_token: true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{# | ||
/** | ||
* @file | ||
* Template override for preview mode of "Copyright overlay" pattern. | ||
*/ | ||
#} | ||
|
||
{{ pattern('copyright_overlay', { | ||
content: content, | ||
}) }} | ||
|
||
{{ pattern('copyright_overlay', { | ||
content: '© Second copyright element. Suspendisse vel mauris vitae ipsum blandit condimentum ut eget quam.', | ||
}) }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
{# | ||
/** | ||
* @file | ||
* Copyright overlay pattern. | ||
*/ | ||
#} | ||
{{ attach_library('oe_bootstrap_theme/pattern.copyright_overlay') }} | ||
|
||
{% set _footer %} | ||
{% include '@oe-bcl/button' with { | ||
label: 'Copy Copyright'|t, | ||
attributes: create_attribute({ | ||
'data-bs-dismiss': 'modal', | ||
'data-copy-target': '#' ~ copy_selector | ||
}) | ||
} only %} | ||
{% endset %} | ||
|
||
{% set _content %} | ||
<div{{ create_attribute({ | ||
'class': 'copyright-content', | ||
'id': copy_selector | ||
}) }}> | ||
{{ content }} | ||
</div> | ||
{% endset %} | ||
|
||
<div{{ attributes.addClass('copyright-overlay') }}> | ||
<span class="copyright-preview"> | ||
{{ content }} | ||
</span> | ||
|
||
{{ pattern('link', { | ||
label: trigger_label|default('View more'|t), | ||
path: '#', | ||
attributes: trigger_attributes | ||
.addClass('copyright-trigger') | ||
.setAttribute('data-bs-toggle', 'modal') | ||
.setAttribute('data-bs-target', '#' ~ modal_id), | ||
}) }} | ||
|
||
{{ pattern('modal', { | ||
'title': modal_title|default('Copyright'|t), | ||
'show_close_button': true, | ||
'body': _content, | ||
'footer': _footer, | ||
'attributes': create_attribute({ | ||
id: modal_id | ||
}) | ||
}) }} | ||
</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Drupal\Tests\oe_bootstrap_theme\FunctionalJavascript; | ||
|
||
use Behat\Mink\Element\NodeElement; | ||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase; | ||
|
||
/** | ||
* Tests the copy to clipboard javascript behaviour. | ||
*/ | ||
class CopyClipboardTest extends WebDriverTestBase { | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected $defaultTheme = 'oe_bootstrap_theme'; | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected static $modules = [ | ||
'oe_bootstrap_theme_helper', | ||
'system', | ||
'ui_patterns', | ||
'ui_patterns_settings', | ||
'ui_patterns_library', | ||
]; | ||
|
||
/** | ||
* Tests the copy to clipboard behavior in the copyright overlay. | ||
*/ | ||
public function testCopyToClipboard(): void { | ||
$this->drupalLogin($this->drupalCreateUser([], NULL, TRUE)); | ||
|
||
$this->drupalGet('/patterns/copyright_overlay'); | ||
|
||
// Mock the clipboard API. | ||
$this->getSession()->executeScript(<<<JS | ||
navigator.clipboard = { | ||
writeText: function(text) { | ||
// Store the copied text in a variable. | ||
window.copiedText = text; | ||
return Promise.resolve(); | ||
} | ||
}; | ||
JS); | ||
|
||
$elements = $this->getSession()->getPage()->findAll('css', '.copyright-overlay'); | ||
|
||
$this->assertCopyrightCopiedToClipboard($elements['0'], '© Copyright ipsum amet John Doe on Doe Images.'); | ||
$this->assertCopyrightCopiedToClipboard($elements['1'], '© Second copyright element. Suspendisse vel mauris vitae ipsum blandit condimentum ut eget quam.'); | ||
} | ||
|
||
/** | ||
* Asserts that the text in the element corresponds to the clipboard. | ||
* | ||
* @param \Behat\Mink\Element\NodeElement $element | ||
* The copyright element. | ||
* @param string $expected | ||
* The expected result. | ||
*/ | ||
protected function assertCopyrightCopiedToClipboard(NodeElement $element, string $expected): void { | ||
$assert_session = $this->assertSession(); | ||
|
||
$assert_session->elementExists('css', '.copyright-trigger', $element)->click(); | ||
$modal = $assert_session->waitForElementVisible('css', '.modal.show'); | ||
|
||
$assert_session->elementExists('css', '[data-copy-target]', $modal)->click(); | ||
|
||
$actual = $this->getSession()->evaluateScript('return window.copiedText;'); | ||
|
||
$this->assertEquals($expected, $actual); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use copyright-content as ID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed.