質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

5回答

1030閲覧

文字数制限をして…を出す際にhtmlソースは除外して処理したいです

hiro421

総合スコア63

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

1クリップ

投稿2017/11/29 00:05

文字数制限をして設定した文字数を超えると…をだして省略するというものを下記URLを参考に実装しました。

http://black-flag.net/jquery/20121010-4227.html

html

1<p class="txt"><strong>全角テキスト全角テキスト全角テキスト全角テキスト</strong><br> 2全角テキストtexttexttexttexttexttexttexttexttexttexttexttexttexttext</p>

javascript

1 var $setElmTopics = $('.txt'); 2 var cutFigureTopics = '50'; // カットする文字数 3 var afterTxtTopics = ' …'; // 文字カット後に表示するテキスト 4 5 $setElmTopics.each(function(){ 6 var textLength = $(this).text().replace(/\s+/g,'').length; 7 var textTrim = $(this).text().substr(0,(cutFigureTopics)) 8 9 if(cutFigureTopics < textLength) { 10 $(this).html(textTrim + afterTxtTopics).css({visibility:'visible'}); 11 } else if(cutFigureTopics >= textLength) { 12 $(this).css({visibility:'visible'}); 13 } 14 });

ただこの方法だと、<strong><br>などのタグが消えてしまい。。
理想としては下記のようなものを作りたいのですが、どのように記述すればいいかが検討がついておりません。

・文字数は<strong><br>などのソースをぬかして、全角では1文字半角では0.5文字として50文字
・50文字を超えると末尾に…をつける
<strong><br>などのソースは消したくない

下記の3番目の形が近いと思うのですが。。
http://gallery.renowan.com/archive/multByteStringSlice/app/index.html

ヒントでも構いませんので、よろしくお願いいたします!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2017/11/29 00:40

CSS の text-overflow: ellipsis では代用できなさそうですか?
yambejp

2017/11/29 00:47

かりに<strong>の途中で超えた場合はどうするのでしょう?閉じるタグがなくなりませんか?逆に無条件にタグを残すと<br>が含まれているとひたすら改行だけ後ろに残った文書になりませんか?
guest

回答5

0

この手のものをまともに処理しようとするとかなり複雑になるし、全角/半角は言うのは簡単ですが判別は大変です。
そこで、幅を固定し、text-overflow: ellipsis を使うのはどうでしょうか?
https://developer.mozilla.org/ja/docs/Web/CSS/text-overflow

-- 追記。
ノード操作をした一例です。ちょっとうんざりしてくるのではないでしょうか?

JavaScript

1function isHalf(code) { 2 return (code >= 0x0 && code < 0x81) || (code == 0xf8f0) || (code >= 0xff61 && code < 0xffa0) || (code >= 0xf8f1 && code < 0xf8f4); 3} 4 5function truncateTextNode(textNode) { 6 var text = textNode.nodeValue; 7 var newText = ''; 8 for (var i = 0; i < text.length; i++) { 9 var c = text.charCodeAt(i); 10 var cost = isHalf(c) ? 0.5 : 1; 11 if (cost > remain) { 12 remain = -1; 13 textNode.nodeValue = newText; 14 return; 15 } 16 17 newText += text.charAt(i); 18 remain -= cost; 19 } 20 21 textNode.nodeValue = newText; 22} 23 24var remain = 50; 25var root = document.querySelector('p.txt'); 26var tw = document.createTreeWalker(root); 27var node; 28while (node = tw.nextNode()) { 29 switch (node.nodeType) { 30 case document.ELEMENT_NODE: 31 if (remain < 0) { 32 node.setAttribute('data-remove', '1'); 33 } 34 35 break; 36 case document.TEXT_NODE: 37 truncateTextNode(node); 38 break; 39 } 40} 41 42if (remain < 0) { 43 $(root.querySelectorAll('[data-remove]')).remove(); 44 root.appendChild(document.createTextNode('…')); 45}

投稿2017/11/29 01:10

編集2017/11/29 07:51
x_x

総合スコア13749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

HTML

1<p class="txt"><strong>全角テキスト全角テキスト全角テキスト全角テキスト</strong><br> 2全角テキストtexttexttexttexttexttexttexttexttexttexttexttexttexttext</p>

テキストノードの途中で区切られるケースを踏まえると、下記のようにマークアップを変更すれば良いですね。

HTML

1<p class="txt"><strong>全角テキスト全角テキスト<span hidden>全角テキスト全角テキスト</span></strong><span hidden><br> 2全角テキストtexttexttexttexttexttexttexttexttexttexttexttexttexttext</span></p>

大雑把な手順は下記の通り。

  1. XPath でテキストノードを得る
  2. 指定文字数を超えたら、超過分を <span hidden></span> で括る

簡単に書いてますが、

  • インラインコンテンツのみでないと、<span> で括れない(computrdStyleの display値を読み取って括る要素を変化させれば対策可)
  • 孫要素が存在したら祖先要素に渡って <span> で括らなければならない

など、考えるべき例外ケースはいくつかあります。
状況を固定すれば対策が少なくなるので、どれだけの状況に対応する汎用性を持たせるか、で難易度が変わってきます。

Re: hiro421 さん

投稿2017/11/29 04:54

think49

総合スコア18156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

本気で処理したいなら、逆にタグをフルに考える形でないと処理できません。

手順としては、

  1. まず、切り詰めたいHTMLをDOM要素に起こす
  2. 以下の操作を、外側のDOM要素のchildNodesに対して行っていく
  • テキストノードだったら、文字数をカウント
  • HTML要素だったら、さらに再帰的に実行
  • 文字数をカウントし続けて制限を超えた後は、残りのノードをすべて削除

投稿2017/11/29 02:08

maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

javascript

1var test = ( 2 (count, tagFlag, length) => e => { 3 if ( count>=length ) 4 return ''; 5 if ( e==='<' ) 6 tagFlag = true; 7 if ( !tagFlag ) { 8 count++; 9 if ( e.codePointAt(0) > 128 ) 10 count++; 11 } 12 if ( e=='>' ) 13 tagFlag = false; 14 return e; 15 } 16)(0, false, 50); 17 18Array.from(`<strong>全角テキスト全角テキスト全角テキスト全角テキスト</strong><br> 19全角テキストtexttexttexttexttexttexttexttexttexttexttexttexttexttext`, e => test(e) ).join('')+'…'; 20 21/* 22<strong>全角テキスト全角テキスト全角テキスト全角テキスト</strong><br> 23全… 24*/ 25

投稿2017/11/29 04:16

Lhankor_Mhy

総合スコア35865

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

アイデアですが、
1.正規表現で<p class="txt">内部の「<」で始まり「>」で終わる文字列を検索
2.htmlタグが挿入されている座標とhtmlタグを配列に記憶しておいて、タグ部分は空文字に置き換え
3.2でタグを取り除いたテキストを50文字に制限して、末尾を「…」に置き換え
4.最後に3に対して、記憶しておいたhtmlタグを、記憶しておいた座標に差し込んでいく

なんて感じでどうでしょうか

投稿2017/11/29 00:41

編集2017/11/29 00:44
comcom_0905

総合スコア44

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問