Я унаследовал некоторую разметку, в которой серия элементов <a>
верхнего уровня содержит набор элементов <span>
, и с помощью CSS они отображаются в виде блоков, которые можно нажимать в списке, например:
.list {
display: inline-flex;
flex-flow: column nowrap;
font: 14px Arial;
}
.list a {
display: flex;
flex-flow: column nowrap;
align-items: stretch;
border: 1px solid #CCC;
border-bottom: none;
background: #FFF;
padding: 4px 10px;
text-decoration: none;
color: #000;
}
.list a:last-child {
border-bottom: 1px solid #CCC;
}
.list a:hover {
background: #CDE;
}
.list a .name {
font-weight: bold;
}
.list a .secondary {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
color: #678;
font-size: 85%;
padding-top: 2px;
}
.list a .address {
padding-right: 16px;
padding-left: 8px;
}
.list a .company-id {
color: #B88;
cursor: text;
padding-left: 4px;
padding-right: 4px;
margin-right: -4px;
}
<div class="list">
<a href="/link/to/company/10101">
<span class="name">Alice Jones & Co.</span>
<span class="secondary">
<span class="address">55 Oak Street, Anytown 15151</span>
<span class="company-id">#10101</span>
</span>
</a>
<a href="/link/to/company/12345">
<span class="name">John Smith Inc.</span>
<span class="secondary">
<span class="address">123 Main Street, Anytown 15151</span>
<span class="company-id">#12345</span>
</span>
</a>
<a href="/link/to/company/20123">
<span class="name">Bob Johnson LLC</span>
<span class="secondary">
<span class="address">17 Spruce Street, Anytown 15152</span>
<span class="company-id">#20123</span>
</span>
</a>
</div>
Запрос
Владелец продукта спросил меня на днях, могу ли я сделать идентификаторы компании не активируется - наши пользователи хотят, чтобы выбирал текст идентификаторов для копирования и вставки.Хорошо, подумал я: превратите каждый элемент <a>
в <li>
, как и должно быть, добавьте немного JavaScript, чтобы переходить по ссылкам при кликах, игнорируйте клики по идентификаторам компании, и все готово.
Затем я узнал, что есть еще одно требование пользователя - элементы <a>
также должны быть нажимаемыми по среднему щелчку или по нажатию Ctrl, чтобы открывать их на новой вкладке.Я намеревался настроить JavaScript для вызова window.open()
, если клавиша Ctrl или средняя кнопка мыши были нажаты, но кажется, что блокировщики рекламы и блокировщики всплывающих окон браузера мешают этой работе надежно: элемент <a>
нуждается в элементебыть настоящим <a>
элементом, и его события должны быть оставлены более или менее нетронутыми.Но это означает, что <a>
будет фиксировать каждое всплывающее событие в своем контенте, включая события, которые я бы предпочел не трогать, например события click-and-drag (и double-click) на идентификаторе компании.
И поскольку список имеет гибкую структуру, я не могу поместить элемент идентификатора компании за пределы элемента <a>
, а затем сделать его частью одного и того же блока, используя приемы position
или margin
: Интервалработать не будет, потому что длина идентификаторов довольно сильно варьируется (от 1
до 129370-5486
).
tl; dr: Мне нужен дочерний элемент для существования внутри элемент <a>
для макета - но он должен существовать снаружи тот же элемент для поведения .
Требования
Для правильного решения я должен выполнить следующие требования:
- Полный элемент
<a>
должен быть интерактивным, как ссылка, за исключениемидентификатор компании <span>
. - Полный элемент
<a>
можно щелкнуть средней кнопкой мыши, чтобы открыть его на новой вкладке, напримервыберите идентификатор компании <span>
. - Пользователь должен иметь возможность щелкнуть и перетащить идентификатор компании
<span>
, чтобы выбрать и скопировать его текст. - Пользователь долженвозможность дважды щелкнуть по идентификатору компании
<span>
, чтобы выделить и скопировать его текст. - Макет должен быть гибким, допускающим пролеты текста произвольной длины и свертывания до самой узкой общей ширины.
- Решение должно работать в современных вечнозеленых браузерах (например, Chrome, Firefox, Edge - не требуется совместимость со старым IE!).
Помимо этого, предел неба: зависимости, нет зависимостей,добавьте / настройте CSS, добавьте JS, измените разметку - если эти шесть пунктов обозначены, вы можете делать все, что захотите.
My Best Solution
До сих пор я пробовал очень много хитростей по сбору событий JavaScript, большинство из которых были неудачными.Лучшее рабочее решение, которое я нашел, вообще не использует JS: я включаю идентификатор компании в разметку дважды - один раз внутри <a>
с visibility:hidden
для целей макета, а затем снова в разметке после </a>
,с position:relative
-содержащим элементом <li>
вокруг всего этого и position:absolute / bottom: / right:
на видимом, выбираемом <span>
.Но кажется, что должен быть лучший способ, который не включает в себя изменение разметки;и если владельцы продуктов когда-нибудь захотят добавить больше текста в каждом поле или немного другой макет, мое решение вряд ли приспособится к этим изменениям.
Так что у вас есть идеи получше, чем я?Выкл. из обычных, выбираемых текстовых элементов внутри <a>
родительского элемента, нажимаемого в противном случае?