Tuesday, 25 July 2017

【Excel関数】表の横項目を「/」を挟んで結合させようとしたら意外に大変だった、というおはなし

ある表の、同年の項目1から項目5までの文字列を、「/」を挟んで結合させたい案件が発生した。
序でに内容のない項目(つまりは空セル)は省いて結合させたい。
具体的にはこんな感じ。

表1

コレ、以外にややこしい事になってしまった。
マクロは使わず(マクロが出来ない、が正解なのだが)、関数のみでどうにか出来ないか悪戦苦闘したからだが。
ややこしすぎて、どうやったか忘れそうなので、備忘録としてまとめてみた。

条件は、
  • 文字列を「/」を挟んで結合させたい
  • 空セルは省く
  • どの項目が空セルになるかはランダム

以上の条件全てを満たす関数を組みたいのだが、懸念点は以下の通りである。
  • 途中に空セルがある場合「/」が「//」や「///」と重なる 例)2017:「東京/大阪///奈良」
  • 最後が空セルの場合、最後に「/」が来てしまう 例)2016:「東京//京都/神戸/」
  • 先頭が空セルの場合、先頭に「/」来てしまう 例)2015:「/大阪//神戸/奈良」

もう何とも意図したものに出来ないのである。

ということで、地道に1づつ解説していく。

まず最初に、
  • 文字列を「/」を挟んで結合させたい

を実装する関数を考えてみる。

セルB7に結合した文字列を表示するものとする。

素直に文字列を結合すると、
B7=B2&"/"&C2&"/"&D2&"/"&E2&"/"&F2(B7=CONCATENATE(B2,"/",C2,"/",D2,"/",E2,"/",F2)に同じ)
結果:「東京/大阪///奈良」

この場合、上記懸念点で記した通り、空セルがある場合は「/」が余計に現れるのである。
今回作成する関数はひじょ〜に長いので、通常文字列を結合させる時に使用するCONCATENATE関数ではなく、「&」を使った文字列結合を採用する。

次に、空セルの場合は省き、そうでない場合は文字列を表示したい時、これは条件分岐のIF関数で、
B7=IF(B2="","",B2)
結果:「東京」

「B2=""」は「セルB2が空セルである場合」を意味し、その条件を満たす時はセルB7に「""」を入れ(何の文字列も入れないことを意味する)、
そうでない場合(セルB2に何らかの文字列が入っている場合)、B2の文字列を表示する、という意味。

この時、「/」はどのような方法で挟み込めば良いか?
空セルの場合は「/」も不要なので、上記の条件分岐の関数のセルに「/」を付属させれば良い。
では、どこが良いか?
セルの前?
それともセルの後?

セルの前に「/」を付属させると、先頭に「/」が来る可能性が出てくるので、これはNGなのがわかる。
ということで、セルの後に「/」を付属させてみる。
上記の条件分岐の関数を改良すると、
B12=IF(B2="","",B2&"/")
結果:「東京/」

以上から、改めて文字列を結合する。
B17=B12&C12&D12&E12&F12
結果:「東京/大阪/奈良/」

これで空セルは省け、且つ余分な「/」もない結果が得られた、よかったよかった………、

アレ?!
えっと、文字列の最後に「/」がありますねぇ〜。

これが最後!
この余分な「/」の削除方法があるんです。
LEFT関数とLEN関数の合わせ技を使うのである。
LEFT(文字列,[文字数])
定義
文字列の先頭(左端)から指定された数の文字列を取得。今回は文字列最後の「/」の直前までの文字列を取得
文字列
取り出す文字を含む文字列を指定。今回はセルB17を指定
文字数
省略可。取り出す文字数を指定。今回はLEN関数で文字数を指定(以下を見よ)

LEFT関数内の「文字数」に、LEN関数を使用するのがミソ。
LEN(文字列)
定義
文字列の文字数を返す。
文字列
指定した文字列の文字数を取得。今回はセルB17から最後の「/」を引いた文字数を取得
しかるに、取得したい文字数は、
(B17の文字数)-(「/」の文字数)=LEN(B17)-1

以上より、
B22=LEFT(B17,LEN(B17)-1)
結果:「東京/大阪/奈良」

これで、ランダムに現れる空セルを省きつつ、余分な「/」も出ずに文字列を結合させることが出来た。

因みに、上記で作成した関数をまとめて1つにすることも可能。
こんな感じになる。
B22=LEFT(IF(B2="","",B2&"/")&IF(C2="","",C2&"/")&IF(D2="","",D2&"/")&IF(E2="","",E2&"/")↲
&IF(F2="","",F2&"/"),LEN(IF(B2="","",B2&"/")&IF(C2="","",C2&"/")&IF(D2="","",D2&"/")↲
&IF(E2="","",E2&"/")&IF(F2="","",F2&"/"))-1)…①

先に、ひじょ〜に長くなるといったが、実はこのことである。

実際の案件では、不特定の人間が各々入力してもらうもののため、
人によってはセル内改行や、スペースを入れてしまうケースが多い。
それらを一々手作業で削除するのは面倒かつ事故発生の可能性もあるので、
それに対処する関数を上記の関数にかませている。

実際の案件の関数の最終形は以下の通り。
CLEAN(SUBSTITUTE(SUBSTITUTE(B22," ","")," ",""))

(本来はB22の箇所に①の関数が挿入されるが、判りづらくなるので上記の表記に留めた)
CLEAN関数とSUBSTITUTE関数を使って、セル内改行や、スペースを削除している。
(コレに関しては別のブログでサクッと書く予定)

最後に、残念なお知らせ(いや良い知らせか)

上記で長々と説明した事柄は、実は、
Excel 2016から、TEXTJOIN関数でアッサリスッキリ出来ちゃうのです!

TEXTJOIN(区切り記号,ignore_empty,文字列1,[文字列2],...)
区切り記号
今回の例では「/」
ignore_empty
空セルを無視するか否か。空セルを無視=TRUE、空セルを無視しない=FALSE
文字列1,[文字列2],...
結合する文字列。今回はセル「B2」から「F2」
(詳細は、「TEXTJOIN 関数 - Office サポート」)

ということで、TEXTJOIN関数でB22を表現すると、
B22=TEXTJOIN("/",TRUE,B2:F2)

こんな簡単に表現できるのである。

バージョンアップしたい……。

謝辞

この案件の解決方法は、

条件に合うセルの値のみ、「CONCATENATE関数」で結合したいです... - Yahoo!知恵袋

でのベストアンサーに選ばれた回答のkei_jun_kuuさんから多大なる教示を受けました。
ここに感謝の意を表したいと思います。深謝。






Wednesday, 12 July 2017

カリグラフィーを書いてたら、ウチの子がやってきて言った言葉に驚嘆したおはなし


先週の土曜日、半年ぶりにカリグラフィーのレッスンに行き、原点回帰してローマンキャピタルの練習をした。最初は鉛筆で、次にペンで。
よく考えたら9年ぶり!だったので、各文字の幅などかなり怪しかったが、手は覚えていたようで、これも練習のタマモノ(9年前のオレ、よう練習していてくれたことよ)。
と云っても、結構書き辛かったりした…。

ところで、ワタクシが書いた文字の右下辺りに、筆蹟が違う文字がツラツラと羅列しているのがおわかりだろうか(下が拡大したもの)。


それはまさしく突然の出来事だった。

ウチの子が「書いてみたい!」と曰わったのである。

かなりビックリ。
今まで見向きもしなかったのに。
字を書くのに興味が無かったのに、である。

元来、何か作るのが好きな質ではある。
最近は手芸方面にも興味を覚えたらしく、雑貨店に連れてけとウルサイ今日このごろ。

まあ、どういう心境の変化か知る由もないが、コレを機に、

文字っ子の道へ引きずり込もう

と画策する悪い父であった。

そして気づいたら、2、3時間ひたすら字を書いていた
興味のあるモノには途轍もない集中力を発揮するその性分、うん、似てるよなぁ。。。

以下、オススメのカリグラフィーの教本たち。









Thursday, 8 December 2016

久々にハマってる本:ジェイムズ・P・ホーガン著『星を継ぐもの』シリーズ

今、久々にハマってる。
SF小説なのだけれど。
それは、
ジェイムズ・P・ホーガン著『星を継ぐもの』シリーズ。



破滅的で暗い話ではない。
いろいろな謎が、
徐々に解明されていく感じが、
ワクワクさせてくれる。



この続編が、
ガニメデの優しい巨人



あっという間に読んでしまった。



なので、その続編
巨人たちの星



を買ってきて今から読むところ。

Monday, 14 October 2013

jQueryのhoverで文字色をふんわり変える効果をつけると、ページ読込完了後の最初のマウスホバーでふんわり変わらない件と代替方法

今までのウェブ制作で、jQueryのhoverを使って文字色をふんわり変える効果をつけていたところ、どうもページ読込完了後の最初のマウスホバーでふんわり変わらないことに気付いた。これはjQueryのhover内の始めのfunction(マウスホバー時の関数に当たる)でアニメーション時間を遅くした時に出くわしたもので、それ以後ひじょ〜に気になって仕方が無いのでその解消方法を探してみたら、CSS3を使えば良さそうだということがわかったので以下にチョットだけ解説を。

1. jQueryのhoverで文字色をふんわり変える

コードはいつもこんな感じのものを使っている。
$(function(){
 $("a").hover(
  function () {
   $(this).stop().animate({color: "任意の色A"}, 500);
  },
  function() {
   $(this).stop().animate({color: "任意の色B" }, 500);
  }
 );
});
jQueryのhoverは、対応ブラウザが多いのだが、ページ読込完了後の最初のマウスホバーではアニメーションが効かないようだ。この現象は、特に、CSSにもa:hoverを同時に指定している場合に起こる現象のようだ。

対応策としては、CSSのa:hoverでの指定はしないことで、アニメーションが効かない現象は解消されるが、これだとjQueryが読込めない時にa:hoverが出来なくなる、という欠点がある。

2. CSS3のtransitionで文字色をふんわり変える

通常のリンク色とマウスホバー時の色指定はこんな感じ。
a {color: 任意の色A;}
a:hover {color: 任意の色B;}
CSS3のtransitionの対応ブラウザは、IEがver10のみで、他のブラウザもベンダープレフィックスでの対応となっている。
しかし1.と違い、ページ読込み完了時の最初のマウスホバーでも効く。
なぜなら、CSSのa:hoverはそのままで、aに
a {
color: #000;
-webkit-transition: 0.5s;
-moz-transition: 0.5s;
-o-transition: 0.5s;
-ms-transition: 0.5s;
transition: 0.5s;
}
a:hover {color: Tomato;}
と赤字部分を追記すれば良いだけなので。
また、transitionに対応していないブラウザでも、1.と違ってa:hoverが出来なくなるということはない。

今後は、古いIEに対応する必要がない場合はCSS3を使うの方が良いかな。

Monday, 17 June 2013

jQueryでline-height値を取得する時、IEだけ返り値が違う

とあるCSSで
body {
    font-size: 12px;
    line-height: 2;
}
と指定し、jQueryにてline-heightの値を取得する時、
var lineHeight = parseFloat($("body").css("line-height"));
とすると、通常「24」と、font-size*line-heightが内部計算された数値が返される(parseFloatは文字列を数値に変換する関数。parseFloat関数なしだと「24px」と単位付きの文字列が返される)。しかし、IEではCSSでline-heightに指定した値「2」がそのまま返されて他のブラウザと異なる結果となり非常に困る。それ故ブラウザ判別のスクリプトが必要になる(ホンマにメンドイ)。

var userAgent = window.navigator.userAgent.toLowerCase();
var appVersion = window.navigator.appVersion.toLowerCase();
   
if (userAgent.indexOf('msie') != -1) {
    if (appVersion.indexOf('msie 6.') != -1) { //ie6のとき
        var getStyle = $("body")[0].currentStyle || document.defaultView.getComputedStyle($("body")[0], '');
        var lineHeight = getStyle.lineHeight*parseFloat($("body").css("font-size"));
        var bHeight = Math.round(lineHeight)
    } else if (appVersion.indexOf('msie 7.') != -1) {//ie7のとき
        var getStyle = $("body")[0].currentStyle || document.defaultView.getComputedStyle($("body")[0], '');
        var lineHeight = getStyle.lineHeight*parseFloat($("body").css("font-size"));
        var bHeight = Math.round(lineHeight)
    } else if (appVersion.indexOf('msie 8.') != -1) {//ie8のとき
        var getStyle = $("body")[0].currentStyle || document.defaultView.getComputedStyle($("body")[0], '');
        var lineHeight = getStyle.lineHeight*parseFloat($("body").css("font-size"));
        var bHeight = Math.round(lineHeight);
    } else if (appVersion.indexOf('msie 9.') != -1) {//ie9のとき
        var lineHeight = parseFloat($("body").css("line-height"))*parseFloat($("body").css("font-size"));
        var bHeight = Math.round(lineHeight);
    } else if (appVersion.indexOf('msie 10.') != -1) {//ie10のとき
        var lineHeight = parseFloat($("body").css("line-height"))*parseFloat($("body").css("font-size"));
        var bHeight = Math.round(lineHeight);
    }
}else{//ie以外
    var lineHeight = parseFloat($("body").css("line-height"));
    var bHeight = Math.round(lineHeight);
}

これで、IEでも期待する値「24」が返ってくる、はず。

上記スクリプトは、JavaScriptでUserAgentによるブラウザ判定「if.useragent.js」v0.9 | みやなび | 宮古島 ホームページ制作 広告代理店より拝借した。深謝。
ie6〜8のとき変数getStyleがあるのは、jQuery を利用して1行の高さ(line-heigt)を取得する: JavaScriptメモを参考にした。深謝。

最終的なline-heightの値は、Math.round関数にて小数点以下四捨五入で丸めてある。

Wednesday, 12 June 2013

上下に展開・格納する縦型メニューjQueryの簡略化に成功

現在拙サイト・ブログ等で使用中の「上下に展開・格納する縦型メニューjQuery」はかなり煩雑で、今回整理して簡略化させることに成功。

縦型メニューのHTML


<ul>
 <li>
  <span id="accordion01" class="accordion">news</span>
  (ここに「+」または「−」が挿入される)
  <ul id="subNavi01" class="subNavi">
   <li><a href="#">ESZETT</a></li>
   <li><a href="#">TYPŒ</a></li>
   <li><a href="#">LETTER-PRESS</a></li>
  </ul>
 </li>
 <li>
  <span id="accordion02" class="accordion">works</span>
  (ここに「+」または「−」が挿入される)
  <ul id="subNavi02" class="subNavi">
   <li><a href="#">web design</a></li>
   <li><a href="#">web demo</a></li>
   <li><a href="#">print</a></li>
  </ul>
 </li>
 <li>
  <span id="accordion03" class="accordion">projects</span>
  (ここに「+」または「−」が挿入される)
  <ul id="subNavi03" class="subNavi">
   <li><a href="#">event calendar</a></li>
   <li><a href="#">letterpress map</a></li>
   <li><a href="#">line museum</a></li>
  </ul>
 </li>
 <li>
  <span id="accordion04" class="accordion">bibliography</span>
  (ここに「+」または「−」が挿入される)
  <ul id="subNavi04" class="subNavi">
   <li><a href="#">basic</a></li>
   <li><a href="#">typography</a></li>
   <li><a href="#">letterform</a></li>
  </ul>
 </li>
</ul>

これまでのjQuery


$(function(){
 $("#subNavi01, #subNavi02, #subNavi03, #subNavi04").hide();
 $("#accordion01, #accordion02, #accordion03, #accordion04").after("<span class='openClose'>+</span>");
 $("#accordion01").click(function(){
  $("#subNavi01:not(:animated)").animate({height: 'show'}, 500,'easeOutQuad');
  $("#accordion01").next().replaceWith("<span class='openClose'>–</span>");
  $("#subNavi01:not(:animated)").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion01").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi02").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion02").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi03").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion03").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi04").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion04").next().replaceWith("<span class='openClose'>+</span>");});
 });
 $("#accordion02").click(function(){
  $("#subNavi02:not(:animated)").animate({height: 'show'}, 500,'easeOutQuad');
  $("#accordion02").next().replaceWith("<span class='openClose'>–</span>");
  $("#subNavi02:not(:animated)").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion02").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi01").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion01").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi03").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion03").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi04").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion04").next().replaceWith("<span class='openClose'>+</span>");});
 });
 $("#accordion03").click(function(){
  $("#subNavi03:not(:animated)").animate({height: 'show'}, 500,'easeOutQuad');
  $("#accordion03").next().replaceWith("<span class='openClose'>–</span>");
  $("#subNavi03:not(:animated)").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion03").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi01").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion01").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi02").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion02").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi04").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion04").next().replaceWith("<span class='openClose'>+</span>");});
 });
 $("#accordion04").click(function(){
  $("#subNavi04:not(:animated)").animate({height: 'show'}, 500,'easeOutQuad');
  $("#accordion04").next().replaceWith("<span class='openClose'>–</span>");
  $("#subNavi04:not(:animated)").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion04").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi01").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion01").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi02").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion02").next().replaceWith("<span class='openClose'>+</span>");});
  $("#subNavi03").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion03").next().replaceWith("<span class='openClose'>+</span>");});
 });
});
うん、ものの見事に煩雑だね〜。ここではもう詳しく解説しないが、ただ1つだけ云えば、ID属性で各ナビごとに一々指示しているから。詳細は、拙ブログ上下に展開・格納するナビおよび縦型メニュー展開・収納時(開閉時)にメニュー横の+−表示が切替るjQueryをご覧あれ。

整理した結果


1.$(function(){
2. $(".subNavi").hide();
3. $(".accordion").after("<span class='openClose'>+</span>");
4. $(".accordion").click(function(){
5.  $(this).next().next().animate({height: 'show'}, 500,'easeOutQuad');
6.  $(this).next().replaceWith("<span class='openClose'>–</span>");
7.  $(".accordion").next().next().not(":animated").animate({height: 'hide'}, 500,'easeInQuad',↵
   function(){$(this).prev().replaceWith("<span class='openClose'>+</span>");});
8. });
9.});
あらまあスッキリ。
要は、クラス属性での指定に替えて汎用性を高めたことだね。
解説すると、
  • 2行目:subNaviクラスを持つUL要素で囲んだ箇所は最初見えないようにする。これはCSSにて「.subNavi {display:none;}」を指定した方が良い。ページロード時にsubNavi部分が1度表示されてから消えるという動作が解消されるから。
  • 3行目:accordionクラスを持つSPAN要素の後ろにSPAN要素の兄弟要素として「+」を追加する(詳細は縦型メニュー展開・収納時(開閉時)にメニュー横の+−表示が切替るjQueryをご覧あれ)。
  • 4行目:accordionクラスを持つSPAN要素の1つをクリックすると、
    • 5行目:このときの$(this)は実際にクリックしたaccordionクラスを持つSPAN要素を指し、それのnext().next()、つまり$(this)の次の次の兄弟要素であるsubNaviクラスを持つUL要素で囲んだ箇所が表示される。この時注意したいのは、クリックされたaccordionクラスを持つSPAN要素の次の兄弟要素は3行目で追加されるafter()内のSPAN要素であるということ。なのでsubNaviクラスを持つUL要素は次の次の兄弟要素となる。
    • 6行目:クリックされたaccordionクラスを持つSPAN要素の次の兄弟要素である、after()で追加したSPAN要素を「−」に置き換える。
    • 7行目:accordionクラスを持つSPAN要素の次の次の兄弟要素であるsubNaviクラスを持つUL要素で囲んだ箇所を格納する。ここで注意。セレクターが$(this)ではなく$(".accordion")なのは、クリックされたaccordionクラスだけでなく全てのaccordionクラスを対象にしているから。この縦型メニューは、どこか1箇所が展開されたら他の全てのsubNaviは格納するようにしているので。
    • 7行目:後半の関数では$(this).prev()と指示しているがこれは何を指しているか。この時の$(this)は7行目前半の$(".accordion").next().next()、つまりはsubNaviクラスを持つUL要素を指していて、それのprev()、つまりその前の兄弟要素であるafter()で追加したSPAN要素を指す。で、この内「−」に差替えられたものを「+」に変更する。
以上だが、click関数内に1度に展開・格納の指示が入っているので、この動作は展開したかと思えばすぐ格納されて結局subNaviクラス部分は表示されないのではないかと思うが、ここでのミソは、7行目にあるnot(":animated")。これをここに入れることによって、1回のクリックでクリックされたaccordionクラス内のsubNaviクラスはanimateしながら展開され、もう一度自身を含めたいずれかのaccordionクラスをクリックすると、クリックされたaccordionクラス内のsubNaviクラスはanimateしながら展開されると同時に、すでに展開しているsubNaviクラスはanimate状態ではないのでこれが7行目の指示のにより格納される、という動作になる。

Monday, 3 June 2013

縦型メニュー展開・収納時(開閉時)にメニュー横の+−表示が切替るjQuery

今回の拙サイト全面改修の際追加したメニュー横の+−表示が切替るjQueryの詳説をば。
実際どのようなものかは、この拙ブログのサイドメニューも同じ仕様なのでご覧あれ。

メニュー右に「+」を追加して、メニュー展開時にこれが「−」に変わり、メニュー収納時にまた「+」になるようなメニュー展開・収納jQuery。この「+」「−」はいわば飾りなのでHTML上には書きたくない、しかしjQueryの特性上、CSSの疑似要素〔:after〕をセレクターとして呼べないこともあって、「+」「−」の切替え方に難儀。当初、〔toggle(fn1, fn2, ..., fnN)〕を使用しようと考えたがjQuery 1.9からこれが廃止されたことを知り愕然。(詳細はjQuery Core 1.9 Upgrade Guide | jQueryを参照)
他に手はないかと色々調べた結果、jQueryの〔after()〕と〔replaceWith()〕が使えそうと判断。〔after()〕は指定したセレクターの後ろにHTML文字列などを挿入するもの、〔replaceWith()〕は指定したセレクターのHTML文字列などを置換するもの。この2つを組み合わせて「+」「−」の切替えを可能にした。
以下に使用例を。
HTML
<ul>
 <li><span id="accordion02">works</span>
  <ul id="subNavi02">
   <li><a href="#">web design</a></li>
   <li><a href="#">web demo</a></li>
   <li><a href="#">print</a></li>
   <li><a href="#">letter carving</a></li>
  </ul>
 </li>
</ul>

jQuery
$(function(){
1:  $("#subNavi02").hide();
2:  $("#accordion02").after("+");
3:  $("#accordion02").click(function(){
4:  $("#subNavi02:not(:animated)").animate({height: 'show'}, 500,'easeOutQuad');
5:  $("#accordion02").next().replaceWith("–");
6:  $("#subNavi02:not(:animated)").animate({height: 'hide'}, 500,'easeInQuad', function(){$("#accordion02").next().replaceWith("+");});
 });
});
解説
  • 1: はじめはサブナビ部分を隠しておくための〔hide()〕
  • 2:「works」の右に「+」を追加するための〔after("+")〕
  • 3,4,5:「works」をクリックすると(3)、サブナビ部分が展開(4)、同時に「+」が「−」に置換される(5)
  • 6: もう一度「works」をクリックするとサブナビ部分は収納され、収納完了後に「−」が「+」に置換される

実はもう一つのミソが上記6の『収納完了後に「−」が「+」に置換』。4,5での書き方の場合はクリックと同時に置換されるが、4,6で使用している〔animate(params, [duration], [easing], [callback])〕(コレ自体の解説は以前のエントリ「上下に展開・格納するナビ」をご覧あれ)の〔[callback]〕部分に置換の関数〔function(){$("#accordion02").next().replaceWith("+");}〕を書き込むことで、収納完了後に置換がなされるようになる(らしい)。

以上だが、ここで1つ疑問が。
今回は1つの〔click()〕内に2つの〔animate()〕を挿入しているが、これで何故メニューの展開・収納が上手くいくのか、理屈上よく理解できていない。。。