HTML - как я могу показать подсказку ТОЛЬКО при активации многоточия

У меня есть диапазон с динамическими данными на моей странице, которые содержат многоточие. Значение:

<span style='text-overflow: ellipsis; overflow : hidden; white-space: nowrap;  
 width: 71;'>${myData}</span>

и я хотел бы добавить к этой всплывающей подсказке этого элемента с тем же содержимым (title= '$ {myData}'), но я хочу, чтобы он отображался только тогда, когда контент длинный, и эллипсис появляется на экране.
Есть ли способ сделать это?

в одном направлении - когда браузер (IE в моем случае) рисует эллипсис - он бросает событие об этом?

Ответ 1

Здесь используется способ, использующий встроенный параметр многоточия, и добавляет атрибут title по требованию (с jQuery) на комментарий Мартина Смита:

$('.mightOverflow').bind('mouseenter', function(){
    var $this = $(this);

    if(this.offsetWidth < this.scrollWidth && !$this.attr('title')){
        $this.attr('title', $this.text());
    }
});

Ответ 2

Здесь чисто CSS-решение. Нет необходимости в jQuery. Он не покажет всплывающую подсказку, вместо этого он просто расширит содержимое до полной длины при наведении курсора мыши.

Отлично работает, если у вас есть контент, который заменяется. Тогда вам не нужно запускать функцию jQuery каждый раз.

.might-overflow {
    text-overflow: ellipsis;
    overflow : hidden;
    white-space: nowrap;
}

.might-overflow:hover {
    text-overflow: clip;
    white-space: normal;
    word-break: break-all;
}

Ответ 3

Ответ uosɐs в корне прав, но вы, вероятно, не хотите делать это в событии mouseenter. Это приведет к тому, что он будет выполнять вычисления, чтобы определить, нужно ли это, каждый раз, когда вы наводите мышь на элемент. Если размер элемента не меняется, нет причин для этого.

Было бы лучше просто вызвать этот код сразу после добавления элемента в DOM:

var $ele = $('#mightOverflow');
var ele = $ele.eq(0);
if (ele.offsetWidth < ele.scrollWidth)
    $ele.attr('title', $ele.text());

Или, если вы не знаете, когда именно это было добавлено, затем вызовите этот код после завершения загрузки страницы.

Если у вас есть более одного элемента, с которым вам нужно это сделать, вы можете дать им все те же классы (например, "mayOverflow" ) и использовать этот код для их обновления:

$('.mightOverflow').each(function() {
    var $ele = $(this);
    if (this.offsetWidth < this.scrollWidth)
        $ele.attr('title', $ele.text());
});

Ответ 4

Вот мой плагин jQuery:

(function($) {
    'use strict';
    $.fn.tooltipOnOverflow = function() {
        $(this).on("mouseenter", function() {
            if (this.offsetWidth < this.scrollWidth) {
                $(this).attr('title', $(this).text());
            } else {
                $(this).removeAttr("title");
            }
        });
    };
})(jQuery);

Использование:

$("td, th").tooltipOnOverflow();

Edit:

Я создал для этого плагина. https://gist.github.com/UziTech/d45102cdffb1039d4415

Ответ 5

Нам нужно определить, действительно ли применяется многоточие, а затем показать всплывающую подсказку для раскрытия полного текста. Этого недостаточно, только сравнивая "this.offsetWidth < this.scrollWidth", когда элемент почти удерживает его содержимое, но только не имеет одного или двух пикселей в ширину, особенно для текста полноразмерных символов китайского/японского/корейского.

Вот пример: http://jsfiddle.net/28r5D/5/

Я нашел способ улучшить обнаружение многоточия:

  • Сначала сравните "this.offsetWidth < this.scrollWidth", продолжите шаг №2, если не удалось.
  • Временно переключить стиль css на {'overflow': 'visible', 'white-space': 'normal', 'word-break': 'break-all'}.
  • Пусть браузер выполняет ретрансляцию. Если происходит перенос слов, элемент будет увеличивать свою высоту, что также означает, что требуется многоточие.
  • Восстановить стиль css.

Вот мое улучшение: http://jsfiddle.net/28r5D/6/

Ответ 6

Я создал плагин jQuery, который использует всплывающую подсказку Bootstrap вместо встроенной подсказки браузера. Обратите внимание, что это не было проверено с более старым браузером.

JSFiddle: https://jsfiddle.net/0bhsoavy/4/

$.fn.tooltipOnOverflow = function(options) {
    $(this).on("mouseenter", function() {
    if (this.offsetWidth < this.scrollWidth) {
        options = options || { placement: "auto"}
        options.title = $(this).text();
      $(this).tooltip(options);
      $(this).tooltip("show");
    } else {
      if ($(this).data("bs.tooltip")) {
        $tooltip.tooltip("hide");
        $tooltip.removeData("bs.tooltip");
      }
    }
  });
};

Ответ 7

Вот два других чистых решения CSS:

  1. Показать усеченный текст на месте:

.overflow {
  overflow: hidden;
  -ms-text-overflow: ellipsis;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.overflow:hover {
  overflow: visible;
}

.overflow:hover span {
  position: relative;
  background-color: white;

  box-shadow: 0 0 4px 0 black;
  border-radius: 1px;
}
<div>
  <span class="overflow" style="float: left; width: 50px">
    <span>Long text that might overflow.</span>
  </span>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ad recusandae perspiciatis accusantium quas aut explicabo ab. Doloremque quam eos, alias dolore, iusto pariatur earum, ullam, quidem dolores deleniti perspiciatis omnis.
</div>

Ответ 8

Это то, что я сделал. Большинство скриптов подсказки требуют выполнения функции, в которой хранятся всплывающие подсказки. Это пример jQuery:

$.when($('*').filter(function() {
   return $(this).css('text-overflow') == 'ellipsis';
}).each(function() {
   if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
      $(this).attr('title', $(this).text());
   }
})).done(function(){ 
   setupTooltip();
});

Если вы не хотите проверять эллипсис css, вы можете упростить:

$.when($('*').filter(function() {
   return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
   $(this).attr('title', $(this).text());
})).done(function(){ 
   setupTooltip();
});

У меня есть "когда" вокруг него, так что функция "setupTooltip" не выполняется до тех пор, пока все заголовки не будут обновлены. Замените "setupTooltip", с помощью функции подсказки и * с элементами, которые вы хотите проверить. * будет проходить через них все, если вы оставите его.

Если вы просто хотите просто обновить атрибуты заголовка с помощью всплывающей подсказки браузеров, вы можете упростить, например:

$('*').filter(function() {
   return $(this).css('text-overflow') == 'ellipsis';
}).each(function() {
   if (this.offsetWidth < this.scrollWidth && !$(this).attr('title')) {
      $(this).attr('title', $(this).text());
   }
});

Или без проверки для многоточия:

$.when($('*').filter(function() {
   return (this.offsetWidth < this.scrollWidth && !$(this).attr('title'));
}).each(function() {
   $(this).attr('title', $(this).text());
});

Ответ 9

Если вы хотите сделать это исключительно с помощью javascript, я бы сделал следующее. Дайте span атрибуту id (чтобы его можно было легко извлечь из DOM) и поместить все содержимое в атрибут с именем "content":

<span id='myDataId' style='text-overflow: ellipsis; overflow : hidden;
 white-space: nowrap; width: 71;' content='{$myData}'>${myData}</span>

Затем в вашем javascript вы можете сделать следующее после того, как элемент был вставлен в DOM.

var elemInnerText, elemContent;
elemInnerText = document.getElementById("myDataId").innerText;
elemContent = document.getElementById("myDataId").getAttribute('content')
if(elemInnerText.length <= elemContent.length)
{
   document.getElementById("myDataId").setAttribute('title', elemContent); 
}

Конечно, если вы используете javascript для вставки span в DOM, вы можете просто сохранить содержимое в переменной перед его вставкой. Таким образом, вам не нужен атрибут content на span.

Есть более элегантные решения, чем это, если вы хотите использовать jQuery.

Ответ 10

У меня есть класс CSS, который определяет, где положить многоточие. Исходя из этого, я делаю следующее (набор элементов может быть другим, я пишу те, где используется многоточие, конечно, это может быть отдельный селектор классов):

$(document).on('mouseover', 'input, td, th', function() {
    if ($(this).css('text-overflow') && typeof $(this).attr('title') === 'undefined') {
        $(this).attr('title', $(this).val());
    }
});

Ответ 11

верхолаз! У меня такая же проблема. браузер, похоже, не знает, что текст усекается. Все атрибуты DOM не показывают никаких следов. конечно, вы можете изменить переполнение на видимое, измерить ширину, затем вернуться к переполнению, а затем сравнить. это уродливое решение, и для меня это не реалистично, потому что у меня много данных на экране, и я не собираюсь их перебирать. отрывочный код: (зацикленный и расточительный)

for(elem in group){
   elem.style.overflow = 'visible';
   var originalWidth = elem.offsetWidth;
   elem.style.overflow = 'hidden';
   if(elem.offsetWidth > originalWidth)
       elem.title = elem.innerHTML;
}

Если у вас есть что-то более существенное и менее "пятнистое", сообщите об этом.

Ответ 12

Ни один из вышеперечисленных решений не работал у меня, но я решил отличное решение. Самая большая ошибка, которую люди делают, - это наличие всех трех свойств CSS, объявленных в элементе на странице pageload. Вы должны добавить эти стили + подсказку динамически IF и ТОЛЬКО, если интервал, в котором вы хотите использовать эллипсы, шире, чем его родитель.

    $('table').each(function(){
        var content = $(this).find('span').text();
        var span = $(this).find('span');
        var td = $(this).find('td');
        var styles = {
            'text-overflow':'ellipsis',
            'white-space':'nowrap',
            'overflow':'hidden',
            'display':'block',
            'width': 'auto'
        };
        if (span.width() > td.width()){
            span.css(styles)
                .tooltip({
                trigger: 'hover',
                html: true,
                title: content,
                placement: 'bottom'
            });
        }
    });

Ответ 13

Вы могли бы окружить диапазон другим диапазоном, а затем просто проверить, превышает ли ширина исходного/внутреннего диапазона больше ширины нового/внешнего диапазона. Обратите внимание, что я говорю, возможно, это примерно основано на моей ситуации, когда у меня был span внутри td, поэтому я действительно не знаю, что если он будет работать с span внутри span,

Вот мой код для других, которые могут оказаться в положении, подобном моему; Я копирую/вставляю его без изменений, даже если он находится в контексте Angular, я не думаю, что это умаляет читаемость и существенную концепцию. Я закодировал его как метод службы, потому что мне нужно было применить его в нескольких местах. Селектор, который я прошел, был селектором классов, который будет соответствовать нескольким экземплярам.

CaseService.applyTooltip = function(selector) {
    angular.element(selector).on('mouseenter', function(){
        var td = $(this)
        var span = td.find('span');

        if (!span.attr('tooltip-computed')) {
            //compute just once
            span.attr('tooltip-computed','1');

            if (span.width() > td.width()){
                span.attr('data-toggle','tooltip');
                span.attr('data-placement','right');
                span.attr('title', span.html());
            }
        }
    });
}

Ответ 14

Вот решение Vanilla JavaScript:

(function init() {

  var cells = document.getElementsByClassName("cell");

  for(let index = 0; index < cells.length; ++index) {
    let cell = cells.item(index);
    cell.addEventListener('mouseenter', setTitleIfNecessary, false);
  }

  function setTitleIfNecessary() {
    if(this.offsetWidth < this.scrollWidth) {
      this.setAttribute('title', this.innerHTML);
    }
  }

})();
.cell {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px;
  border-style: solid;
  width: 120px; 
}
<div class="cell">hello world!</div>
<div class="cell">hello mars! kind regards, world</div>

Ответ 15

Это было мое решение, работает как шарм!

    $(document).on('mouseover', 'input, span', function() {
      var needEllipsis = $(this).css('text-overflow') && (this.offsetWidth < this.scrollWidth);
      var hasNotTitleAttr = typeof $(this).attr('title') === 'undefined';
      if (needEllipsis === true) {
          if(hasNotTitleAttr === true){
            $(this).attr('title', $(this).val());
          }
      }
      if(needEllipsis === false && hasNotTitleAttr == false){
        $(this).removeAttr('title');
      }
  });