はじめに
プリザンターをつかっていて「このサイト、階層が変わってる!だれが動かしたの?」ってなること、ありませんか?
サイトの管理権限をユーザーに持たせていると、サイトの階層移動や順番の入れ替えができるのですが、ドラッグ&ドロップだけで出来てしまうので、ちょっとした誤動作で意図せず移動させてしまう事故が発生してしまいます。
今回は、これを防ぐためのスクリプトを紹介します。
移動を防ぐ方法
移動はjQuery UIのSortableで実現されています。そのため、該当の要素に対してsortable
オプションの有効・無効を切り替えることで、移動をさせる・させないを設定することができます。APIのオプションはこちらです。
実際に実装してみた
いろいろと実装の方法はあるのですが、今回は該当の要素の上にポイントが乗った時に、有効・無効の判断をおこなって、切り替えるようにしてみました。
要件としては
- 最初は無効で、必要な場合のみ有効に切り替える
- 有効・無効はメニューで切り替えることが出来るようにする
の2点を想定します。
まずは移動が有効なのか無効なのかを判断するために、Body要素の中に、現在の状態を保持するフラグを作ります。
//同じ要素を複数回追加しないように、要素の有無をチェックする
if(!$('#SiteSortable').length){
$('body').append('<input id="SiteSortable" name="SiteSortable" type="hidden" value="0">');
}
このBodyの中にHiddenなInputを設置して、フラグや値を保持するというのはプリザンターでは、一般的な方法なので覚えておくと便利です。$p.UserId
などのスクリプトで使える関数も、実はこのInput群からデータを取っているというものは多いです。
次に、このフラグを反転させて、有効・無効を切り替える術を用意します。これも実装方法はいくらかあるのですが、今回はナビゲーションメニュー内に切替のメニューを用意することにします。
{
"TargetId": "SettingsMenu",
"Action": "Append",
"NavigationMenus": [
{
"ContainerId": "ExtendSettingsContainer",
"MenuId": "ExtendSettingsMenu",
"Name": "拡張管理",
"Icon": "ui-icon ui-icon-gear",
"ChildMenus": [
{
"MenuId": "SettingsMenu_DisableSorter",
"Name": "移動を有効にする",
"Icon": "ui-icon ui-icon-radio-off",
"Url": "javascript:$p.naviMenuExtendDisableSorter();",
"ReferenceTypes": ["Sites"],
"Actions": ["index"]
}
]
}
]
}
このような感じで、表示されているページがサイトの場合のみに表示されるメニューを追加します。メニューからはJavaScriptの関数をキックします。
$p.naviMenuExtendDisableSorter = function(){
if($('#SiteSortable').val() == 0){
$('#SiteSortable').val(1);
$('#SettingsMenu_DisableSorter a').text('移動を無効にする');
$p.closeSideMenu();
}else{
$('#SiteSortable').val(0);
$('#SettingsMenu_DisableSorter a').text('移動を有効にする');
$p.closeSideMenu();
}
}
こちらがキックされる関数です。最初に追加したBobyのInput要素のValueを見て、そのフラグを反転させて、文言を差し替えています。
次は、実際に移動させる要素側の処理を追加します。
$('.nav-sites.sortable').on('mouseenter pointerenter touchstart',function(){
$(this).sortable($('#SiteSortable').val() == 0 ? 'disable' : 'enable');
});
移動することが出来る要素の上にポインタなどが乗ったときに、Body内のInputを見て、移動が有効・無効の判断をおこなって、それをスイッチさせています。
ソースコードまとめ
これを最後にまとめて、拡張スクリプト・拡張ナビゲーションメニューとして設置します。
if(!$('#SiteSortable').length){
$('body').append('<input id="SiteSortable" name="SiteSortable" type="hidden" value="0">');
}
$p.naviMenuExtendDisableSorter = function(){
if($('#SiteSortable').val() == 0){
$('#SiteSortable').val(1);
$('#SettingsMenu_DisableSorter a').text('ソートを無効にする');
$p.closeSideMenu();
}else{
$('#SiteSortable').val(0);
$('#SettingsMenu_DisableSorter a').text('ソートを有効にする');
$p.closeSideMenu();
}
}
$('.nav-sites.sortable').on('mouseenter pointerenter touchstart',function(){
$(this).sortable($('#SiteSortable').val() == 0 ? 'disable' : 'enable');
});
{
"TargetId": "SettingsMenu",
"Action": "Append",
"NavigationMenus": [
{
"ContainerId": "ExtendSettingsContainer",
"MenuId": "ExtendSettingsMenu",
"Name": "拡張管理",
"Icon": "ui-icon ui-icon-gear",
"ChildMenus": [
{
"MenuId": "SettingsMenu_DisableSorter",
"Name": "ソートを有効にする",
"Icon": "ui-icon ui-icon-radio-off",
"Url": "javascript:$p.naviMenuExtendDisableSorter();",
"ReferenceTypes": ["Sites"],
"Actions": ["index"]
}
]
}
]
}
まとめ
サイトの移動を禁止させる仕組みが出来ました。
UI回りの実装はjQuery UIを使っているということ、使い回しをする値はBodyの中にInputをHiddenで入れておくというプリザンターの小技を覚えておくと、いろいろと応用を利かせることが出来ます。