Popupをもう少しどうにかしてみる
Popupをもう少し拡張しておきます
位置指定オプションにx,y,x1,y1,x2,y2を追加します
- x,yはポップアップ中心
- x1,y1はwindow左上からポップアップ左上
- x2,y2はwindow右下からポップアップ右下
を指定します
/Src/cm.ts
/* * ポップアップ */ interface PopupOptions { arrow?: boolean; x?: number; y?: number; x1?: number; // x左端指定 x2?: number; // x右端指定 y1?: number; // y上端指定 y2?: number; // y下端指定 positionFixed?: boolean; // 位置固定 restoreScrollPos?: boolean; // スクロール位置復元 focusSelector?: string | JQuery; // フォーカス指定 closeButton?: boolean; // 閉じるボタン付加 onHeightOverflow?(overflow: boolean): any; // 高さ食み出しイベント onOpend?: any; onClosed?: any; // 終了イベント } namespace Popup { "use strict"; /* * コンテナ取得 */ export function getContainer(selector: string | JQuery): JQuery { return $(selector).closest(".ui-popup-container"); } /* * オープン */ export function open(selector: string | JQuery, options?: PopupOptions): JQuery { let pos: number = undefined; let target = $(selector); let Container = getContainer(target); // 閉じるボタン追加 if (options && options.closeButton) { target.css("padding-top", "2em"); let btn = $("<button>"); btn.addClass("ui-btn ui-btn-icon-notext ui-icon-delete ui-popup-close"); btn.css({ "position": "absolute" , "margin": "0.3em" , "top": 0 , "right": 0 , "left": "auto" , "bottom": "auto" , "padding": 0 }); target.append(btn); } /* * 位置変更 */ target.off("popupbeforeposition").on("popupbeforeposition", function (event: Event, data: any) { // 位置固定 if (options && options.positionFixed) { // Container.css("position", "fixed"); } // 位置指定 if (options) { if (options.positionTo) { // 基準指定 delete data.x; delete data.y; data.positionTo = options.positionTo; // リサイズ時の位置復元 } else { // 吹き出し有無判定 let hasArrow = (target.children(".ui-popup-arrow-container").length > 0); // x座標 let cx: number = undefined; if (!isNaN(options.x)) { cx = options.x; } else if (!hasArrow) { // 吹き出し無しのみ左右端指定可 let winW = $(window).width(); let itmW = target.outerWidth(); if (!isNaN(options.x1)) { // 左端指定 cx = options.x1 + (itmW / 2); } else if (!isNaN(options.x2)) { // 右端指定 cx = (winW - (itmW / 2)) - options.x2; } } // y座標 let cy: number = undefined; if (!isNaN(options.y)) { cy = options.y; } else if (!hasArrow) { // 吹き出し無しのみ上下端指定可 let winH = $(window).height(); let itmH = target.outerHeight(); if (!isNaN(options.y1)) { cy = options.y1 + (itmH / 2); // 上端指定 } else if (!isNaN(options.y2)) { cy = (winH - (itmH / 2)) - options.y2; // 下端指定 } } // リサイズ時の座標復元 if (!isNaN(cx) || !isNaN(cy)) { delete data.positionTo; if (!isNaN(cx)) { data.x = cx; } if (!isNaN(cy)) { data.y = cy; } } } } // 高さオーバーフローイベント if (options && options.onHeightOverflow) { let winH = $(window).height(); let itmH = target.outerHeight(); let overflow = false; if (itmH >= winH) { overflow = true; } options.onHeightOverflow(overflow); // コールバック } }); /* * オープン後 */ target.off("popupafteropen").on("popupafteropen", function (event: Event) { // フォーカス指定 if (options && options.focusSelector) { let itm = $(options.focusSelector); itm.focus(); } // 位置固定 if (options && options.positionFixed) { Container.css({ "position": "fixed" , "margin-top": -cm.getScrollTop() }); } $(Window).resize(); // オープン完了 if (options && options.onOpend) { options.onOpend(); // コールバック } }); /* * クローズ */ target.off("popupafterclose").on("popupafterclose", function (event: Event) { // スクロール位置復元 if (isNaN(pos) === false) { $.mobile.silentScroll(pos); } // 終了イベント if (options && options.onClosed) { options.onClosed(); // コールバック } // イベントハンドラ破棄 target.off("popupbeforeposition") .off("popupafteropen") .off("popupafterclose"); // コンテナ位置設定削除 Container.css("position", ""); target = null; Container = null; }); // スクロール位置保持 if (options && options.restoreScrollPos) { pos = cm.getScrollTop(); } // オープン if (!options) { options = { transition: "fade" // フェードイン , tolerance: "0" // 余白なし }; } else { if (!options.transition) { options.transition = "fade"; } if (!options.tolerance) { options.tolerance = "0"; } } target.popup(options).popup("open", options); return target; } /* * クローズ */ export function close(): boolean { if ($(".ui-popup").isVisible() === true) { $(".ui-popup").popup("close"); return true; } return false; } export function isActive(id?: string): boolean { if (id) { return ($("#" + id + "-popup.ui-popup-active").length > 0); } else { return ($(".ui-popup-active").length > 0); } } /* * クローズボタン押下 */ $(document).on("click", ".ui-btn.ui-popup-close", function (event: Event) { Popup.close(); }); }
サンプルです
HomeのPage2に追加します
/Views/Home/Index.vbhtml
<div data-role="page" id="page2"> <div data-role="popup" data-history="false" id="page2_popup1" data-arrow="false"> <ul data-role="listview" data-icon="false"> <li><a href="#">アイテム1</a></li> <li><a href="#">アイテム2</a></li> <li><a href="#">アイテム3</a></li> <li><a href="#">アイテム4</a></li> <li><a href="#">アイテム5</a></li> <li><a href="#">アイテム6</a></li> <li><a href="#">アイテム7</a></li> <li><a href="#">アイテム8</a></li> <li><a href="#">アイテム9</a></li> <li><a href="#">アイテム10</a></li> </ul> </div> <div data-role="header" data-position="fixed" data-fullscreen="false" data-tap-toggle="false"> <h1>Dialog</h1> <a href="#" class="ui-btn ui-btn-icon-notext ui-icon-video" cmd="btn1">ボタン1</a> <a href="#" class="ui-btn ui-btn-icon-notext ui-icon-camera" cmd="btn2">ボタン2</a> </div> <div role="main" class="ui-content ui-form"> <ul data-role="listview" data-inset="true" data-icon="false" class="split"> <li> <div class="ui-field-contain em7"> <label for="text-12">Text input:</label> <div> <input name="text-12" id="text-12" type="text" value=""> </div> </div> <button class="ui-btn ui-btn-icon-notext ui-btn-split ui-icon-carat-d" cmd="popup1"></button> </li> <li> <div class="ui-field-contain em7"> <label for="text-13">Text input clr:</label> <div> <input name="text-13" id="text-13" type="text" value="" data-clear-btn="true"> </div> </div> </li> <li> <div class="ui-field-contain em7"> <label for="search-8">Search:</label> <div> <input name="search-8" id="search-8" type="search" value=""> </div> </div> </li> <li> <div class="ui-field-contain em7"> <label for="textarea-12">Textarea:</label> <div> <textarea name="textarea-12" id="textarea-12" rows="8" cols="40"></textarea> </div> </div> <button class="ui-btn ui-btn-icon-notext ui-btn-split ui-icon-delete"></button> </li> <li> <div class="ui-field-contain em7"> <label for="Switch">Flip switch:</label> <div> <input name="flip-checkbox-1" id="flip-checkbox-1" type="checkbox" data-role="flipswitch"> </div> </div> </li> </ul> </div> <div data-role="footer" data-position="fixed" data-fullscreen="false" data-tap-toggle="false"> <div class="ui-toolbar" id="page2_cmd"> <div class="ui-left-panel"> <a href="#" class="ui-btn" cmd="reset">リセット</a> </div> <div class="ui-right-panel"> <a href="#" class="ui-btn ui-btn-active">OK</a> <a href="#page1" class="ui-btn">キャンセル</a> </div> </div> </div> </div>
/Src/home.ts
namespace Page2 { $(document).on("click", "#page2 > .ui-header > .ui-btn", function (event: Event) { $(this).blur(); let y1 = $("#page2 > .ui-header").outerHeight() + $(window).scrollTop(); let cmd = $(this).attr("cmd"); switch (cmd) { case "btn1": Popup.open("#page2_popup1", { x1: 0 , y1: y1 , positionFixed: true , transition: "slidedown" }); break; case "btn2": Popup.open("#page2_popup1", { x2: 0 , y1: y1 , transition: "slidedown" }); break; } }); $(document).on("click", "#page2 li > .ui-btn", function (event: Event) { let cmd = $(this).attr("cmd"); switch (cmd) { case "popup1": let pos = $(this).offset(); Popup.open("#page2_popup1", { x2: $(window).width() - pos.left - $(this).outerWidth() - 1 , y1: pos.top + $(this).outerHeight() }); break; } }); $(document).on("click", "#page2 > .ui-footer .ui-btn", function (event: Event) { $(this).blur(); let cmd = $(this).attr("cmd"); switch (cmd) { case "reset": let y2 = $("#page2 > .ui-footer").outerHeight() - $(window).scrollTop(); Popup.open("#page2_popup1", { x1: 0 , y2: y2 , transition: "flip" , positionFixed: true }); break; } }); }
ボタンのドロップダウンメニュー風にしたり出来るようになりました