Как сделать элемент <a>с выбираемыми текстом дочерними элементами? - PullRequest
0 голосов
/ 05 декабря 2018

Я унаследовал некоторую разметку, в которой серия элементов <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 &amp; 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> родительского элемента, нажимаемого в противном случае?

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Хейдон Пикеринг (Heydon Pickering) написал статью о инклюзивном дизайне карты , в которой рассказывается, как обрабатывать выбираемый текст внутри компонента карты, когда вся карта активна.

Одно из решений, котороеработа для вас будет состоять в том, чтобы заменить каждый из элементов <a> на элементы <li>, как вы это делали, но затем добавить тег <a> вокруг только названия компании.Затем вы можете добавить псевдоэлемент к тегу привязки, который расширяет всю ширину / высоту родительского элемента <li>.Наконец, добавьте position: relative к идентификатору, чтобы он располагался над псевдоэлементом anchors, чтобы он не активировал ссылку.

.list {
  display: inline-flex;
  flex-flow: column nowrap;
  font: 14px Arial;
  margin: 0;
  padding: 0;
}
  .list li {
    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;
    position: relative;
  }
    .list a::after {
      content: '';
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
    }
  
    .list li:last-child {
      border-bottom: 1px solid #CCC;
    }
    .list li:hover {
      background: #CDE;
    }

    .list li .name {
      font-weight: bold;
    }
    .list li .secondary {
      display: flex;
      flex-flow: row nowrap;
      justify-content: space-between;
      color: #678;
      font-size: 85%;
      padding-top: 2px;
    }
    
    .list li .address {
      padding-right: 16px;
      padding-left: 8px;
    }
    .list li .company-id {
      color: #B88;
      cursor: text;
      padding-left: 4px;
      padding-right: 4px;
      margin-right: -4px;
      position: relative;
    }
<ul class="list">
    <li>
        <a href="/link/to/company/10101" class="name">Alice Jones &amp; Co.</a>
        <span class="secondary">
            <span class="address">55 Oak Street, Anytown 15151</span>
            <span class="company-id">#10101</span>
        </span>
    </li>
    <li>
      <a href="/link/to/company/12345" class="name">John Smith Inc.</a>
      <span class="secondary">
          <span class="address">123 Main Street, Anytown 15151</span>
          <span class="company-id">#12345</span>
      </span>
    </li>
    <li>
      <a href="/link/to/company/20123" class="name">Bob Johnson LLC</a>
      <span class="secondary">
          <span class="address">17 Spruce Street, Anytown 15152</span>
          <span class="company-id">#20123</span>
      </span>
    </li>
</ul>
0 голосов
/ 05 декабря 2018

Вот соответствующий кодовый блок, который я создал, но psuedo-a закомментирован в js: https://codepen.io/anon/pen/XyLgag

Это должно помочь вам начать, но не совсем так, как вам нужно, я уверен ...HTH

CSS:

a.psuedo {
  position: absolute;
  top: 0;
  left: 30%;
  width: 15px;
  height: 15px;
  border: 0 !important;
  background: transparent;
  margin: 0;
  padding: 0;
}

JQUERY ДЛЯ КОПИРОВАНИЯ НА CLIPBOARD:

//Add custom event listener
$(':root').on('mousedown', '*', function() {
    var el = $(this),
        events = $._data(this, 'events');
    if (events && events.clickHold) {
        el.data(
            'clickHoldTimer',
            setTimeout(
                function() {
                    el.trigger('clickHold')
                },
                el.data('clickHoldTimeout')
            )
        );
    }
}).on('mouseup mouseleave mousemove', '*', function() {
    clearTimeout($(this).data('clickHoldTimer'));
});

//Attach it to the element
$('.company-id').data('clickHoldTimeout', 2000); //Time to hold
$('.company-id').on('clickHold', function() {
  /* Get the text field */
  var copyText = $(this).html();

  /* Copy the text inside the text field */
  document.execCommand("copy");
  console.log("copied -- " + copyText);

});

JQUERY ДЛЯ ДОБАВЛЕНИЯ ПЕВДО-ЯКОРНОЙ TAG

$(".company-id").each(function() {
    $(this).append('<a class="psuedo" target="_blank" href="www.google.com"></a>');
  });
...