javascrpitの正規表現による文字列置換「String.replace」について

まず、簡単な例を見ていましょう:

例題1:

「#A」「#B」「#C」のみ、頭の「#」を消します。
(例えば、”#AA#BB#CC#D” → “AABBCC#D”)

それは簡単です。

str = "#AA#BB#CC#D";
str = str.replace(/#([ABC])/g, "$1");

でOKです。

ただ、マッチした結果に対してさらに複雑な処理を行いたい場合にはどうしますか。

例題2

「#A」「#B」「#C」のみ、頭の「#」を消して、小文字に変換します。
(例えば、”#AA#BB#CC#D” → “aAbBcC#D”)

たぶん下記の方法を考えた方がいらっしゃるだろうと思いますが、実はNGです。

// × NG
str = "#AA#BB#CC#D";
str = str.replace(/#([ABC])/g, "$1".toLowerCase());

“$1″という文字列オブジェクトにtoLowerCase()を使ってしまったのです。

↓↓↓↓↓

では、下記のやり方はどうですか。

// △ FirefoxやGoogle ChromeだとOK
str = "#AA#BB#CC#D";
str = str.replace(/#([ABC])/g,
  function() {
    return RegExp.$1.toLowerCase();
  }
);

replaceの中で無名関数を使うという方法です。
テストした結果、うまく行けたブラウザーもあれば(Firefox、Google Chromeなど)、行けなかったブラウザーもあります(IEなど)。

↓↓↓↓↓

Electronic Genome
↑というブログを参考したら、下記のやり方だとIEでも動きました:

// 〇 OK
str = "#AA#BB#CC#D";
str = str.replace(/#([ABC])/g,
  function(whole, p1) {
    return p1.toLowerCase();
  }
);

つまり、replaceの中の無名関数に、引数を渡しました。

→ やっと、問題を解決しました!

※wholeやp1など、引数の具体的な意味について、
Electronic Genome – JavascriptのString.replaceに無名関数を渡して複雑な置換
↑を参照してください。

scriptaculous.jsでSortableを実装する時、onStartとonEndが拾えますか。

scriptaculous.js(v1.8.1)を使ってソート可能なリストを実装しています。

Sortable.createでonChangeとonUpdateが拾えますが、
ドラッグの開始時と終了時に、onStartとonEndみたいなイベントも拾いたいんですが、うまくいきませんでした。

→ とりあえずdragdrop.jsに手を入れることにしました。

576: var SortableObserver = Class.create({
577:   initialize: function(element, observer) {
578:     this.element   = $(element);
579:     this.observer  = observer;
580:     this.lastValue = Sortable.serialize(this.element);
581:   },
582:
583:   onStart: function() {
584:     this.lastValue = Sortable.serialize(this.element);
// -> ここにドラッグ開始時の処理を書きます
585:   },
586:
587:   onEnd: function() {
588:     Sortable.unmark();
589:     if(this.lastValue != Sortable.serialize(this.element))
590:       this.observer(this.element)
// -> ここにドラッグ終了時の処理を書きます
591:   }
592: });

という感じで、一応機能としては動いていますが、あまりソースには手を入れたくないですね。。。

Draggableオブジェクト作成時にはstarteffectとendeffectが使えますが、Sortableには似たようなものがありますかね。。。