sikaku

要素内の文字置き換えプラグイン

ある日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。

広い門の下には、この男のほかに誰もいない。ただ、所々丹塗の剥げた、大きな円柱に、蟋蟀が一匹とまっている。羅生門が、朱雀大路にある以上は、この男のほかにも、雨やみをする市女笠や揉烏帽子が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。

「羅生門」芥川龍之介

要素内の子孫要素まで探索して、文字のみ置き換えるプラグインです。

別件で入用だったので作成。個人的には結構便利。

何ができるの?

基本

jQuery要素内文字置き換え
  1. var pattern = /abc/g;
  2. var replacement = 'ABC';
  3. //通常の要素内文字置き換え
  4. $('#testA').text( $('#testA').text().replace(pattern,replacement) );
  5. //プラグイン使用時
  6. $('#testB').replaceText(pattern,replacement);

通常、jQeuryでHTML要素内の文字置き換えをしようとすると、のような形になります。

それをで済ませられるよってプラグインです。

HTML例

記述HTML
  1. <!--通常の要素内文字置き換え対象要素-->
  2. <div id="testA">abcdefg</div>
  3. <!--プラグイン使用時対象要素-->
  4. <div id="testB">abcdefg</div>
jQuery実行後HTML
  1. <!--通常の要素内文字置き換え対象要素-->
  2. <div id="testA">ABCdefg</div>
  3. <!--プラグイン使用時対象要素-->
  4. <div id="testB">ABCdefg</div>

指定要素内にHTML要素を内包している場合に有効

指定要素内にHTML要素を内包している場合、前述の「通常の要素内文字置き換えjQuery」でも、.text()メソッドを.html()メソッドに変更することで対応可能ですが、下記問題が発生する可能性があります。

その点に対応したくて作ったプラグインなので、下記項で困った場合の代替案として採用できるのではないでしょうか。

置き換え対象文字列に、HTMLタグの開始,終了タグ内の記述が含まれる

.replace()メソッドはあくまで文字列を対象に置き換えを行ってくれるだけなので、HTMLタグの開始,終了タグが含まれていても判別はしてくれません。パターン部分の正規表現次第でおそらく判別も可能ではあると思いますが、正直面倒です。

問題時の記述例

例:文中のURLをリンクタグにしたい
jQuery
  1. var pattern = /https?:\/\/[\w\-_.=?#%]+/g;
  2. var replacement = '<a href="$&">$&</a>';
  3. //通常の要素内文字置き換え
  4. $('#testP1A').html( $('#testP1A').html().replace(pattern,replacement) );
  5. //プラグイン使用時
  6. $('#testP1B').replaceText(pattern,replacement);
記述HTML
  1. <!--通常の要素内文字置き換え対象要素-->
  2. <div id="testP1A">
  3. <h2><a href="http://siteA">サイトA</a>おすすめページリスト</h2>
  4. <ul>
  5. <li>ページ1http://siteA/page1/</li>
  6. <li>ページ2http://siteA/page2/</li>
  7. <li>ページ3http://siteA/page3/</li>
  8. </ul>
  9. </div>
  10. <!--プラグイン使用時対象要素-->
  11. <div id="testP1B">
  12. <h2><a href="http://siteA">サイトA</a>おすすめページリスト</h2>
  13. <ul>
  14. <li>ページ1http://siteA/page1/</li>
  15. <li>ページ2http://siteA/page2/</li>
  16. <li>ページ3http://siteA/page3/</li>
  17. </ul>
  18. </div>
jQuery実行後HTML
  1. <!--通常の要素内文字置き換え対象要素-->
  2. <div id="testP1A">
  3. <h2><a href="<a href="http://siteA">http://siteA</a>">サイトA</a>おすすめページリスト</h2>
  4. <ul>
  5. <li>ページ1<a href="http://siteA/page1/">http://siteA/page1/</a></li>
  6. <li>ページ2<a href="http://siteA/page2/">http://siteA/page2/</a></li>
  7. <li>ページ3<a href="http://siteA/page3/">http://siteA/page3/</a></li>
  8. </ul>
  9. </div>
  10. <!--プラグイン使用時対象要素-->
  11. <div id="testP1B">
  12. <h2><a href="http://siteA">サイトA</a>おすすめページリスト</h2>
  13. <ul>
  14. <li>ページ1<a href="http://siteA/page1/">http://siteA/page1/</a></li>
  15. <li>ページ2<a href="http://siteA/page2/">http://siteA/page2/</a></li>
  16. <li>ページ3<a href="http://siteA/page3/">http://siteA/page3/</a></li>
  17. </ul>
  18. </div>

通常の文字置き換え対象要素内は、HTMLの開始タグ内も置き換え対象になっているのが見て取れる

指定要素内の要素のイベント指定が無効になる

javaScript及びjQueryの性質上、実行時存在する要素にしかイベント指定ができません。

指定要素内を.html()メソッドを用いて置き換えると、元の内包要素は全て破棄され、イベント指定も実質的になくなります。挿入するHTML記述自体が同一でも、元とは異なる新規要素になる為、新たにイベント指定が必要になります。

問題時の記述例

jQuery
  1. //イベント設定
  2. $('.trigger').on('click',function(){ //.triggerがクリックされたら
  3. $(this).css('color','red'); //文字色を赤くする
  4. });
  5. var pattern = /click/g;
  6. var replacement = 'クリック';
  7. //通常の要素内文字置き換え
  8. $('#testP2A').html( $('#testP2A').html().replace(pattern,replacement) );
  9. //プラグイン使用時
  10. $('#testP2B').replaceText(pattern,replacement);
記述HTML
  1. <!--通常の要素内文字置き換え対象要素-->
  2. <div id="testP2A">
  3. <span class="trigger">clickで色が赤くなります。</span>
  4. </div>
  5. <!--プラグイン使用時対象要素-->
  6. <div id="testP2B">
  7. <span class="trigger">clickで色が赤くなります。</span>
  8. </div>
jQuery実行後HTML
  1. <!--通常の要素内文字置き換え対象要素-->
  2. <div id="testP2A">
  3. <span class="trigger">クリックで色が赤くなります。</span>
  4. </div>
  5. <!--プラグイン使用時対象要素-->
  6. <div id="testP2B">
  7. <span class="trigger">クリックで色が赤くなります。</span>
  8. </div>
demo
clickで色が赤くなります。
clickで色が赤くなります。

jQuery実行後HTMLの記述は双方同一だが、通常処理では内包要素ごと置き換えているためクリックイベントが発火しない。

指定要素内の文字置き換えを拒否できる

第三引数指定で、対象要素内で文字置き換え拒否をする要素を指定できるようにしました。

指定した要素内は子孫要素まで文字置き換えの対象外になります。

jQuery
  1. $('#test3').replaceText(/https?:\/\/[\w\-_.=?#%]+/g,'<a href="$&">$&</a>','a');
記述HTML
  1. <div id="test3">
  2. <h2><a href="http://siteA">http://siteA</a></h2>
  3. <ul>
  4. <li>ページ1http://siteA.page1</li>
  5. <li>ページ2http://siteA.page2</li>
  6. <li>ページ3http://siteA.page3</li>
  7. </ul>
  8. </div>
jQuery実行後HTML
  1. <div id="test3">
  2. <h2><a href="http://siteA">http://siteA</a></h2>
  3. <ul>
  4. <li>ページ1<a href="http://siteA.page1">http://siteA.page1</a></li>
  5. <li>ページ2<a href="http://siteA.page2">http://siteA.page2</a></li>
  6. <li>ページ3<a href="http://siteA.page3">http://siteA.page3</a></li>
  7. </ul>
  8. </div>

第三引数に'a'を指定した為、a要素内のテキストは置き換えられていない

二種類用意

今回二種類のメソッドを用意しています。状況に合わせて使い分けてください。

  • .replaceText()

    前述してきた、要素内の文字置き換えをしやすくするメソッドです。

  • .wrapText()

    上記を利用した、要素内の文字を新規HTML要素で囲いやすくしたメソッドです。

    .replaceText()で第二引数にHTML記述をすれば良いだけの話ですが、こちらは戻り値を新規作成したHTML要素群にしています。そのため追加要素にさらに処理を加えたい場合に有効と思います。

source code

プラグイン

jQuery
  1. (function( $ ){
  2. $.fn.replaceText = function(pattern,replacement,nofollow) {
  3. var htmlEsc = str => str.replace(/[&<>'"`]/g,function(s){ return '&#'+s.charCodeAt(0)+';'});
  4. var $not = this.find(nofollow||'script,style').find('*').addBack();
  5. this.find('*').addBack().not($not).contents().each(function(){
  6. if( this.nodeType != 3 ) return true;
  7. var str = htmlEsc( $(this).text() );
  8. if( !str.match(pattern) ) return true;
  9. $(this).replaceWith( str.replace(pattern,replacement) );
  10. });
  11. return this;
  12. };
  13. $.fn.wrapText = function(pattern,tagname,nofollow) {
  14. var pattern = pattern || /&#\d+;|\S/g;
  15. var tagname = tagname || 'span';
  16. var $adv = this.find(tagname);
  17. return this.replaceText(pattern,'<'+tagname+'>$&</'+tagname+'>',nofollow).find(tagname).not($adv);
  18. };
  19. })( jQuery );

呼び出し .replaceText()

基本

target.replaceText(pattern,replacement,nofollow)

構文

element.replaceText(string|regexp,string|function[,string|element])

引数
  • pattern
    指定必須
    • string,regexpどちらかでの指定
    • 文字の置き換え対象の指定

    .replace()メソッドに値渡しをしているだけなので、指定詳細についてはそちらを参照推奨

    探索対象文字列はHTML上意味を持つ記号が文字数値参照に変換されています。その辺を加味して指定してください。HTMLエスケープ用関数と同処理のなので詳細はそちらで。

  • replacement
    指定必須
    • string,functionどちらかでの指定
    • 置き換え後の文字を指定

    .replace()メソッドに値渡しをしているだけなので、指定詳細についてはそちらを参照推奨

  • nofollow
    • string,elementどちらかでの指定
    • 探索対象外要素の指定。ここで指定した要素内は文字の置き換えが実行されません。

    デフォルトでscriptstyle要素内が探索対象外になっています。

戻り値

target自身

呼び出し .wrapText()

基本

target.wrapText(pattern,tagname,nofollow)

構文

element.wrapText([string|regexp[,string[,string|element]]])

引数
  • pattern
    • string,regexpどちらかでの指定
    • HTML要素で覆う文字パターンを指定
    • 未指定時'/&#\d+;|\S/g'(改行,スペースを除く一字)

    .replaceText()メソッドに値渡しをしているだけなので、指定詳細についてはそちらを参照推奨

  • tagname
    • stringでの指定
    • 指定文字を覆うHTML要素名を指定
    • 未指定時'span'
  • nofollow
    • string,elementどちらかでの指定

    .replaceText()メソッドに値渡しをしているだけなので、指定詳細についてはそちらを参照推奨

戻り値

本処理で新規作成したtagname要素

特に属性付与なんかの機能は持たせていないので、メソッドチェーンで対応してください。

使用例

.replaceText()

サイト全体の表記ブレ統一
demo
使用言語について

html,css,javascript,jquery使用

html
HyperText Markup Language(ハイパーテキスト マークアップ ランゲージ)は、ハイパーテキストを記述するためのマークアップ言語の1つ。略してHTML(エイチティーエムエル)と呼ばれることが多い。/wikipedia-Htmlより引用
css
Cascading Style Sheets(CSS、カスケーディング・スタイル・シート、カスケード・スタイル・シート、日: 段階スタイルシート[1])とは、HTML や XML の要素をどのように修飾(表示)するかを指示する、W3Cによる仕様の一つ。文書の構造と体裁を分離させるという理念を実現する為に提唱されたスタイルシートの、具体的な仕様の一つ。/wikipedia-Cssより引用
javascript
JavaScript(ジャバスクリプト)とは、プログラミング言語のひとつである。JavaScriptはプロトタイプベースのオブジェクト指向スクリプト言語であるが、クラスなどのクラスベースに見られる機能も取り込んでいる。/wikipedia-JAVASCRIPTより引用
jquery
jQuery(ジェイクエリー)は、ウェブブラウザ用のJavaScriptコードをより容易に記述できるようにするために設計されたJavaScriptライブラリである。/wikipedia-JQUERYより引用

ソースコード

jQuery
  1. $(function(){
  2. var list = {
  3. 'html':'HTML',
  4. 'css': 'CSS',
  5. 'javascript':'JavaScript',
  6. 'jquery':'jQuery'
  7. }
  8. $('body').replaceText(/(html|css|javascript|jquery)/gi,function(str){
  9. return list[str.toLowerCase()];
  10. });
  11. });
HTML
  1. <h5>使用言語について</h5>
  2. <p>html,css,javascript,jquery使用</p>
  3. <h6>html</h6>
  4. <blockquote><em>HyperText Markup Language</em>(ハイパーテキスト マークアップ ランゲージ)は、ハイパーテキストを記述するためのマークアップ言語の1つ。略して<em>HTML</em>(エイチティーエムエル)と呼ばれることが多い。/wikipedia-Htmlより引用</blockquote>
  5. <h6>css</h6>
  6. <blockquote><em>Cascading Style Sheets</em>(CSS、カスケーディング・スタイル・シート、カスケード・スタイル・シート、日: 段階スタイルシート[1])とは、HTML や XML の要素をどのように修飾(表示)するかを指示する、W3Cによる仕様の一つ。文書の構造と体裁を分離させるという理念を実現する為に提唱されたスタイルシートの、具体的な仕様の一つ。/wikipedia-Cssより引用</blockquote>
  7. <h6>javascript</h6>
  8. <blockquote><em>JavaScript</em>(ジャバスクリプト)とは、プログラミング言語のひとつである。JavaScriptはプロトタイプベースのオブジェクト指向スクリプト言語であるが、クラスなどのクラスベースに見られる機能も取り込んでいる。/wikipedia-JAVASCRIPTより引用</blockquote>
  9. <h6>jquery</h6>
  10. <blockquote><em>jQuery</em>(ジェイクエリー)は、ウェブブラウザ用のJavaScriptコードをより容易に記述できるようにするために設計されたJavaScriptライブラリである。/wikipedia-JQUERYより引用</blockquote>

記述では言語名の大文字小文字の表記がぶれているが実表示では統一されている。

サイト全体をお嬢様言葉に
demo

こんばんは。demo内ですが、解説です。

1行上で早速破綻している通り、超突貫記述なのでかなり適当なところが多いです。

しっかり熟慮して組めばなかなかの精度の物が出来上がりそうではあります。

エイプリールフールなんかにいかがでしょうか?

来年の時期前に余裕があれば、武士口調,関西弁,土佐弁にするものなんかをつくりたいですね。

ソースコード

jQuery
  1. $(function(){
  2. $('body').replaceText(/(です|ます)|(ですよ)|((?:ですか|でしょうか)(?=?))|(ある|あります)|(余裕|暇)|(こんにちは|こんばんは|おはよう)/gm,function(str,m1,m2,m3,m4,m5,m6){
  3. if(m1) return m1+'わ';
  4. if(m2) return 'でしてよ';
  5. if(m3) return 'かしら';
  6. if(m4) return 'ありましてよ';
  7. if(m5) return 'お茶を嗜む時間';
  8. if(m6) return 'ごきげんよう'
  9. })
  10. });
HTML
  1. <p>こんばんは。demo内ですが、解説です。</p>
  2. <p>1行上で早速破綻している通り、超突貫記述なのでかなり適当なところが多いです。</p>
  3. <p>しっかり熟慮して組めばなかなかの精度の物が出来上がりそうではあります。</p>
  4. <p>エイプリールフールなんかにいかがでしょうか?</p>
  5. <p>来年の時期前に余裕があれば、武士口調,関西弁,土佐弁にするものなんかをつくりたいですね。</p>
掲示板のアンカー装飾
demo
  1. 774: ○○って××ですか?
  2. 775: >>774 そうですよ。
  3. 776: >>774です。 >>775さんありがとう!

ソースコード

jQuery
  1. $(function(){
  2. $('#bbs').replaceText(/(?:&#62;){2}\d+/g,'<span style="color:#0000ff">$&</span>');
  3. });
HTML
  1. <ol id="bbs">
  2. <li>774: ○○って××ですか?</li>
  3. <li>775: &gt;&gt;774 そうですよ。</li>
  4. <li>776: &gt;&gt;774です。 &gt;&gt;775さんありがとう!</li>
  5. </ol>
独自タグの自作
demo

ある日の暮方の事である。一人の#ruby_下人_げにん#が、#ruby_羅生門_らしょうもん#の下で雨やみを待っていた。

広い門の下には、この男のほかに誰もいない。ただ、所々#ruby_丹塗_にぬり#の#ruby_剥_は#げた、大きな#ruby_円柱_まるばしら#に、#ruby_蟋蟀_きりぎりす#が一匹とまっている。羅生門が、#ruby_朱雀大路_すざくおおじ#にある以上は、この男のほかにも、雨やみをする#ruby_市女笠_いちめがさ#や#ruby_揉烏帽子_もみえぼし#が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。

「#ruby_羅生門_らしょうもん#」#ruby_芥川_あくたがわ##ruby_龍之介_りゅうのすけ#

ソースコード

jQuery
  1. $(function(){
  2. $('body').replaceText(/#ruby_(.*?)_(.*?)#/gs,'<ruby>$1<rp>(</rp><rt>$2</rt><rp>)</rp></ruby>');
  3. });
HTML
  1. <p>ある日の暮方の事である。一人の#ruby_下人_げにん#が、#ruby_羅生門_らしょうもん#の下で雨やみを待っていた。</p>
  2. <p>広い門の下には、この男のほかに誰もいない。ただ、所々#ruby_丹塗_にぬり#の#ruby_剥_は#げた、大きな#ruby_円柱_まるばしら#に、#ruby_蟋蟀_きりぎりす#が一匹とまっている。羅生門が、#ruby_朱雀大路_すざくおおじ#にある以上は、この男のほかにも、雨やみをする#ruby_市女笠_いちめがさ#や#ruby_揉烏帽子_もみえぼし#が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。</p>
  3. <p class="xr">「#ruby_羅生門_らしょうもん#」#ruby_芥川_あくたがわ##ruby_龍之介_りゅうのすけ#</p>
記号の表示調整
demo

三点リーダ(……)やダッシュ(――)等の、一部記号の表示調整に使えないこともないです。

三点リーダに関してはかなり邪道な方法で縦位置中央に表示されるようにしている為、別の方法を使った方が無難です……

――ダッシュは字間指定で隙間が気になる場合なんかに有効なんじゃないでしょうか。

ソースコード

jQuery
  1. $(function(){
  2. $('body').replaceText(/([…―])\1*/gs,function(str,c){
  3. switch( c ) {
  4. case '…': return '<span class="leader" lang="en">'+str+'</span>';
  5. case '―': return '<span class="dash">'+str+'</span>';
  6. default: return str;
  7. }
  8. });
  9. });
HTML
  1. <p>三点リーダ(……)やダッシュ(――)等の、一部記号の表示調整に使えないこともないです。</p>
  2. <p>三点リーダに関してはかなり邪道な方法で縦位置中央に表示されるようにしている為、別の方法を使った方が無難です……</p>
  3. <p>――ダッシュは字間指定で隙間が気になる場合なんかに有効なんじゃないでしょうか。</p>
CSS
  1. .leader {
  2. position: relative;
  3. top: -0.25em;
  4. font-family: Verdana,Arial,sans-serif;
  5. }
  6. .dash {
  7. margin-right: 4px;
  8. letter-spacing: -1px;
  9. }

三点リーダは英字フォント指定で環境差異なく下付きにした後に文字毎上に移動させるというかなり邪道な方法を使っています。

ダッシュも指定フォントで結構差異があるのですが、とりあえずでletter-spacingで字間を狭め、margin-rightで「本来のletter-spacing」-「今回のletter-spacing」を指定し違和感を減らしています。使用環境に合わせて調節してください。

この辺の話を始めると長くなるので以上。

.wrapText()

文字送り
demo

ある日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。

広い門の下には、この男のほかに誰もいない。ただ、所々丹塗の剥げた、大きな円柱に、蟋蟀が一匹とまっている。羅生門が、朱雀大路にある以上は、この男のほかにも、雨やみをする市女笠や揉烏帽子が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。

「羅生門」芥川龍之介もう一度

ソースコード

jQuery
  1. $(function(){
  2. var time = 100;
  3. var $tgt = $('#demo').wrapText(0,0,'.none');
  4. var $trg = $('#trigger');
  5. $trg.on('click',function(){
  6. $trg.addClass('false');
  7. setTimeout(function(){
  8. $trg.removeClass('false');
  9. },time*$tgt.length);
  10. $tgt.hide().each(function(i){
  11. $(this).delay(time*i).fadeIn(0);
  12. });
  13. });
  14. });
HTML
  1. <div id="demo">
  2. <p>ある日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。</p>
  3. <p>広い門の下には、この男のほかに誰もいない。ただ、所々丹塗の剥げた、大きな円柱に、蟋蟀が一匹とまっている。羅生門が、朱雀大路にある以上は、この男のほかにも、雨やみをする市女笠や揉烏帽子が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。</p>
  4. <p class="none">「羅生門」芥川龍之介<span id="trigger">もう一度</span></p>
  5. </div>

こっちに関しては、前述したとおり、追加要素にさらに処理を加えるのに向いています。

以前サイト内のpartsやjunkに置いていた、グラデーション文字や文字のアーチ配置なんかと相性がいいのですが、そちらの処理も紹介しようとすると長くなるのでまた別の機会に使用例をだそうと思います。