http://gihyo.jp/book/2013/978-4-7741-5489-3/support
どーも身についていませんが、gihyo.jpの↑このサンプルは分かりやすい。
ステートパターンなので、例えば、actionクラスでの処理の振分けに適用できます
<html> <head> <style> #list li { cursor: pointer; font-size: 20px; } #drag-item { display: none; background:yellow; alpha: 0.5; z-index: 99; position: absolute; font-size: 20px; } .drag-over { border-bottom: 2px dashed #777; background: #FED; } .text-editing { z-index: 99; position: absolute; font-size: 20px; } </style> <script src="jquery-1.3.2.js"></script> <script> $(function() { var state = null; var selected = null; // イベント処理を状態オブジェクトに委譲 $("#list li").mousedown(function(event) { state.onMouseDown(event); }); $("#list").mousemove(function(event) { state.onMouseMove(event); }); $("#list").mouseup(function(event) { state.onMouseUp(event); }); $("#list").dblclick(function(event) { state.onDblClick(event); }); $(document).keydown(function(event) { state.onKeyDown(event); }); // 状態遷移関数の定義 function transitState(newState) { $("#debug").text(state + " -> " + newState); state = newState; } // AbstractStateクラスの定義 var AbstractState = function() {}; AbstractState.prototype = { initialize: function() {}, onMouseDown: function(event) {}, onMouseMove: function(event) {}, onMouseUp: function(event) {}, onDblClick: function(event) {}, onKeyDown: function(event) {}, toString: function() { return "AbstractState"; } }; // Normalクラスの定義 var NormalState = function() { selected = null; // 選択解除 }; $.extend(NormalState.prototype, AbstractState.prototype, { onMouseDown: function(event) { var target = event.target; if (target.tagName == "LI") { // 移動中状態に遷移 transitState(new DragMovingState(target)); } }, onDblClick: function(event) { var target = event.target; if (target.tagName == "LI") { // テキスト編集中状態に遷移 transitState(new TextEditingState(target)); } }, toString: function() { return "NormalState"; } }); // DragMovingStateの定義 DragMovingState = function(target) { selected = target; $("#drag-item").text($(selected).text()).show(); }; $.extend(DragMovingState.prototype, AbstractState.prototype, { onMouseMove: function(event) { var target = event.target; if (target.tagName == "LI") { // プレビュー用のspanを移動 $("#drag-item").css({left: event.pageX + 2, top: event.pageY + 2}); // マウス直下項目のスタイルを変更 $("#list li").removeClass("drag-over"); $(target).addClass("drag-over"); } }, onMouseUp: function(event) { var target = event.target; $("#list li").removeClass("drag-over"); // 項目を移動 if (target !== selected) { $(target).after(selected); } // プレビュー用のspanを非表示 $("#drag-item").hide(); // 通常状態に戻る transitState(new NormalState()); }, toString: function() { return "DragMovingState"; } }); // TextEditingStateの定義 TextEditingState = function(target) { selected = target; var pos = $(selected).position(); // テキストフィールドを作成して表示 this.input = $("<input type='text' class='text-editing'>") .css({left: pos.left, top: pos.top}) .val($(selected).text()) .appendTo("body") .focus(); // 選択された項目の内容を消す $(selected).html(" "); }; $.extend(TextEditingState.prototype, AbstractState.prototype, { onKeyDown: function(event) { if (event.which == 13) { // enterキーだったら // 選択された項目の内容を更新 var text = this.input.value; $(selected).text(this.input.val()); // テキストフィールドを除去 this.input.remove(); // 通常状態に遷移 transitState(new NormalState()); } }, toString: function() { return "TextEditingState"; } }); // 初期状態はNormalStateから開始 transitState(new NormalState()); }); </script> </head> <body onselectstart="return false;" onmousedown="if (typeof event.preventDefault != 'undefined') { event.preventDefault(); }"> <ul id="list"> <li>Item-1</li> <li>Item-2</li> <li>Item-3</li> <li>Item-4</li> <li>Item-5</li> </ul> <span id="drag-item">test</span> Debug : <span id="debug"></span> </body> </html>