要素内の文字置き換えプラグイン
ある日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。
広い門の下には、この男のほかに誰もいない。ただ、所々丹塗の剥げた、大きな円柱に、蟋蟀が一匹とまっている。羅生門が、朱雀大路にある以上は、この男のほかにも、雨やみをする市女笠や揉烏帽子が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。
「羅生門」芥川龍之介
- HTMLエスケープ用関数の記述をちょっと変えました。処理内容に変化はありません。
- デフォルトで
script
style
要素を探索対象外に指定しました。 - 記事再編(仕様も大幅に変更しました)
- 記事投稿
要素内の子孫要素まで探索して、文字のみ置き換えるプラグインです。
別件で入用だったので作成。個人的には結構便利。
何ができるの?
基本
jQuery要素内文字置き換え
- var pattern = /abc/g;
- var replacement = 'ABC';
- //通常の要素内文字置き換え
- $('#testA').text( $('#testA').text().replace(pattern,replacement) );
- //プラグイン使用時
- $('#testB').replaceText(pattern,replacement);
通常、jQeuryでHTML要素内の文字置き換えをしようとすると、のような形になります。
それをで済ませられるよってプラグインです。
記述HTML
- <!--通常の要素内文字置き換え対象要素-->
- <div id="testA">abcdefg</div>
- <!--プラグイン使用時対象要素-->
- <div id="testB">abcdefg</div>
jQuery実行後HTML
- <!--通常の要素内文字置き換え対象要素-->
- <div id="testA">ABCdefg</div>
- <!--プラグイン使用時対象要素-->
- <div id="testB">ABCdefg</div>
指定要素内にHTML要素を内包している場合に有効
指定要素内にHTML要素を内包している場合、前述の「通常の要素内文字置き換えjQuery」でも、.text()
メソッドを.html()
メソッドに変更することで対応可能ですが、下記問題が発生する可能性があります。
その点に対応したくて作ったプラグインなので、下記項で困った場合の代替案として採用できるのではないでしょうか。
置き換え対象文字列に、HTMLタグの開始,終了タグ内の記述が含まれる
.replace()
メソッドはあくまで文字列を対象に置き換えを行ってくれるだけなので、HTMLタグの開始,終了タグが含まれていても判別はしてくれません。パターン部分の正規表現次第でおそらく判別も可能ではあると思いますが、正直面倒です。
例:文中のURLをリンクタグにしたい
jQuery
- var pattern = /https?:\/\/[\w\-_.=?#%]+/g;
- var replacement = '<a href="$&">$&</a>';
- //通常の要素内文字置き換え
- $('#testP1A').html( $('#testP1A').html().replace(pattern,replacement) );
- //プラグイン使用時
- $('#testP1B').replaceText(pattern,replacement);
記述HTML
- <!--通常の要素内文字置き換え対象要素-->
- <div id="testP1A">
- <h2><a href="http://siteA">サイトA</a>おすすめページリスト</h2>
- <ul>
- <li>ページ1http://siteA/page1/</li>
- <li>ページ2http://siteA/page2/</li>
- <li>ページ3http://siteA/page3/</li>
- </ul>
- </div>
- <!--プラグイン使用時対象要素-->
- <div id="testP1B">
- <h2><a href="http://siteA">サイトA</a>おすすめページリスト</h2>
- <ul>
- <li>ページ1http://siteA/page1/</li>
- <li>ページ2http://siteA/page2/</li>
- <li>ページ3http://siteA/page3/</li>
- </ul>
- </div>
jQuery実行後HTML
- <!--通常の要素内文字置き換え対象要素-->
- <div id="testP1A">
- <h2><a href="<a href="http://siteA">http://siteA</a>">サイトA</a>おすすめページリスト</h2>
- <ul>
- <li>ページ1<a href="http://siteA/page1/">http://siteA/page1/</a></li>
- <li>ページ2<a href="http://siteA/page2/">http://siteA/page2/</a></li>
- <li>ページ3<a href="http://siteA/page3/">http://siteA/page3/</a></li>
- </ul>
- </div>
- <!--プラグイン使用時対象要素-->
- <div id="testP1B">
- <h2><a href="http://siteA">サイトA</a>おすすめページリスト</h2>
- <ul>
- <li>ページ1<a href="http://siteA/page1/">http://siteA/page1/</a></li>
- <li>ページ2<a href="http://siteA/page2/">http://siteA/page2/</a></li>
- <li>ページ3<a href="http://siteA/page3/">http://siteA/page3/</a></li>
- </ul>
- </div>
通常の文字置き換え対象要素内は、HTMLの開始タグ内も置き換え対象になっているのが見て取れる
指定要素内の要素のイベント指定が無効になる
javaScript及びjQueryの性質上、実行時存在する要素にしかイベント指定ができません。
指定要素内を.html()
メソッドを用いて置き換えると、元の内包要素は全て破棄され、イベント指定も実質的になくなります。挿入するHTML記述自体が同一でも、元とは異なる新規要素になる為、新たにイベント指定が必要になります。
jQuery
- //イベント設定
- $('.trigger').on('click',function(){ //.triggerがクリックされたら
- $(this).css('color','red'); //文字色を赤くする
- });
- var pattern = /click/g;
- var replacement = 'クリック';
- //通常の要素内文字置き換え
- $('#testP2A').html( $('#testP2A').html().replace(pattern,replacement) );
- //プラグイン使用時
- $('#testP2B').replaceText(pattern,replacement);
記述HTML
- <!--通常の要素内文字置き換え対象要素-->
- <div id="testP2A">
- <span class="trigger">clickで色が赤くなります。</span>
- </div>
- <!--プラグイン使用時対象要素-->
- <div id="testP2B">
- <span class="trigger">clickで色が赤くなります。</span>
- </div>
jQuery実行後HTML
- <!--通常の要素内文字置き換え対象要素-->
- <div id="testP2A">
- <span class="trigger">クリックで色が赤くなります。</span>
- </div>
- <!--プラグイン使用時対象要素-->
- <div id="testP2B">
- <span class="trigger">クリックで色が赤くなります。</span>
- </div>
demo
jQuery実行後HTMLの記述は双方同一だが、通常処理では内包要素ごと置き換えているためクリックイベントが発火しない。
他
指定要素内の文字置き換えを拒否できる
第三引数指定で、対象要素内で文字置き換え拒否をする要素を指定できるようにしました。
指定した要素内は子孫要素まで文字置き換えの対象外になります。
jQuery
- $('#test3').replaceText(/https?:\/\/[\w\-_.=?#%]+/g,'<a href="$&">$&</a>','a');
記述HTML
- <div id="test3">
- <h2><a href="http://siteA">http://siteA</a></h2>
- <ul>
- <li>ページ1http://siteA.page1</li>
- <li>ページ2http://siteA.page2</li>
- <li>ページ3http://siteA.page3</li>
- </ul>
- </div>
jQuery実行後HTML
- <div id="test3">
- <h2><a href="http://siteA">http://siteA</a></h2>
- <ul>
- <li>ページ1<a href="http://siteA.page1">http://siteA.page1</a></li>
- <li>ページ2<a href="http://siteA.page2">http://siteA.page2</a></li>
- <li>ページ3<a href="http://siteA.page3">http://siteA.page3</a></li>
- </ul>
- </div>
第三引数に'a'
を指定した為、a
要素内のテキストは置き換えられていない
二種類用意
今回二種類のメソッドを用意しています。状況に合わせて使い分けてください。
-
.replaceText()
前述してきた、要素内の文字置き換えをしやすくするメソッドです。
-
.wrapText()
上記を利用した、要素内の文字を新規HTML要素で囲いやすくしたメソッドです。
.replaceText()
で第二引数にHTML記述をすれば良いだけの話ですが、こちらは戻り値を新規作成したHTML要素群にしています。そのため追加要素にさらに処理を加えたい場合に有効と思います。
source code
プラグイン
jQuery
- (function( $ ){
- $.fn.replaceText = function(pattern,replacement,nofollow) {
- var htmlEsc = str => str.replace(/[&<>'"`]/g,function(s){ return '&#'+s.charCodeAt(0)+';'});
- var $not = this.find(nofollow||'script,style').find('*').addBack();
- this.find('*').addBack().not($not).contents().each(function(){
- if( this.nodeType != 3 ) return true;
- var str = htmlEsc( $(this).text() );
- if( !str.match(pattern) ) return true;
- $(this).replaceWith( str.replace(pattern,replacement) );
- });
- return this;
- };
- $.fn.wrapText = function(pattern,tagname,nofollow) {
- var pattern = pattern || /&#\d+;|\S/g;
- var tagname = tagname || 'span';
- var $adv = this.find(tagname);
- return this.replaceText(pattern,'<'+tagname+'>$&</'+tagname+'>',nofollow).find(tagname).not($adv);
- };
- })( 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どちらかでの指定
- 探索対象外要素の指定。ここで指定した要素内は文字の置き換えが実行されません。
デフォルトで
script
style
要素内が探索対象外になっています。
戻り値
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
- $(function(){
- var list = {
- 'html':'HTML',
- 'css': 'CSS',
- 'javascript':'JavaScript',
- 'jquery':'jQuery'
- }
- $('body').replaceText(/(html|css|javascript|jquery)/gi,function(str){
- return list[str.toLowerCase()];
- });
- });
HTML
- <h5>使用言語について</h5>
- <p>html,css,javascript,jquery使用</p>
- <h6>html</h6>
- <blockquote><em>HyperText Markup Language</em>(ハイパーテキスト マークアップ ランゲージ)は、ハイパーテキストを記述するためのマークアップ言語の1つ。略して<em>HTML</em>(エイチティーエムエル)と呼ばれることが多い。/wikipedia-Htmlより引用</blockquote>
- <h6>css</h6>
- <blockquote><em>Cascading Style Sheets</em>(CSS、カスケーディング・スタイル・シート、カスケード・スタイル・シート、日: 段階スタイルシート[1])とは、HTML や XML の要素をどのように修飾(表示)するかを指示する、W3Cによる仕様の一つ。文書の構造と体裁を分離させるという理念を実現する為に提唱されたスタイルシートの、具体的な仕様の一つ。/wikipedia-Cssより引用</blockquote>
- <h6>javascript</h6>
- <blockquote><em>JavaScript</em>(ジャバスクリプト)とは、プログラミング言語のひとつである。JavaScriptはプロトタイプベースのオブジェクト指向スクリプト言語であるが、クラスなどのクラスベースに見られる機能も取り込んでいる。/wikipedia-JAVASCRIPTより引用</blockquote>
- <h6>jquery</h6>
- <blockquote><em>jQuery</em>(ジェイクエリー)は、ウェブブラウザ用のJavaScriptコードをより容易に記述できるようにするために設計されたJavaScriptライブラリである。/wikipedia-JQUERYより引用</blockquote>
記述では言語名の大文字小文字の表記がぶれているが実表示では統一されている。
サイト全体をお嬢様言葉に
demo
こんばんは。demo内ですが、解説です。
1行上で早速破綻している通り、超突貫記述なのでかなり適当なところが多いです。
しっかり熟慮して組めばなかなかの精度の物が出来上がりそうではあります。
エイプリールフールなんかにいかがでしょうか?
来年の時期前に余裕があれば、武士口調,関西弁,土佐弁にするものなんかをつくりたいですね。
jQuery
- $(function(){
- $('body').replaceText(/(です|ます)|(ですよ)|((?:ですか|でしょうか)(?=?))|(ある|あります)|(余裕|暇)|(こんにちは|こんばんは|おはよう)/gm,function(str,m1,m2,m3,m4,m5,m6){
- if(m1) return m1+'わ';
- if(m2) return 'でしてよ';
- if(m3) return 'かしら';
- if(m4) return 'ありましてよ';
- if(m5) return 'お茶を嗜む時間';
- if(m6) return 'ごきげんよう'
- })
- });
HTML
- <p>こんばんは。demo内ですが、解説です。</p>
- <p>1行上で早速破綻している通り、超突貫記述なのでかなり適当なところが多いです。</p>
- <p>しっかり熟慮して組めばなかなかの精度の物が出来上がりそうではあります。</p>
- <p>エイプリールフールなんかにいかがでしょうか?</p>
- <p>来年の時期前に余裕があれば、武士口調,関西弁,土佐弁にするものなんかをつくりたいですね。</p>
掲示板のアンカー装飾
demo
- 774: ○○って××ですか?
- 775: >>774 そうですよ。
- 776: >>774です。 >>775さんありがとう!
jQuery
- $(function(){
- $('#bbs').replaceText(/(?:&#62;){2}\d+/g,'<span style="color:#0000ff">$&</span>');
- });
HTML
- <ol id="bbs">
- <li>774: ○○って××ですか?</li>
- <li>775: >>774 そうですよ。</li>
- <li>776: >>774です。 >>775さんありがとう!</li>
- </ol>
独自タグの自作
demo
ある日の暮方の事である。一人の#ruby_下人_げにん#が、#ruby_羅生門_らしょうもん#の下で雨やみを待っていた。
広い門の下には、この男のほかに誰もいない。ただ、所々#ruby_丹塗_にぬり#の#ruby_剥_は#げた、大きな#ruby_円柱_まるばしら#に、#ruby_蟋蟀_きりぎりす#が一匹とまっている。羅生門が、#ruby_朱雀大路_すざくおおじ#にある以上は、この男のほかにも、雨やみをする#ruby_市女笠_いちめがさ#や#ruby_揉烏帽子_もみえぼし#が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。
「#ruby_羅生門_らしょうもん#」#ruby_芥川_あくたがわ##ruby_龍之介_りゅうのすけ#
jQuery
- $(function(){
- $('body').replaceText(/#ruby_(.*?)_(.*?)#/gs,'<ruby>$1<rp>(</rp><rt>$2</rt><rp>)</rp></ruby>');
- });
HTML
- <p>ある日の暮方の事である。一人の#ruby_下人_げにん#が、#ruby_羅生門_らしょうもん#の下で雨やみを待っていた。</p>
- <p>広い門の下には、この男のほかに誰もいない。ただ、所々#ruby_丹塗_にぬり#の#ruby_剥_は#げた、大きな#ruby_円柱_まるばしら#に、#ruby_蟋蟀_きりぎりす#が一匹とまっている。羅生門が、#ruby_朱雀大路_すざくおおじ#にある以上は、この男のほかにも、雨やみをする#ruby_市女笠_いちめがさ#や#ruby_揉烏帽子_もみえぼし#が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。</p>
- <p class="xr">「#ruby_羅生門_らしょうもん#」#ruby_芥川_あくたがわ##ruby_龍之介_りゅうのすけ#</p>
記号の表示調整
demo
三点リーダ(……)やダッシュ(――)等の、一部記号の表示調整に使えないこともないです。
三点リーダに関してはかなり邪道な方法で縦位置中央に表示されるようにしている為、別の方法を使った方が無難です……
――ダッシュは字間指定で隙間が気になる場合なんかに有効なんじゃないでしょうか。
jQuery
- $(function(){
- $('body').replaceText(/([…―])\1*/gs,function(str,c){
- switch( c ) {
- case '…': return '<span class="leader" lang="en">'+str+'</span>';
- case '―': return '<span class="dash">'+str+'</span>';
- default: return str;
- }
- });
- });
HTML
- <p>三点リーダ(……)やダッシュ(――)等の、一部記号の表示調整に使えないこともないです。</p>
- <p>三点リーダに関してはかなり邪道な方法で縦位置中央に表示されるようにしている為、別の方法を使った方が無難です……</p>
- <p>――ダッシュは字間指定で隙間が気になる場合なんかに有効なんじゃないでしょうか。</p>
CSS
- .leader {
- position: relative;
- top: -0.25em;
- font-family: Verdana,Arial,sans-serif;
- }
- .dash {
- margin-right: 4px;
- letter-spacing: -1px;
- }
三点リーダは英字フォント指定で環境差異なく下付きにした後に文字毎上に移動させるというかなり邪道な方法を使っています。
ダッシュも指定フォントで結構差異があるのですが、とりあえずでletter-spacing
で字間を狭め、margin-right
で「本来のletter-spacing
」-「今回のletter-spacing
」を指定し違和感を減らしています。使用環境に合わせて調節してください。
この辺の話を始めると長くなるので以上。
.wrapText()
文字送り
demo
ある日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。
広い門の下には、この男のほかに誰もいない。ただ、所々丹塗の剥げた、大きな円柱に、蟋蟀が一匹とまっている。羅生門が、朱雀大路にある以上は、この男のほかにも、雨やみをする市女笠や揉烏帽子が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。
「羅生門」芥川龍之介もう一度
jQuery
- $(function(){
- var time = 100;
- var $tgt = $('#demo').wrapText(0,0,'.none');
- var $trg = $('#trigger');
- $trg.on('click',function(){
- $trg.addClass('false');
- setTimeout(function(){
- $trg.removeClass('false');
- },time*$tgt.length);
- $tgt.hide().each(function(i){
- $(this).delay(time*i).fadeIn(0);
- });
- });
- });
HTML
- <div id="demo">
- <p>ある日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。</p>
- <p>広い門の下には、この男のほかに誰もいない。ただ、所々丹塗の剥げた、大きな円柱に、蟋蟀が一匹とまっている。羅生門が、朱雀大路にある以上は、この男のほかにも、雨やみをする市女笠や揉烏帽子が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。</p>
- <p class="none">「羅生門」芥川龍之介<span id="trigger">もう一度</span></p>
- </div>
こっちに関しては、前述したとおり、追加要素にさらに処理を加えるのに向いています。
以前サイト内のpartsやjunkに置いていた、グラデーション文字や文字のアーチ配置なんかと相性がいいのですが、そちらの処理も紹介しようとすると長くなるのでまた別の機会に使用例をだそうと思います。