کار با پنجره ها و رویدادهای مرورگر
ایجاد پنجرههای جدید
در جاوا اسکریپت با استفاده از متد open از شئ window میتوان یک پنجرهی جدید (یا زبانهی جدید) ایجاد کرد. این متد ۴ آرگومان ورودی میپذیرد که هر ۴ مورد اختیاری هستند. با توجه به اینکه آرگومان چهارم تقریباً هیچگاه مورد استفاده قرار نمیگیرد، فقط ۳ آرگومان اول معرفی میشوند. ابتدا با سادهترین حالت شروع میکنیم. در این حالت فقط یک آدرس URL به عنوان آرگومان اول به متد open ارسال میشود. در این صورت یک زبانهی جدید در مرورگر ایجاد شده و صفحهی وب مورد نظر را بارگذاری میکند. به مثال زیر توجه کنید.
<button id="open" type="button">Open</button>
<button id="close" type="button">Close</button>
const button1 = document.querySelector('#open');
button1.addEventListener('click' , openWindow);
function openWindow(){
open('http://otedia.com');
}
با اجرای این برنامه و کلیک کردن بر روی دکمهی "Open"، یک زبانهی جدید در مرورگر باز شده و آدرس "http://otedia.com" در این زبانه بارگذاری میشود. این برنامه را میتوانید اینجا اجرا کنید.
متد open یک اشارهگر به پنجرهی جدید بازمیگرداند. با استفاده از این اشارهگر میتوان به پنجرهی جدید دسترسی پیدا کرده و اعمال لازم را در صورت نیاز بر روی آن انجام داد. یکی از اعمالی که میتوان بر روی پنجرههای جدید انجام داد، بستن آنها است. برای انجام این کار میتوان از متد close استفاده کرد. البته برای این منظور حتماً باید اشارهگری که توسط متد open بازگردانده میشود، ذخیره شده باشد. مثال زیر نحوهی انجام این کار را نشان میدهد.
const button1 = document.querySelector('#open');
button1.addEventListener('click' , openWindow);
const button2 = document.querySelector('#close');
button2.addEventListener('click' , closeWindow);
let pointer;
function openWindow(){
pointer = open('http://otedia.com');
}
function closeWindow(){
pointer.close();
}
حال با کلیک کردن بر روی دکمهی "Open"، یک زبانهی جدید در مرورگر باز میشود. و با کلیک کردن بر روی دکمهی "Close"، همان زبانه بسته میشود. توجه کنید که در صورتی که چند بار بر روی دکمهی "Open" کلیک کنید، چند زبانه در مرورگر باز میشود. اما با کلیک کردن بر روی دکمهی "Close" فقط میتوانید آخرین زبانهی باز شده را ببندید. زیرا فقط آخرین اشارهگری که توسط متد open بازگرداده شده است در متغیر pointer ذخیره میشود. این برنامه را میتوانید اینجا اجرا کنید.
در آرگومان دوم متد open میتوان یک نام دلخواه را برای پنجرهی جدید مشخص کرد. از این نام میتوان در مراحل بعدی برای بارگذاری مجدد صفحه و یا بارگذاری یک صفحهی جدید در پنجرهی مورد نظر استفاده کرد. برای این منظور باید نام قبلی را مجدداً در متد open به کار ببریم. یعنی در صورتی که نام موجود در آرگومان دوم متد open، قبلاً برای پنجرهی دیگری به کار رفته باشد، متد open پنجرهی جدیدی ایجاد نمیکند. بلکه صفحهی مورد نظر را در همان پنجرهی موجود باز میکند. البته در صورتی که پنجرهی قبلی هنوز بسته نشده باشد. به مثال زیر توجه کنید.
const button1 = document.querySelector('#open');
button1.addEventListener('click' , openWindow);
function openWindow(){
open('http://otedia.com' , 'otedia');
}
حال با اولین کلیک بر روی دکمهی "Open" یک زبانهی جدید در مرورگر با نام "otedia" ایجاد میشود. البته این نام توسط کاربر قابل مشاهده نیست. اما با کلیکهای بعدی بر روی این دکمه، زبانهی جدیدی باز نمیشود. زیرا یک زبانه با نام "otedia" باز است. بنابراین صفحهی جدید در همان زبانهی قبلی بارگذاری میشود. البته در این مثال آدرس صفحهی جدید با آدرس صفحهی قبلی یکسان است. اما اگر دو آدرس متفاوت هم باشند، باز هم زبانهی جدیدی ایجاد نخواهد شد. این مثال را میتوانید اینجا اجرا کنید.
به طور خلاصه میتوان گفت در صورتی که پنجره یا زبانهای با نام مشخص شده در آگومان دوم باز باشد، متد open پنجره یا زبانهی جدیدی ایجاد نمیکند، بلکه فقط آدرس مشخص شده را در پنجره یا زبانهی موجود بارگذاری میکند.
اما آرگومان دوم متد open چند مقدار ویژه نیز میتواند داشته باشد که هر یک دارای مفهوم خاصی است. این موارد عبارتند از :
- _blank : به معنی باز شدن در یک پنجره یا زبانهی جدید است. (حالت پیشفرض)
- _self : به معنی باز شدن در پنجرهی جاری است. یعنی مانند استفاده از متد assign رفتار کرده و آدرس صفحهی جاری را تغییر میدهد.
- _parent : به معنی باز شدن در پنجرهی والد است. این حالت فقط زمانی به کار میرود که صفحهی وب توسط تگ <iframe> بارگذاری شده باشد.
- _top : به معنی باز شدن در پنجرهی والد ریشه است. این حالت فقط زمانی به کار میرود که صفحهی وب توسط تگ <iframe> بارگذاری شده باشد.
تفاوت دو حالت "_parent" و "_top" زمانی مشخص میشود که تگهای <iframe> به صورت تو در تو استفاده شده باشند. در این صورت "_top" به معنی پنجرهای است که والد تمام <iframe> ها است. اما "_parent" به معنی والد <iframe> جاری است که میتواند پنجرهی اصلی باشد یا یک <iframe> دیگر. در صورتی که فقط یک سطح از <iframe> ها وجود داشته باشد، تفاوتی بین این دو حالت وجود ندارد و هر دو به پنجرهی اصلی مرورگر اشاره میکنند. البته در مجموع این دو مقدار ویژه به ندرت به کار برده میشوند.
آرگومان سوم متد open نیز مانند دو آرگومان قبلی یک رشته است. با استفاده از این رشته میتوان ویژگیهای پنجرهی جدید را مشخص کرد. ویژگیهایی مانند عرض، ارتفاع، موقعیت در صفحه نمایش و ... را میتوان در این رشته مشخص کرد. البته نحوهی رفتار مرورگرهای مختلف با این آرگومان یکسان نیست و تفاوتهایی در این زمینه وجود دارد. از این آرگومان معمولاً برای باز کردن پنجرههای Pop-up استفاده میشود که بیشتر جهت تبلیغات به کار میروند و حتماً نمونههایی از این نوع پنجرهها را تا به حال در وبسایتهای مختلف دیدهاید.
به عنوان مثال در برنامهی زیر با کلیک کردن بر روی دکمهی "Open" یک پنجرهی جدید با ابعاد ۴۰۰ در ۵۰۰ پیکسل باز شده و از سمت چپ و بالای صفحه نمایش به ترتیب ۱۰۰ و ۲۰۰ پیکسل فاصله دارد.
const button1 = document.querySelector('#open');
button1.addEventListener('click' , openWindow);
function openWindow(){
open('http://otedia.com' , '_blank' , 'width=400,height=500,left=100,top=200');
}
این برنامه را میتوانید اینجا اجرا کنید. همچنین جزئیات بیشتر در رابطه با این آرگومان را میتوانید اینجا مطالعه کنید.
نکته : با توجه به اینکه معمولاً از متد open برای باز کردن پنجرههای تبلیغاتی Pop-up استفاده میشود که معمولاً بسیار آزار دهنده هستند. مرورگرهای امروزی بخشی به نام Pop-up Blocker دارند که از باز شدن پنجرههای جدید به صورت خودکار جلوگیری میکنند. به همین دلیل استفاده از متد open فقط در صورتی امکانپذیر است که کاربر عملی را در صفحهی وب انجام دهد. یعنی نمیتوان در زمان بارگذاری صفحهی وب از متد open استفاده کرد. بلکه باید مانند مثالهای فوق، این متد را بعد از انجام یک عمل توسط کاربر (مثلاً کلیک روی دکمه) اجرا کرد. به همین دلیل است که در سایتهایی که از پنجرههای Pop-up برای تبلیغات استفاده میکنند، بعد از کلیک کردن کاربر در صفحهی وب پنجرهی تبلیغاتی نمایش داده میشود.
رویدادهای مرورگر
در فصل هفتم و هشتم با بسیاری از رویدادهایی که برای عناصر صفحهی وب رخ میدهند آشنا شدیم. اما رویدادها میتوانند برای مرورگر نیز رخ دهند. تعداد رویدادهایی که برای مرورگر (شئ window) رخ میدهند بسیار زیاد است. برخی از این رویدادها برای عناصر صفحهی وب نیز رخ میدهند (مانند click یا scroll) و برخی دیگر فقط مختص مرورگر هستند (مانند afterprint). در این بخش قصد داریم به معرفی مهمترین رویدادهای مرورگر بپردازیم.
رویداد load
رویداد load یکی از مهمترین رویدادهایی است که برای مرورگر رخ میدهد. این رویداد پس از بارگذاری تمام محتوای صفحه رخ میدهد. در فصل هفتم با رویداد DOMContentLoaded آشنا شدیم. این رویداد بعد از بارگذاری ساختار DOM رخ میدهد. یعنی نیازی به بارگذاری منابع خارجی مانند تصاویر، فایلهای CSS، فایلهای جاوا اسکریپت و ... نیست و به محض بارگذاری ساختار DOM (یا همان سند HTML) رویداد DOMContentLoaded رخ میدهد. به همین دلیل معمولاً Event Handler های عناصر DOM را پس از وقوع این رویداد تعریف میکنیم.
اما ممکن است در شرایط خاصی لازم باشد علاوه بر بارگذاری سند HTML، بارگذاری تمام منابع خارجی نیز برای اجرای صحیح برنامه مورد نیاز باشد. مثلاً یک بازی را در نظر بگیرید که شامل تعداد زیادی تصویر است. برای شروع این بازی لازم است تا تمام تصاویر بارگذاری شده باشند. در چنین شرایطی میتوان از رویداد load برای شئ window استفاده کرد و اجازهی شروع بازی را پس وقوع رویداد load صادر کرد.
تا قبل از HTML5، رویداد DOMContentLoaded در مرورگرها پشتیبانی نمیشد. به همین دلیل در برنامههای جاوا اسکریپت قدیمی از رویداد load به جای رویداد DOMContentLoaded استفاده میشد. زیرا رویداد load از روزهای اولیهی پیدایش جاوا اسکریپت در مرورگرها پشتیبانی میشد. اما با توجه به اینکه در صفحاتی که منابع خارجی زیادی دارند رویداد load کمی با تاخیر رخ میدهد، رویداد DOMContentLoaded در HTML5 معرفی شد. بنابراین برای تعریف Event Handler ها بهتر است از رویداد DOMContentLoaded استفاده شود. زیرا این رویداد بسیار سریعتر از رویداد load رخ میدهد و برای تعریف Event Handler ها نیازی به وقوع رویداد load نیست و بارگذاری سند HTML برای این منظور کافی است.
رویداد beforeunload
این رویداد قبل از بسته شدن یک پنجره رخ میدهد. از این رویداد معمولاً برای جلوگیری از بسته شدن پنجرههایی استفاده میشود که با بسته شدن آنها ممکن است اطلاعات مهمی از دست برود. مثلاً اگر مشغول آپلود کردن یک فایل باشید و در همین حین پنجره را ببندید، بخش آپلود شده از دست خواهد رفت و باید فایل را مجدداً آپلود کنید. و یا به عنوان مثالی دیگر سایت CodePen را در نظر بگیرید. در صورتی که یک برنامه را در این سایت ویرایش کنید و قبل از ذخیره کردن تغییرات قصد بستن مرورگر را داشته باشید، با پیامی شبیه به شکل زیر مواجه میشوید که به شما هشدار میدهد که در صورت بسته شدن پنجره، تغییرات انجام شده از دست خواهند رفت و برای بستن پنجره از شما درخواست تاییدیه میشود.
.
توجه کنید که این رویداد قابلیت لغو کامل با متد preventDefault را ندارد. یعنی نمیتوانید از بسته شدن پنجره جلوگیری کنید، بلکه فقط میتوانید پیامی را به کاربر نمایش دهید و برای بستن پنجره از کاربر تاییدیه دریافت کنید. برای این کار کافی است متد preventDefault را به کار ببرید. البته در حال حاضر در مرورگر Chrome علاوه بر استفاده از متد preventDefault باید یک رشتهی دلخواه را در خاصیت returnValue از شئ event قرار دهید. به مثال زیر توجه کنید.
window.addEventListener('beforeunload' , (event) => {
event.preventDefault();
event.returnValue = '';
});
این مثال را میتوانید اینجا اجرا کنید.
نکته : توجه کنید که استفاده از این رویداد، مانند استفاده از متد open فقط در صورتی امکانپذیر است که کاربر عملی را در صفحهی وب انجام داده باشد. مثلاً روی صفجه کلیک کند یا متنی را در یک فیلد وارد کند. در غیر این صورت این رویداد قابل استفاده نیست. این ویژگی باعث میشود تا پنجرههای تبلیغاتی Pop-up، که معمولاً کاربر هیچ عملی را در آنها انجام نمیدهد، امکان استفاده از این رویداد و ممانعت از بسته شدن پنجره را نداشته باشند.
رویداد resize
زمانی که اندازهی پنجرهی مرورگر تغییر میکند، رویداد resize رخ میدهد. در صورتی که این تغییر اندازه به صورت تدریجی (با ماوس) انجام شود، این رویداد مانند رویداد mousemove به صورت متوالی رخ میدهد. پس نباید در زمان وقوع این رویداد کارهای پیچیده با بار پردازشی بالا انجام شود. مثال زیر نحوهی عملکرد این رویداد را نشان میدهد.
window.addEventListener('resize' , (event) => {
let red = Math.floor(255 * Math.random(255));
let green = Math.floor(255 * Math.random(255));
let blue = Math.floor(255 * Math.random(255));
document.body.style.backgroundColor = `rgb(${red} , ${green} , ${blue}`;
});
این برنامه را میتوانید اینجا اجرا کنید. با اجرای این برنامه، با هر تغییری که در اندازهی مرورگر ایجاد میشود، رویداد resize رخ میدهد. و با هر بار وقوع رویداد resize، دستورات موجود در تابع Event Handler اجرا میشوند. در این تابع ابتدا ۳ عدد تصادفی بین ۰ تا ۲۵۵ ایجاد میشود. سپس با استفاده از این اعداد یک رنگ RGB تولید شده و در ویژگی background-color از عنصر <body> قرار داده میشود. بنابراین اگر به صورت متوالی اندازهی مرورگر را تغییر دهید، رنگ پس زمینه نیز به صورت متوالی تغییر خواهد کرد.
سایر رویدادهای شئ window
تعداد رویدادهایی که برای شئ window رخ میدهند بسیار زیاد بوده و بیشترشان برای سایر عناصر صفحهی وب نیز قابل استفاده هستند. مثلاً رویدادهایی مانند click یا mousemove را برای شئ window نیز میتوان به کار برد. اما به غیر از رویدادهایی که پیش از این برای شئ window معرفی شدند، مهمترین رویدادهایی که میتوان برای شئ window به کار برد، رویدادهای زیر هستند.
- hashchange : زمانی رخ میدهد که مقدار hash در آدرس صفحهی وب تغییر کند.
- blur : زمانی رخ میدهد که پنجره (یا زبانه) focus را از دست بدهد.
- focus : زمانی رخ میدهد که پنجره (یا زبانه) focus را در اختیار بگیرد.
- scroll : زمانی رخ میدهد که موقعیت نوار لغزنده (scrollbar) تغییر کند.
سعی کنید از این رویدادها برای شئ window استفاده کنید و رفتار هر یک را مشاهده کنید.