snap
イベントをバインドする方法を探しています。
サーフェス上で要素をドラッグしていて、ドラッグ可能な要素が宣言されたスナップ位置にスナップされたときに、イベントをトリガーしたいと考えています。
このようなもの:
$(".drag").draggable({
snap: ".grid",
snaped: function( event, ui ) {}
});
ボーナス ポイント:ドラッグ可能な要素がスナップ.grid
された要素への参照。
snap
イベントをバインドする方法を探しています。
サーフェス上で要素をドラッグしていて、ドラッグ可能な要素が宣言されたスナップ位置にスナップされたときに、イベントをトリガーしたいと考えています。
このようなもの:
$(".drag").draggable({
snap: ".grid",
snaped: function( event, ui ) {}
});
ボーナス ポイント:ドラッグ可能な要素がスナップ.grid
された要素への参照。
ウィジェットは、そのままでは (まだ)そのdraggable
ようなイベントを公開しません。それを変更してカスタム バージョンを維持するか、より良い方法として、そこから新しいウィジェットを派生させ、そこに新しいイベントを実装することができます。ただし、3 つ目の方法があります。
この質問から、ウィジェットが潜在的に「スナップ可能な」要素の配列をそのsnapElements
プロパティに格納していることがわかります。次に、この配列の各要素は、ドラッグ可能なヘルパーが現在この要素にスナップされている場合と、そうでない場合 (ヘルパーは同時に複数の要素にスナップできる)のsnapping
プロパティを公開します。true
false
snapElements
配列はイベントごとに更新されるため、ハンドラーdrag
では常に最新です。drag
そこdraggable
から、関連付けられた要素からdata()_trigger()
を使用してウィジェット インスタンスを取得し、そのメソッドを呼び出して独自のsnapped
イベントを発生させるだけです (実際dragsnapped
には内部で)。渡す際に、スナップされた要素をラップする jQuery オブジェクトを使用してオブジェクトを$.extend()することができます。ui
$(".drag").draggable({
drag: function(event, ui) {
var draggable = $(this).data("draggable");
$.each(draggable.snapElements, function(index, element) {
if (element.snapping) {
draggable._trigger("snapped", event, $.extend({}, ui, {
snapElement: $(element.item)
}));
}
});
},
snap: ".grid",
snapped: function(event, ui) {
// Do something with 'ui.snapElement'...
}
});
ただし、上記のコードはまだ改善の余地があります。現状では、ドラッグ可能なヘルパーが要素にスナップされている限り、すべてのイベント (頻繁に発生するsnapped
)に対してイベントがトリガーされます。さらに、スナップの終了時にイベントがトリガーされないため、これはあまり実用的ではなく、このようなイベントがペアで発生するという規則 ( 、) を損ないます。drag
snapped-in
snapped-out
幸いなことに、snapElements
配列は永続的であるため、状態を保存するために使用できます。snappingKnown
各配列要素にプロパティを追加してsnapped
、その要素のイベントを既にトリガーしたことを追跡できます。さらに、最後の呼び出し以降に要素がスナップアウトされたことを検出し、それに応じて対応するために使用できます。
snapped-out
以下のコードでは、別のイベントを導入するのではなく、追加snapping
のプロパティ (要素の現在の状態を反映する) をui
オブジェクトに渡すことを選択していることに注意してください (もちろん、これは好みの問題です)。
$(".drag").draggable({
drag: function(event, ui) {
var draggable = $(this).data("draggable");
$.each(draggable.snapElements, function(index, element) {
ui = $.extend({}, ui, {
snapElement: $(element.item),
snapping: element.snapping
});
if (element.snapping) {
if (!element.snappingKnown) {
element.snappingKnown = true;
draggable._trigger("snapped", event, ui);
}
} else if (element.snappingKnown) {
element.snappingKnown = false;
draggable._trigger("snapped", event, ui);
}
});
},
snap: ".grid",
snapped: function(event, ui) {
// Do something with 'ui.snapElement' and 'ui.snapping'...
var snapper = ui.snapElement.attr("id"),snapperPos = ui.snapElement.position(),
snappee = ui.helper.attr("id"), snappeePos = ui.helper.position(),
snapping = ui.snapping;
// ...
}
});
このソリューションは、こちらでテストできます。
最後に、もう 1 つの改善点として、イベントがそうであるように、snapped
イベントをキャンセル可能drag
にすることが考えられます。これを実現するには、への呼び出しの 1 つが returnの場合false
、drag
ハンドラーから_trigger()
戻る必要がありますfalse
。ただし、スナップインまたはスナップアウトでのドラッグ操作のキャンセルは、一般的に非常にユーザーフレンドリーな機能とは思えないため、これを実装する前によく考えてください。
更新: jQuery UI 1.9 以降、キーdata()
はウィジェットの完全修飾名になり、ドットがダッシュに置き換えられます。したがって、ウィジェット インスタンスを取得するために上記で使用したコードは次のようになります。
var draggable = $(this).data("ui-draggable");
それ以外の:
var draggable = $(this).data("draggable");
非修飾名の使用は 1.9 で引き続きサポートされていますが、推奨されておらず、1.10 でサポートが削除されます。
jquery-ui 1.10.0では、上記のコードは機能しません。代わりに、ドラッグ機能は次のとおりです。
drag: function(event, ui) {
var draggable = $(this).data("ui-draggable")
$.each(draggable.snapElements, function(index, element) {
if(element.snapping) {
draggable._trigger("snapped", event, $.extend({}, ui, {
snapElement: $(element.item)
}));
}
});
}