Здравствуйте. Помогите, пожалуйста, поправить ошибки в скрипте, который скрывает
часть длинного текста. А именно, если в тексте есть параграфы, то он их игнорирует
или скрывает после первого, или еще любым другим способом как ему угодно. Если текст
идет сплошной, без параграфов, то скрипт работает правильно. И еще один момент, как
научить скрипт, чтобы он скрывал текст после точки, а не в средине предложения? Спасибо!
(function($) {
$.fn.truncate = function(options) {
var defaults = {
length: 100,
minTrail: 10,
moreText: "",
lessText: "",
ellipsisText: ""
};
var options = $.extend(defaults, options);
return this.each(function() {
obj = $(this);
var body = obj.html();
if (body.length > options.length + options.minTrail) {
var splitLocation = body.indexOf(' ', options.length);
if (splitLocation != -1) {
var splitLocation = body.indexOf(' ', options.length);
var str1 = body.substring(0, splitLocation);
var str2 = body.substring(splitLocation, body.length - 1);
obj.html(str1 + '' + options.ellipsisText +
'' + '' + str2 + '');
obj.find('.truncate_more').css("display", "none");
obj.append(
''
);
var moreLink = $('.truncate_more_link', obj);
var moreContent = $('.truncate_more', obj);
var ellipsis = $('.truncate_ellipsis', obj);
moreLink.click(function() {
if (moreLink.text() == options.moreText) {
moreContent.show('normal');
moreLink.text(options.lessText);
ellipsis.css("display", "none");
} else {
moreContent.hide('normal');
moreLink.text(options.moreText);
ellipsis.css("display", "inline");
}
return false;
});
}
}
});
};
})(jQuery);
$().ready(function() {
$('.story').truncate({
length: 20,
minTrail: 10,
moreText: 'Подробнее',
lessText: 'Скрыть',
ellipsisText: "[...]"
});
});
.story {
margin: 0 0 20px 0;
}
В этом блоке нет параграфов. Однажды осенью матушка варила в гостиной
медовое варенье, а я, облизываясь, смотрел на кипучие пенки. Батюшка у окна читал Придворный
календарь, ежегодно им получаемый. Эта книга имела всегда сильное нљ него влияние: никогда
не перечитывал он ее без особенного участия, и чтение это производило в нем всегда
удивительное волнение желчи. Матушка, знавшая наизусть все его свычаи и обычаи, всегда
старалась засунуть несчастную книгу как можно подалее, и таким образом Придворный
календарь не попадался ему на глаза иногда по целым месяцам. Зато, когда он случайно
его находил, то, бывало, но целым часам не выпускал уж из своих рук. Итак, батюшка
читал Придворный календарь, изредка пожимая плечами и повторяя вполголоса: «Генерал-поручик!..
Он у меня в роте был сержантом!.. Обоих российских орденов кавалер!. А давно ли
мы...» Наконец батюшка швырнул календарь на диван и погрузился в задумчивость, не предвещавшую
ничего доброго.
В этом блоке есть параграфы.
Однажды осенью матушка варила в гостиной медовое варенье, а я, облизываясь,
смотрел на кипучие пенки. Батюшка у окна читал Придворный календарь, ежегодно им получаемый.
Эта книга имела всегда сильное нљ него влияние: никогда не перечитывал он ее
без особенного участия, и чтение это производило в нем всегда удивительное волнение
желчи.
Матушка, знавшая наизусть все его свычаи и обычаи, всегда старалась засунуть
несчастную книгу как можно подалее, и таким образом Придворный календарь не попадался
ему на глаза иногда по целым месяцам. Зато, когда он случайно его находил, то, бывало,
но целым часам не выпускал уж из своих рук.
Итак, батюшка читал Придворный календарь, изредка пожимая плечами и повторяя
вполголоса: «Генерал-поручик!.. Он у меня в роте был сержантом!.. Обоих российских
орденов кавалер!. А давно ли мы...» Наконец батюшка швырнул календарь на диван и погрузился
в задумчивость, не предвещавшую ничего доброго.
Ответы
Ответ 1
Чтобы текст скрывал после точки - надо и искать точку, а не пробел, как сейчас.
Для того, чтобы использовать скрипт не только с текстом, но и с текстом включающим
теги его нужно сильно модифицировать.
не использовать .html();, который возвращает html в виде текста. В этом случае можно
случайно разрезать тег пополам.
можно рассматривать элемент с классом story и его дочерние элементы в виде дерева
В таком виде можно разделить узел в котором находится искомая подстрока на то, что
надо показать и то, что надо скрыть, попутно добавив служебный элемент с ..., а все
соседние справа узлы поместить в элемент, который надо скрыть
Примером реализации функции, которая определяет узел который надо разделять может
стать следующая функция find
function find(container, text, minLength) {
var curIndex = 0;
// обход дерева в глубину
for (var nodes = Array.from(container.childNodes); nodes.length;) {
var node = nodes.shift();
if (node.nodeType == Node.ELEMENT_NODE) { // если не дошли до нижнего уровня
спускаемся дальше
nodes.unshift(...node.childNodes);
continue;
}
// определяем наличием искомой строки в текущем узле
var index = -1;
do {
index = node.textContent.indexOf(text, index + 1);
} while (index != -1 && curIndex + index < minLength);
// если строка найдена и соблюдено условие минимальной показываемой длины
if (index != -1) {
curIndex += index;
return [node, index]; // возвращаем найденный узел и индекс, по которому его
надо разделить
} else {
curIndex += node.textContent.length;
}
}
return [null, -1];
}
После получения узла и точки разбиения, нужно разбить текстовое содержимое на две
части: то что надо показать и то что надо скрыть. В самом узле оставить только часть
которая видна.
Добавить справа от текущего служебный узел с [...]
Добавить справа узел со скрытым текстом.
Подняться на уровень выше, и все соседние справа элементы поместить в узел отвечающий
за скрытый текст
повторять пункт 8 пока не поднимемся до самого контейнера - элемента с классом .story
Пример конечной реализации:
(function($) {
$.fn.truncate = function(options) {
var defaults = {
length: 100,
minTrail: 10,
moreText: "",
lessText: "",
ellipsisText: ""
};
var options = $.extend(defaults, options);
function find(container, text, minLength) {
var curIndex = 0;
for (var nodes = Array.from(container.childNodes); nodes.length;) {
var node = nodes.shift();
if (node.nodeType == Node.ELEMENT_NODE) {
nodes.unshift(...node.childNodes);
continue;
}
var index = -1;
do {
index = node.textContent.indexOf(text, index + 1);
} while (index != -1 && curIndex + index < minLength);
if (index != -1) {
curIndex += index;
return [node, index];
} else {
curIndex += node.textContent.length;
}
}
return [null, -1];
}
return this.each(function() {
var obj = $(this);
var body = this.textContent;
if (body.length > options.length + options.minTrail) {
var textToFind = '.';
if (body.indexOf(textToFind, options.length) != -1) {
var [node, startIndex] = find(this, textToFind, options.length);
var splitLocation = startIndex + textToFind.length;
var str1 = node.textContent.substring(0, splitLocation);
var str2 = node.textContent.substring(splitLocation + 1);
node.textContent = str1;
if (str2.length) {
$(node).after(`${str2}`);
}
$(node).after(`${options.ellipsisText}`);
var oi = 0;
while (node != this) {
var span = $('').addClass('truncate_more');
for (var nextNode = node.nextSibling, savedNode; nextNode; nextNode =
savedNode) {
if (nextNode.classList && (nextNode.classList.contains('truncate_more')
|| nextNode.classList.contains('truncate_ellipsis'))) continue;
savedNode = nextNode.nextSibling;
span.append(nextNode);
}
node = node.parentNode;
$(node).append(span);
}
obj.find('.truncate_more').css("display", "none");
obj.append(
''
);
var moreLink = $('.truncate_more_link', obj);
var moreContent = $('.truncate_more', obj);
var ellipsis = $('.truncate_ellipsis', obj);
moreLink.click(function() {
if (moreLink.text() == options.moreText) {
moreContent.show('normal');
moreLink.text(options.lessText);
ellipsis.css("display", "none");
} else {
moreContent.hide('normal');
moreLink.text(options.moreText);
ellipsis.css("display", "inline");
}
return false;
});
}
}
});
};
})(jQuery);
$().ready(function() {
$('.story').truncate({
length: 20,
minTrail: 10,
moreText: 'Подробнее',
lessText: 'Скрыть',
ellipsisText: "[...]"
});
});
.story {
margin: 0 0 20px 0;
}
В этом блоке нет параграфов. Однажды осенью матушка варила в гостиной
медовое варенье, а я, облизываясь, смотрел на кипучие пенки. Батюшка у окна читал Придворный
календарь, ежегодно им получаемый. Эта книга имела всегда сильное нљ него влияние: никогда
не перечитывал он ее без особенного участия, и чтение это производило в нем всегда
удивительное волнение желчи. Матушка, знавшая наизусть все его свычаи и обычаи, всегда
старалась засунуть несчастную книгу как можно подалее, и таким образом Придворный
календарь не попадался ему на глаза иногда по целым месяцам. Зато, когда он случайно
его находил, то, бывало, но целым часам не выпускал уж из своих рук. Итак, батюшка
читал Придворный календарь, изредка пожимая плечами и повторяя вполголоса: «Генерал-поручик!..
Он у меня в роте был сержантом!.. Обоих российских орденов кавалер!. А давно ли
мы...» Наконец батюшка швырнул календарь на диван и погрузился в задумчивость, не предвещавшую
ничего доброго.
В этом блоке есть параграфы.
Однажды осенью матушка варила в гостиной медовое варенье, а я, облизываясь,
смотрел на кипучие пенки. Батюшка у окна читал Придворный календарь, ежегодно им получаемый.
Эта книга имела всегда сильное нљ него влияние: никогда не перечитывал он ее
без особенного участия, и чтение это производило в нем всегда удивительное волнение
желчи.
Матушка, знавшая наизусть все его свычаи и обычаи, всегда старалась засунуть
несчастную книгу как можно подалее, и таким образом Придворный календарь не попадался
ему на глаза иногда по целым месяцам. Зато, когда он случайно его находил, то, бывало,
но целым часам не выпускал уж из своих рук.
Итак, батюшка читал Придворный календарь, изредка пожимая плечами и повторяя
вполголоса: «Генерал-поручик!.. Он у меня в роте был сержантом!.. Обоих российских
орденов кавалер!. А давно ли мы...» Наконец батюшка швырнул календарь на диван и погрузился
в задумчивость, не предвещавшую ничего доброго.