Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Плагин обрезающий текст для jQuery (https://javascript.ru/forum/project/21063-plagin-obrezayushhijj-tekst-dlya-jquery.html)

devote 27.08.2011 12:03

Плагин обрезающий текст для jQuery
 
Вот штампанул тока что плагин для jQuery, может кому надо будет... Что делает!? все просто, обрезает лишние строки. Тоесть первый параметр число указывающее скока можно строк отображать, и если текст превышает это число строк, то скрипт обрежет текст и подставит то что указано во втором параметре. По сути он не обрезает текст, а просто в то место где кончается строка, он вставляет то что указано во втором параметре.

вот смотрите:
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript">
(function( $ ){
$.fn.correctLines = function( maxLine, moreText ) {
	return this.each(function( index, self ) {
		var temp, classes, i, lineHeight;

		maxLine = ( temp = /^(?:.*\s)?fixline_([\d]+)(?:\s.*)?$/.exec( self.className ) ) && temp[1] || maxLine || 3;
		moreText = moreText || '...<br />';

		var od = $( self ).css( "display" );
		var clone = $( self ).css( "display", "block" ).clone( true ).
				css( {"height": "auto", "position": "absolute", "width": self.offsetWidth + "px" } ).html("");
		$( self ).css( "display", od ).after( clone );

		var height = 0,
			width = self.offsetWidth,
			lines = 0,
			lastHeight = 0,
			startWord = 0,
			endWord = -1,
			txt = self.innerHTML,
			part = [];

			while( /(<.*)\s(.*>)/g.exec( txt ) ) {
				txt = txt.replace(/(<.*)\s(.*>)/g, '$1&jftF767Tgjk56&$2');
			}
			txt = txt.split(' ');

		for( i = 0; i < txt.length; i++ ) {

			txt[i] = txt[i].replace(/&jftF767Tgjk56&/g, ' ');
			clone[0].innerHTML += txt[ i ] + ' ';

			if ( clone[0].clientHeight > lastHeight ) {

				height = lastHeight;
				startWord = endWord + 1;
				endWord = i - 1;

				lastHeight = clone[0].offsetHeight;

				if ( ++lines > maxLine ) {
					break;
				}
			}
		}

		if ( lines > maxLine ) {

			$( self ).css({height: height + "px", overflowY: 'hidden'});

			part = txt.slice( startWord, endWord + 1 );
			height = clone.html( part.join(' ') )[0].offsetHeight;
			for( i = part.length - 1; i >= 0; i-- ) {

				clone.html( part.join(' ') + moreText );

				if ( clone[0].offsetHeight > height ) {
					part.splice( i, 1 );
					endWord--;
				} else {
					break;
				}
			}

			txt[ endWord ] += moreText;

			self.innerHTML = txt.join(" ");
		} else {
			$( self ).css({height: "auto"});
		}

		clone.remove();
	});
}
})( jQuery );
</script>

<div style="width: 200px; border: 1px solid #000;">
	<div class="correct_comment">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla tincidunt nunc commodo magna posuere sollicitudin. Quisque ultrices sodales nisi eu sagittis.</div>
</div>

<br />
<style>.fvem1{width:200px;font-size:14px;border:1px solid #000000;}</style> 
<div class="fvem1"> 
    <div class="correct_comment">Loremipsud <div style="font-size:45px">olorsitmet</div>, consecteturad ipiscingelit. Nulla tincidunt nunc commodo magna posuere sollicitudin. Quisque ultrices sodales nisi eu sagittis.</div> 
</div>
<br />
<style>.fvem2{width:20%;font-size:14px;border:1px solid #000000;}</style>
<div class="fvem2">
	<div class="correct_comment">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla tincidunt nunc commodo magna posuere sollicitudin. Quisque ultrices sodales nisi eu sagittis.</div>
</div>

<script type="text/javascript">
	jQuery(".correct_comment").correctLines( 3, '<span onclick="jQuery(this).parent().css(\'height\', \'auto\').end().hide();">...&nbsp;<span style="color: #f00; text-decoration: underline; cursor: pointer;">more</span></span>' );
</script>
В примере текст на пять строк, но я ему говорю что надо тока три. В реале он их не обрезает, а просто в ту часть где нужно вставляет то что указано во втором параметре, а если не указано то ставить троеточее и перевод строки.

Gozar 27.08.2011 12:21

Я правильно понял, что для того, чтобы посчитать количество k - переводов строк(\n - <br>) и в случае если k> заданного сделать subsring по последнему пробелу меньше допустим 400 символов с подстановкой за ними трех точек, ты написал 121 строку?

И зачем в твоем скрипте столько обращений к style?

devote 27.08.2011 12:24

Цитата:

Сообщение от Gozar
ты написал 121 строку?

слушай я написал это за 15 мин от скуки, понятно дело не оптимизировал, и т.д. а шо прада много style чтоль?:D Ну ппц, видимо от невысыпания что-то я там нахимичил ;) Ну ниче, еще надо 15 мин на него и глядишь строк меньше станет :lol:

devote 27.08.2011 12:25

а вообще ты прав там слишком много ненужного мусора... хм... что-то я погорячился

Gozar 27.08.2011 12:27

напиши в 3 строки, по крайней мере большее количество возможно не потребуется ))

devote 27.08.2011 12:28

А слушай, стал то нужен для выяснения размера мать его строки в высоту... ну он же леально текст то не режет, а блок протсто уменьшает, и оверфлоу ставит... но тем немение можно сделать поменьше кода всеж

devote 27.08.2011 12:29

Цитата:

Сообщение от Gozar
Я правильно понял, для того чтобы посчитать количество k - переводов строк(\n - <br>) и в случае если k> заданного сделать subsring

Нет не правильно, в тексте нету этих переводов, текст в одну строку... посмотри внимательно

Gozar 27.08.2011 12:29

Цитата:

Сообщение от devote (Сообщение 122863)
А слушай, стал то нужен для выяснения размера мать его строки в высоту

ой, что-то мне кажется такое решение сомнительным.

devote 27.08.2011 12:30

Будь там эти (\n - <br>) тогда и хрень эту писать не пришлось бы.)

devote 27.08.2011 12:31

Цитата:

Сообщение от Gozar
ой, что-то мне кажется такое решение сомнительным.

Главное фурычит :D

Gozar 27.08.2011 12:31

применение плагина?

devote 27.08.2011 12:33

а этот кусок можно вообще удалить:
if ( self.className.indexOf('fixline_') >= 0 ) { 
            classes = self.className.split(" "); 
            for( i = 0; i < classes.length; i++ ) { 
                if ( classes[ i ].indexOf('fixline_') >= 0) { 
                    temp = classes[ i ].split("_"); 
                    maxLine = parseInt( temp[1] ); 
                    break; 
                } 
            } 
        }
Он нужен для того что бы можно было указать класс у элемента с числом строк, типо универсал и все такое... ну пример у меня стоит так:
<div class="correct_comment">

а можно так:
<div class="correct_comment fixline_2">

и тогда приоритет будет не первый параметр у функции, а то число что стоит после fixline_

melky 27.08.2011 12:34

devote, я думал, плагины для jQuery пишутся на jQuery ;)

ну там всякие hasClass, $.each, фишки да цепочки вызовов

devote 27.08.2011 12:38

Цитата:

Сообщение от Gozar
применение плагина?

все очень просто:
смотрим первый пост

devote 27.08.2011 12:39

Цитата:

Сообщение от melky (Сообщение 122870)
devote, я думал, плагины для jQuery пишутся на jQuery ;)

ну там всякие hasClass, $.each, фишки да цепочки вызовов

Да тупая привычка писать на чистом js, никак не могу привыкнуть к тому что это jQuery :D

devote 27.08.2011 13:40

Вот немного его уменьшил:
смотрим первый пост

melky 27.08.2011 14:06

еще парочку подкину идей для сжатия кода.

jQuery.fn.correctLines = function( maxLine, moreText ) {

		var self = this[ 0 ], temp, classes, i, lineHeight, 
*!*
               $ = jQuery;
*/!*

.....
lineHeight.toString().indexOf("px") > 0

~(lineHeight+'').indexOf("px")

....
clone.html('');
jQuery( document.body ).append( clone );

jQuery( document.body ).append(  clone.empty() );

....
for( i = 0; i < txt.length; i++ ) {

			clone[0].innerHTML += txt[ i ] + ' ';

			if ( clone[0].offsetHeight > lastHeight ) {
				if ( lastHeight == 0 ) {
					height = clone[0].offsetHeight;
				}
				startWord = endWord + 1;
				endWord = i - 1;
				lines++;
				lastHeight = clone[0].offsetHeight;
			}

			if ( lines > maxLine ) {
				break;
			}
		}


jQuery.each :
Цитата:

We can break the $.each() loop at a particular iteration by making the callback function return false. Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
$.each(txt, function(i, a) {

    clone[0].innerHTML += a + ' ';

    if (clone[0].offsetHeight > lastHeight) {

        if (lastHeight == 0) {
            height = clone[0].offsetHeight;
        }

        startWord = endWord + 1;
        endWord = i - 1;
        lastHeight = clone[0].offsetHeight;
    }

    if ( ++lines > maxLine) return false;
});

...
this.css({
*!*
    height: lines > maxLine ? (lineHeight * maxLine) + "px" *!*: "auto"*/!*,
*/!*
    overflowY: 'hidden'
});

?????

.....
for( i = startWord; i <= endWord; i++ ) {
			part.push( txt[ i ] );
		}

		for( i = part.length - 1; i >= 0; i-- ) {

			clone.html( part.join(' ') + moreText );

			if ( clone[0].offsetHeight > height ) {
				part.splice( i, 1 );
				endWord--;
			} else {
				break;
			}
		}

не удумал, как заменить, но повторябщиеся операции всегда надо заменять

devote 27.08.2011 14:11

Цитата:

Сообщение от melky
еще парочку подкину идей для сжатия кода.

Да привычка у мну писать на чистом JS от того и джуквери не особо люблю, пишу тока на нем когда надо чето по бырому. А этот плуг и есть бобырому =) Но замечания справедливы не спорю.

devote 27.08.2011 15:36

Внес изменения в первый пост, с замечаниями от melky, кроме конечно .each() она мне не катит, там у мну break стоит, а этот .each() на это не предусмотрен.

melky 27.08.2011 16:01

я там дал выдержку из документации и подчеркнул кой чего :)

devote 27.08.2011 16:05

Цитата:

Сообщение от melky
я там дал выдержку из документации и подчеркнул кой чего

Да я вкурсе, что можно вернуть false, а про брейк так с дуру ляпнул...

melky 27.08.2011 16:27

devote, еще чуть-чуть.
дальше совершаются операции, о которых ведаете только вы :)
$.fn.correctLines = function( maxLine, moreText ) {

....

        var clone = $( self ).clone( true ).
                css( {"height": "auto", "width": self.offsetWidth + "px"} ).html("W");

        lineHeight = this.css('line-height');

        if ( lineHeight == "normal" ) {

            *!*$( document.body ).append( clone );*/!*
            *!*lineHeight = clone[0].clientHeight;*/!*
            *!*clone.remove();*/!*

        } else if ......

        var height = lineHeight,
            width = self.offsetWidth,
            .....


        *!*$( document.body ).append( clone.empty() );*/!*


$.fn.correctLines = function( maxLine, moreText ) {

....

        var clone = $( self ).clone( true ).
                css( {"height": "auto", "width": self.offsetWidth + "px"} ).html("W");

      
        *!*clone.appendTo( document.body );*/!*


        lineHeight = this.css('line-height');

        if ( lineHeight == "normal" ) {
            lineHeight = clone[0].clientHeight;
        } else if ......

        var height = lineHeight,
            width = self.offsetWidth,
            .....
     

        *!*clone.empty();*/!*

devote 27.08.2011 17:11

Цитата:

Сообщение от melky
clone.empty().appendTo( document.body );

не прокатит, ибо размер блока будет нулевым в этом случае... Я же не просто так создаю клон и сую в него "W" что бы он имел высоту строки.

melky 27.08.2011 17:42

Цитата:

Сообщение от devote (Сообщение 122945)
не прокатит, ибо размер блока будет нулевым в этом случае... Я же не просто так создаю клон и сую в него "W" что бы он имел высоту строки.

прошу прощения. это уже я пропустил empty. поправил. невнимательность :)

devote 27.08.2011 18:04

гуд... ну больше уж точно некуда тут оптимизить, хотя если хорошенько все продумать то вполне возможно и можно.

Gozar 27.08.2011 18:06

Перестало работать

devote 27.08.2011 18:08

Цитата:

Сообщение от Gozar
Перестало работать

Как так? В демонстрашке первого поста все пашет, какой бравзер?

devote 27.08.2011 18:10

да в файрфоксе что-то перестало пахать

devote 27.08.2011 18:12

поправил, убрал знак ~ из кода: ~( lineHeight + '' ).indexOf("px")

devote 27.08.2011 18:21

Ну дык че, полезный хоть миниплаг? Или хренью я занимаюсь? Фишка этого плага в том что он не считает строки по \n <br /> а считает их именно так как ставит браузер, тоесть это удобно например делать там где люди оставляют огромные коменты, и их можно свернуть таким образом. Или иногда на сайтах нужно в каком нить блоке показать часть новостей или чего либо подобного, тоже удобно. Не нужно считать там количество букв, не зная при этом размер шрифта и т.д. Думаю я где нить его точняк пришпандолю в каком нить проекте который буду делать =)

Gozar 27.08.2011 18:22

<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript">
(function( $ ){
	$.fn.correctLines = function( maxLine, moreText ) {

		var self = this[ 0 ], temp, classes, i, lineHeight;

		maxLine = ( temp = /^(?:.*\s)?fixline_([\d]+)(?:\s.*)?$/.exec( self.className ) ) && temp[1] || maxLine || 3;
		moreText = moreText || '...<br />';

		var clone = $( self ).clone( true ).
				css( {"height": "auto", "width": self.offsetWidth + "px"} ).html("W");

		clone.appendTo( document.body );

		lineHeight = this.css('line-height');

		if ( lineHeight == "normal" ) {
			lineHeight = clone[0].clientHeight;
		} else if ( ( lineHeight + '' ).indexOf("px") > 0 ) {
			lineHeight = parseInt( lineHeight );
		} else {
			lineHeight = parseInt( this.css('font-size') ) * parseFloat( lineHeight );
		}

		var height = lineHeight,
			width = self.offsetWidth,
			lines = 0,
			lastHeight = 0,
			startWord = 0,
			endWord = -1,
			txt = self.innerHTML.split(" "),
			part = [];

		clone.empty();

		for( i = 0; i < txt.length; i++ ) {

			clone[0].innerHTML += txt[ i ] + ' ';

			if ( clone[0].offsetHeight > lastHeight ) {
				if ( lastHeight == 0 ) {
					height = clone[0].offsetHeight;
				}
				startWord = endWord + 1;
				endWord = i - 1;
				lastHeight = clone[0].offsetHeight;

				if ( ++lines > maxLine ) {
					break;
				}
			}
		}

		if ( lines > maxLine ) {

			this.css({height: ( lineHeight * maxLine ) + "px", overflowY: 'hidden'});

			part = txt.slice( startWord, endWord + 1 );

			for( i = part.length - 1; i >= 0; i-- ) {

				clone.html( part.join(' ') + moreText );

				if ( clone[0].offsetHeight > height ) {
					part.splice( i, 1 );
					endWord--;
				} else {
					break;
				}
			}

			txt[ endWord ] += moreText;

			self.innerHTML = txt.join(" ");
		} else {
			this.css({height: "auto"});
		}

		clone.remove();
	}
})( jQuery );
</script>
<style>.fvem{width:20%;font-size:14px;border:1px solid #000000;}</style>
<div class="fvem">
	<div class="correct_comment">Loremipsudolorsitmet, consecteturadipiscingelit. Nulla tincidunt nunc commodo magna posuere sollicitudin. Quisque ultrices sodales nisi eu sagittis.</div>
</div>

<script type="text/javascript">
	jQuery(".correct_comment").correctLines( 3, '<span onclick="jQuery(this).parent().css(\'height\', \'auto\').end().hide();">... <span style="color: #f00; text-decoration: underline; cursor: pointer;">more</span></span>' );
</script>

devote 27.08.2011 18:24

Gozar,
ща подумаю над этим, где-то что-то я упустил

Gozar 27.08.2011 18:25

devote,
Некоторые вещи лучше не делать чем делать. Идея забавна, но по мне так маложизнеспособна.

Gozar 27.08.2011 18:35

Это был не самый распространенный вариант, а теперь сюрприз, самый распространенный:
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript">
(function( $ ){
	$.fn.correctLines = function( maxLine, moreText ) {

		var self = this[ 0 ], temp, classes, i, lineHeight;

		maxLine = ( temp = /^(?:.*\s)?fixline_([\d]+)(?:\s.*)?$/.exec( self.className ) ) && temp[1] || maxLine || 3;
		moreText = moreText || '...<br />';

		var clone = $( self ).clone( true ).
				css( {"height": "auto", "width": self.offsetWidth + "px"} ).html("W");

		clone.appendTo( document.body );

		lineHeight = this.css('line-height');

		if ( lineHeight == "normal" ) {
			lineHeight = clone[0].clientHeight;
		} else if ( ( lineHeight + '' ).indexOf("px") > 0 ) {
			lineHeight = parseInt( lineHeight );
		} else {
			lineHeight = parseInt( this.css('font-size') ) * parseFloat( lineHeight );
		}

		var height = lineHeight,
			width = self.offsetWidth,
			lines = 0,
			lastHeight = 0,
			startWord = 0,
			endWord = -1,
			txt = self.innerHTML.split(" "),
			part = [];

		clone.empty();

		for( i = 0; i < txt.length; i++ ) {

			clone[0].innerHTML += txt[ i ] + ' ';

			if ( clone[0].offsetHeight > lastHeight ) {
				if ( lastHeight == 0 ) {
					height = clone[0].offsetHeight;
				}
				startWord = endWord + 1;
				endWord = i - 1;
				lastHeight = clone[0].offsetHeight;

				if ( ++lines > maxLine ) {
					break;
				}
			}
		}

		if ( lines > maxLine ) {

			this.css({height: ( lineHeight * maxLine ) + "px", overflowY: 'hidden'});

			part = txt.slice( startWord, endWord + 1 );

			for( i = part.length - 1; i >= 0; i-- ) {

				clone.html( part.join(' ') + moreText );

				if ( clone[0].offsetHeight > height ) {
					part.splice( i, 1 );
					endWord--;
				} else {
					break;
				}
			}

			txt[ endWord ] += moreText;

			self.innerHTML = txt.join(" ");
		} else {
			this.css({height: "auto"});
		}

		clone.remove();
	}
})( jQuery );
</script>
<style>.fvem{width:200px;font-size:14px;border:1px solid #000000;}</style>
<div class="fvem">
	<div class="correct_comment">Loremipsud <div style="font-size:45px">olorsitmet</div>, consecteturad ipiscingelit. Nulla tincidunt nunc commodo magna posuere sollicitudin. Quisque ultrices sodales nisi eu sagittis.</div>
</div>

<script type="text/javascript">
	jQuery(".correct_comment").correctLines( 3, '<span onclick="jQuery(this).parent().css(\'height\', \'auto\').end().hide();">... <span style="color: #f00; text-decoration: underline; cursor: pointer;">more</span></span>' );
</script>

devote 27.08.2011 18:59

Gozar,
Все поправил, можешь наслаждаться =)

Gozar 27.08.2011 19:19

devote,
Как же я могу наслаждаться если второй блок имеет прокрутку и текст не читается?
Гибкость настройки такого плагина сравнима с кирпичом. В то же самое время любой веб мастер порежет текст до помещающихся в, заранее известного размера, блок символов текста, обрезая их по последнему пробелу и это все уместиться в 1-2 строки.

devote 27.08.2011 19:59

Все сделал, куча всего даже снес =) Но вообще не рекомендуется пихать в текст теги с какими либо атрибутами... Но хотя щас я это учел...

Наслаждайтесь! )))

devote 28.08.2011 16:29

Цитата:

Сообщение от Gozar
В то же самое время любой веб мастер порежет текст до помещающихся в, заранее известного размера, блок символов текста, обрезая их по последнему пробелу и это все уместиться в 1-2 строки.

Не соглашусь с тобой, если прогер будет резать текст, это уже будет говорить о том что в тексте нет тегов, ибо я сомневаюсь что прогер будет резать текст при этом в котором имеются теги. Это уже получиться не корректный текст... Мой плагин с обычным текстом работает вполне корректно, я не рассчитывал на то что в тексте будут присутствовать теги, хотя некоторые вполне уже после твоих замечаний можно вставлять, такие как b, i, и т.д. да и любые без атрибутов. Так что не надо говорить что скрипт Г и не нужен, кому-то пригодиться да и с обычным текстом он вполне корректно работает... И повторюсь, "если прогер планирует резать текст, значит в тексте нету тегов". Ну а если в тексте есть теги и прогер режет текст, то таких прогеров, прогерами не назовешь.

Gozar 28.08.2011 18:57

devote,
Не пользователи для программистов, а программисты для пользователей.

Вот три причины по которым лично я не буду использовать этот плагин никогда:
1. Слишком большой скрипт, для решения задач вёрстки. Если можно решить проблему вёрсткой - css+html, то я буду решать задачу вёрсткой.

2. Пользователи пихают в текст всё подряд и придется резать теги скриптом, а значит нужен в 4 раза короче скрипт, который будет резать теги и заодно обрезать по символу.

3. На сайте может и чаще всего бывает и так много скриптов и нужна очень веская причина подключить ещё один.

devote 28.08.2011 19:17

Цитата:

Сообщение от Gozar
1. Слишком большой скрипт, для решения задач вёрстки. Если можно решить проблему вёрсткой - css+html, то я буду решать задачу вёрсткой.

Для данной функциональности я считаю это не такой и большой скрипт.. Хотя если ты можешь написать меньше кода не теряя при этом функционал... То я не против посмотреть на это.

Цитата:

Сообщение от Gozar
2. Пользователи пихают в текст всё подряд и придется резать теги скриптом, а значит нужен в 4 раза короче скрипт, который будет резать теги и заодно обрезать по символу.

Мне не важно что они пихают, теги они пихать не смогут. Для этого и сущетвую специальные функции которые не позволяют тегам вести себя как тег. Напрмер htmlspecialshars тоесть при выборке из базы весь текст проходит через эту функцию, а можно вообще сразу записывать в базу прогнав через нее до вставки записи в БД.

Цитата:

Сообщение от Gozar
3. На сайте может и чаще всего бывает и так много скриптов и нужна очень веская причина подключить ещё один.

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


Часовой пояс GMT +3, время: 21:12.