یک popup window یکی از قدیمیترین روشها برای نشان دادن document اضافی به کاربر است.
اساسا شما فقط اجرا میکنید:
window.open('https://javascript.info/')
… و آن یک پنجرهی جدید با URL داده شده باز میکند. اکثر مرورگرهای مدرن به گونهای پیکربندی شدهاند که به جای پنجرههای جداگانه، آدرس اینترنتی را در پنجرههای جدید باز کنند.
از زمانهای بسیار قدیم، Popupها وجود دارند. ایدهی اولیه این بود که بتوان یک محتوای دیگر را بدون بستن پنجرهی اصلی نمایش داد. در حال حاضر، راههای دیگری برای این کار وجود دارد: میتوانیم داده را به صورت پویا با fetch بارگیری کنیم و آن را در یک <div>
که به صورت پویا ایجاد شده است نمایش دهیم. بنابراین، popupها چیزهایی نیستند که ما هر روز از آنها استفاده کنیم.
همچنین، popupها در دستگاههای موبایل که چند پنجره را به صورت همزمان نشان نمیدهند کمی مشکل هستند.
با این حال، کارهایی وجود دارند که popupها هنوز در آنها استفاده میشوند. برای مثال، برای مجوز OAuth (lgin با Google/Facebook/…) چون که:
- یک popup پنجرهای جدا است که محیط JavaScript جداگانهی خود را دارد. بنابراین باز کردن یک popup از یک سایت سوم غیر قابل اطمینان، امن است.
- باز کردن یک popup بسیار ساده است.
- یک popup میتواند پیمایش کند (آدرس سایت را تغییر دهد) و به پنجرهی بازکننده پیام بفرستد.
مسدود کردن popup
در گذشته، سایتهای خبیث بسیار از popup سواستفاده میکردند. یک صفحه میتوانست تعداد زیادی popup با تبلیغات باز کند. بنابراین امروزه، اکثر مرورگرها تلاش میکنند که popup را مسدود کنند و از کاربر در برابر آنها محافظت کنند.
اکثر مرورگرها، اگر فراخوانی popupها خارج از event handlerهای ایجاد شده توسط کاربر صورت بگیرد، آنها را مسدود میکنند.
برای مثال:
// popup مسدود شده است
window.open('https://javascript.info');
// popup اجازه داده شده است
button.onclick = () => {
window.open('https://javascript.info');
};
به این ترتیب، کاربرها تا حدودی از popupهای ناخواسته محافظت میشوند، اما عملکرد به طور کامل غیرفعال نمیشود.
window.open
برای باز کردن یک popup از syntax روبهرو استفاده میشود: window.open(url, name, params)
:
- url
- یک URL برای بارگیری در پنجره جدید.
- name
- یک name پنجرهی جدید. هر پنجره یک
window.name
دارد و اینجا میتوانیم مشخص کنیم که از کدام پنجره به عنوان popup استفاده کنیم. اگر قبلا پنجرهای با این نام وجود داشته باشد، – URL داده شده در آن باز میشود، در غیر این صورت، یک پنجرهی جدید باز میشود. - params
- رشتهی configuration برای پنجرهی جدید. این شامل تنظیماتی است که با comma مشخص میشوند. هیچ spaceای نباید در params وجود داشته باشد، برای مثال:
width=200,height=100
تنظیمات برای params
:
- Position:
چپ/بالا
(عددی) – مختصات گوشهی سمت چپ بالای پنجره در صفحه. یک محدودیت وجود دارد: یک پنجرهی جدید را نمیتوان خارج صفحه قرار داد.عرض/ارتفاع
(عددی) – عرض و ارتفاع یک پنجرهی جدید. در حداقل عرض/ارتفاع یک محدودیت وجود دارد. بنابرین غیرممکن است که یک پنجرهی غیرقابل دیدن ایجاد کرد.
- ویژگیهای پنجره:
menubar
(بله/خیر) – .منوی مرورگر را در پنجره جدید نشان میدهد یا پنهان میکندtoolbar
(بله/خیر) – .نوار پیمایش مرورگر (به عقب، جلو، بارگذاری مجدد و …) را در پنجره جدید نشان میدهد یا پنهان میکندlocation
(بله/خیر) – .به طور پیش فرض اجازه مخفی کردن آن را نمیدهند IE و FF را در پنجرهی جدید نشان میدهد یا پنهان میکند URL فیلدstatus
(بله/خیر) – .را نشان میدهد یا پنهان میکند. باز هم، اکثر مرورگرها آن را مجبور به نمایش میکنند status barresizable
(بله/خیر) – .اجازه میدهد تا تغییر اندازه را برای پنجره جدید غیرفعال کنید. توصیه نمیشودscrollbars
(بله/خیر) – .اجازه میدهد تا نوارهای اسکرول را برای پنجره جدید غیرفعال کنید. توصیه نمیشود.
همجنین، تعدادی ویژگی خاص مرورگر وجود دارند که کمتر پشتیبانی میشوند که معمولا از آنها استفاده نمیشود. برای مثال، window.open در MDN را بررسی کنید.
مثال: یک پنجرهی minimalistic
بیایید یک پنجره با حداقل مجموعهای ویژگیها باز کنیم، فقط برای آن که ببینیم مرورگر کدام یکی از آنها را غیرفعال میکند:
let params = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,
width=0,height=0,left=-1000,top=-1000`;
open('/', 'test', params);
اینجا اکثر “ویژگیهای پنجره” غیرفعال شدهاند و پنجره خارج صفحه قرار میگیرد. آن را اجرا کنید و ببینید واقعا چه اتفاقی میافتد. اکثر مرورگرها موارد عجیب و غریب مثل width/height
صفر و left/top
خارج از صفحه را درست میکنند. برای مثال، chrome همچین پنجرهای را با عرض/ارتفاع کامل باز میکند تا تمام صفحه را اشغال کند.
بیایید گزینههای موقعیتیابی عادی و مختصات عرض
، ارتفاع
، چپ
، بالا
را اضافه کنیم:
let params = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,
width=600,height=300,left=100,top=100`;
open('/', 'test', params);
اکثر مرورگرها مثال بالا را در صورت لزوم نشان می دهند.
قوانین مربوط به تنظیمات حذف شده:
- اگر هیچ آرگومان سومی در فراخوانی
open
نیست یا خالی است، آنگاه پارامترهای پیشفرض پنجره استفاده میشوند. - اگر رشتهای از params وجود دارد اما بعضی از ویژگیهای
yes/no
حذف شدهاند، آنگاه فرض میشود که ویژگیهای حذفشده مقدارno
را دارند. اگر پارامترها را مشخص میکنید،مطمئن شوید که تمام ویژگیهای مورد نیاز به صراحت روی yes تنظیم شدهاند. - اگر هیچ
left/top
ای در params وجود ندارد، مرورگر تلاش میکند که پنجرهای جدید را نزدیک آخرین پنجرهی باز شده، باز کند. - اگر هیچ
width/height
ای وجود ندارد، پنجرهی جدید همان اندازهی آخرین پنجرهی باز شده را خواهد داشت.
دسترسی به popup از طریق پنجره
فراخوانی open
ارجاعی به پنجرهی جدید را برمیگرداند. از آن میتوان برای دستکاری کردن propertyها، تغییر دادن location و حتی بیشتر استفاده کرد.
در این مثال، ما از JavaScript محتوای popup را تولید میکنیم.
let newWin = window.open("about:blank", "hello", "width=200,height=200");
newWin.document.write("Hello, world!");
و اینجا بعد از load کردن، محتوا را دستکاری میکنیم.
let newWindow = open('/', 'example', 'width=300,height=300')
newWindow.focus();
alert(newWindow.location.href); // (*) about:blank, هنوز شروع نشده است loading
newWindow.onload = function() {
let html = `<div style="font-size:30px">Welcome!</div>`;
newWindow.document.body.insertAdjacentHTML('afterbegin', html);
};
لطفا توجه داشته باشید: بلافاصله بعد از window.open
پنجرهی جدید هنوز load نشده است. آن، در خط (*)
با alert
نشان داده میشود. پس صبر میکنیم تا onload
آن را اصلاح کند. همچنین برای newWin.document
میتوانیم از DOMContentLoaded
handler استفاده کنیم.
.میتوانند به صورت آزادانه به محتوای یکدیگر دسترسی داشته باشند (همان پروتکل://domain:port) پنجرهها فقط در صورتی که از یک مبدا باشند
.را ببینید ارتباط بین پنجرهای این برای دلایل امنیتی غیرممکن است. برای جزئیات، بخش gmail.com
از popup باشد و site.com
در غیر این صورت، برای مثال اگر پنجرهی اصلی از
دسترسی به پنجره از طریق popup
یک popup علاوه بر استفاده از ارجاع window.opener
میتواند به “opener” هم دسترسی داشته باشد. این برای تمام پنجرهها به جز popupها null است.
اگر کد زیر را اجرا کنید، محتوای openr window (در حال حاضر) را با “Test” جایگزین میکند.
let newWin = window.open("about:blank", "hello", "width=200,height=200");
newWin.document.write(
"<script>window.opener.document.body.innerHTML = 'Test'<\/script>"
);
بنابراین، ارتباط میان پنجرهها دوطرفه است: پنجرهی اصلی و popup ارجاعی به یکدیگر دارند.
بستن یک popup
برای بستن یک پنجره: win.close()
.
برای اینکه چک کنیم که یه پنجره بسته است یا نه: win.closed
.
از نظر فنی، close()
method برای هر window
قابل دسترسی است اما اگر window
با window.open()
ایجاد شده باشد، window.close()
توسط اکثر مرورگرها نادیده گرفته میشود. پس آن فقط روی یک popup کار خواهد کرد.
اگر پنجره بسته باشد، closed
property برابر true
میشود. این برای بررسی اینکه popup (یا پنجرهی اصلی) هنوز باز هستند یا نه مفید است. یک کاربر میتواند هر وقتی ببندد و کد ما باید امکان آن را در نظر بگیرد.
این کد پنجره را load میکند و سپس میبندد.
let newWindow = open('/', 'example', 'width=300,height=300');
newWindow.onload = function() {
newWindow.close();
alert(newWindow.closed); // true
};
حرکت دادن و تغییر اندازه
راههایی برای جابهجایی/تغییر اندازهی یک پنجره وجود دارد:
win.moveBy(x,y)
- پنجره را نسبت به موقعیت فعلی،
x
پیکسل به سمت راست وy
پیکسل به سمت پایین حرکت میدهد. مقادیر منفی هم مجاز هستند (برای حرکت دادن به چپ/بالا) win.moveTo(x,y)
- پنجره را به مختصات
(x,y)
در صفحه میبرد. win.resizeBy(width,height)
- پنجره را با اندازههای
width/height
داده شده نسبت به اندازهی فعلی تغییر سایز میدهد. مقادیر منفی مجاز هستند. win.resizeTo(width,height)
- پنجره را به اندازهی داده شده تغییر اندازه میدهد.
همچنین یک window.onresize
event نیز وجود دارد.
.برای اینکه از سواستفاده جلوگیری شود، مرورگر معمولا این متدها را مسدود میکنند. آنها فقط روی پنجرههای بازشو که هیچ صفحهی اضافی ندارند، به طور قابل اعتماد کار میکنند
.پنهان هستند Frontend-developers هیچ راهی برای به حداقل رساندن یا به حداکثر رساندن یک پنجره نیست. این متدها که در سطح سیستمعامل هستند از دید JavaScript در
.روشهای جابجایی/تغییر اندازه برای پنجرههای حداکثر/حداقل شده کار نمیکنند
پیمایش یک پنجره
ما قبلا در مورد scroll کردن یک پنجره در بخش Window sizes and scrolling صحبت کردهایم.
win.scrollBy(x,y)
- پنجره را نسبت به scroll فعلی،
x
پیکسل به راست وy
پیکسل به پایین scroll میکند. مقادیر منفی مجاز هستند. win.scrollTo(x,y)
- پنجره را به مختصات داده شده
(x,y)
scroll میکند. elem.scrollIntoView(top = true)
- پنجره را scroll میکند که
elem
را در بالا (پیش فرض) یا پایین برایelem.scrollIntoView(false)
نمایش دهد.
همچنین یک window.onscroll
event نیز هست.
Focus/blur روی یک پنجره
از نظر تئوری برای focus/unfocus کردن روی یک پنجره، دو متد window.focus()
و window.blur()
وجود دارند. و همچنین focus/blur
events هستند که که اجازه میدهند که لحظهای که بازدیدکننده روی یک پنجره focus/unfocus میکند و به جای دیگری تغییر میدهد را ثبت کنید.
اگرچه، در عمل آنها به شدت محدود هستند، زیرا در گذشته صفحات بد از آنها سوء استفاده میکردند.
برای مثال به این کد نگاه کنید:
window.onblur = () => window.focus();
وقتی یک کاربر تلاش میکند که از پنجره بیرون برود (window.onblur
)، این، پنجره را به focus برمیگرداند. هدف این است که کاربر را در window
قفل کنیم.
در نتیجه مرورگرها مجبور بودند تعدادی محدودیت معرفی کنند تا کدی مثل آن را ممنوع کند و کاربر را از تبلیغات و صفحات بد محافظت کنند. آنها به مرورگر بستگی دارند.
برای مثال، یک مرورگر موبایل معمولا window.focus()
را به طور کامل نادیده میگیرد. همچنین وقتی که یک popup در یک صفحهی جدا به جای یک پنجرهی جدبد باز میشود، فوکوس کردن کار نمیکند.
با این حال، موارد استفادهای وجود دارد که چنین فراخوانیهایی کار میکنند و میتوانند مفید باشند.
برای مثال:
- وقتی یک popup باز میکنیم، ممکن است ایدهی خوبی باشد که
newWindow.focus()
را روی آن اجرا کنیم. در هر صورت، برای برخی ترکیبات سیستمعامل/مرورگر، تضمین میکند که کاربر اکنون در پنجرهی جدید است. - گر بخواهیم ردیابی کنیم که چه زمانی بازدیدکننده واقعاً از برنامهی وب ما استفاده می کند، می توانیم
window.onfocus/onblur
را ردیابی کنیم. این به ما امکان میدهد فعالیتهای درون صفحه، انیمیشنها و… را تعلیق/ازسرگیری کنیم. اما لطفا توجه داشته باشید کهblur
event به این معنی است که بازدیدکننده از پنجره خارج شده است، اما همچنان ممکن است آن را مشاهده کند. پنجره در پسزمینه است، اما همچنان ممکن است قابل مشاهده باشد.
خلاصه
پنجرههای popup به ندرت استفاده میشوند. چون گزینههای دیگری وجود دارند: load کردن و نمایش دادن اطلاعات در صفحه یا در iframe.
اگر میخواهیم یک popup باز کنیم، یک تمرین خوب این است که به کاربر دربارهی آن اطلاعات بدهیم. یک نماد “opening window” نزدیک یک لینک یا دکمه به بازدیدکننده اجازه میدهد تا از تغییر فوکوس جان سالم به در ببرد و هر دو پنجره را در ذهن نگه دارد.
- یک popup میتواند با فراخوانی
open(url, name, params)
باز شود. آن ارجاع را به پنجرهی تازه بازشده بازمیگرداند. - مرورگرها فراخوانیهای
open
از خارج کنشهای کاربر را مسدود میکنند. معمولا یک اعلان ظاهر میشود که کاربر ممکن است به آنها اجازه بدهد. - مرورگرها به صورت پیشفرض یک tab جدید باز میکنند اما اگر اندازهها ارائه شده باشند، آنگاه یک پنجرهی popup خواهد بود.
- پنجرهی popup ممکن است با استفاده از
window.opener
property به پنجرهی بازکننده دسترسی داشته باشد. - اگر popup و پنجرهی اصلی از یک مبدا باشند، میتوانند به صورت آزادانه یکدیگر را بخوانند یا تغییر دهند. در غیر این صورت، میتوانند مکان یکدیگر را تغییر دهند و پیام رد و بدل کنند.
برای بستن popup: از فراخوانی close()
استفاده کنید. همچنین کاربر ممکن است آنها را ببندد (دقیقا شبیه هر پنجرهی دیگری). بعد از آن مقدار window.closed
برابر true
است.
- متدهای
focus()
وblur()
اجازه میدهند که روی یک پنجره focus/unfocus کنیم. اما آنها همیشه کار نمیکنند. - با
focus
andblur
events امکان ردیابی جابهجایی در داخل و خارج صفحه فراهم میشود/ اما لطفا توجه داشته باشید که بعد ازblur
یک پنجره ممکن است همچنان در وضعیت پسزمینه قابل مشاهده باشد.