۲۵ ژوئیه ۲۰۲۲

رویدادهای موس

در این بخش به جزئیاتی درباره‌ی رویدادهای موس و خصوصیات آن‌ها می‌پردازیم.

توجه داشته باشید: این رویدادها نه تنها بواسطه “دستگاه‌های موس”، بلکه بواسطه دستگاه‌های شبیه‌سازی شده تلفن و تبلت نیز روی بدهند.

انواع رویدادهای موس

ما قبلا با چند مورد از این رویدادها آشنا شده‌ایم:

mousedown/mouseup
دکمه موس کلیک/رها می‌شود.
mouseover/mouseout
اشاره‌گر موس روی/بیرون عنصر می‌رود.
mousemove
هر حرکت موس روی عنصر این رویداد را فرامی‌خواند.
click
درصورتی که کلید چپ موس استفاده شود، این رویداد بعد از mousedown و سپس mouseup‍ روی یک عنصر فراخوانده می‌شود.
dblclick
زمانی که دو کلیک روی یک عنصر در بازه زمانی کوتاهی انجام شود فراخوانده می‌شود. امروزه به ندرت استفاده می‌شود.
contextmenu
زمانی که کلید راست موس فشرده روی یک عنصر فشرده شود فراخوانده می‌شود. راه‌های دیگری برای باز کردن منوی زمینه وجود دارد. برای مثال استفاده از یک کلید مخصوص در کیبورد این رویداد را نیز فراخوانی می‌کند، پس این دقیقا یک رویداد موس نیست.‌

…چندین رویداد دیگر وجود دارند که بعدا آنهارا برسی می‌کنیم.

ترتیب رویدادها

همان‌طور که در لیست بالاهم مشاهده کردید، یک عمل کاربر می‌تواند باعث فراخوانی چند رویداد شود.

برای مثال، یک کلیک چپ ابتدا mousedown‍ را فراخوانی می‌کند، هنگامی که کلید فشرده می‌شود، سپس mouseup‍ و click زمانی که کلید رها می‌شود.

در مواقعی که یک عمل از سمت کاربر باعث فراخوانی چند رویداد شود، ترتیب آنها ثابت خواهد بود. به این معنی که کنترل‌کننده‌ها به ترتیب mousedownmouseupclick صدا زده خواهند شد.

روی دکمه زیر کلیک کنید تا رویدادها را ببینید. دابل کلیک را هم امتحان کنید.

در قسمت آزمایشی زیر همه رویدادهای موس (mouse) چاپ می‌شوند، و اگر بیش از ۱ ثانیه فاصله زمانی بین آن‌ها باشد، توسط یک خط افقی جدا می‌شوند.

همچنین می‌توانیم یک خاصیت button مشاهده کنیم که به ما این امکان را می‌دهد تا کلید موس را شناسایی کنیم که در قسمت پایین شرح داده شده.

کلید موس

رویدادهای مربوط به کلیک‌کردن همیشه یک خاصیت button خواهند داشت، که به ما این امکان را می‌دهد کلید موس را دقیقا تشخیص دهیم.

ما معمولا این خاصیت را برای رویدادهای click و contextmenu استفاده نمی‌کنیم،‌ زیرا اولی فقط با کلیک چپ، و دومی با کلیک راست اتفاق می‌افتد.

از طرف دیگر، کنترل‌کننده‌های mousedown و mouseup‍‍ ممکن است به event.button نیاز پیدا کنند، زیرا این رویدادها به واسطه هر کلیدی اتفاق می‌افتند، پس button این امکان را می‌دهد تا “کلیک کلید راست” و “کلیک کلید چپ” موس را تشخیص دهیم.

مقادیر قابل قبول برای event.button:

event.button وضعیت کلید
0 کلید چپ (اصلی)
1 کلید وسط (کمکی)
2 کلید راست (ثانوی)
3 کلید X1 (عقب)
4 کلید X2 (جلو)

بیشتر موس‌ها فقط کلید چپ و راست را دارند، پس مقادیر احتمالی 0 و 2 هستند. دستگاه‌های لمسی نیز هنگامی که روی آنها ضربه زده شود رفتار مشابهی‌ را ایجاد می‌کنند.

همچنین خصوصیت event.buttons همه کلیدهایی که هم اکنون فشرده شده‌اند را دارد، یک بیت به ازای هر کلید. در عمل این خصوصیت به ندرت استفاده می‌شود، در صورت نیاز، می‌توانید جزئیات بیشتری را MDN پیدا کنید.

event.which منسوخ شده

کدهای قدیمی احتمالا از خاصیت event.which استفاده کرده‌اند که یک روش غیر استاندارد برای گرفتن کلید ها است. مقادیر احتمالی به صورت زیر است:

  • event.which == 1 – کلید چپ,
  • event.which == 2 – کلید وسط,
  • event.which == 3 – کلید راست.

به دلیل اینکه ‍event.which منسوخ شده، نباید از از آن استفاده کنیم.

اصلاح‌کننده‌ها: shift, alt, ctrl و meta

همه رویدادهای موس اطلاعاتی درباره کلیدهای اصلاح‌کننده دارند.

خصوصیات رویداد:

  • shiftKey: Shift
  • altKey: Alt (یا Opt برای مک)
  • ctrlKey: Ctrl
  • metaKey: Cmd برای مک

مقادیر آنها در صورتی که کلید اشاره‌شده در حین رویداد فشرده شده بود، true است.

برای مثال، کلید زیر تنها روی Alt+Shift+کلیک کار می‌کند:

<button id="button">روی من Alt+Shift+کلیک کنید</button>

<script>
  button.onclick = function(event) {
    if (event.altKey && event.shiftKey) {
      alert('هووورا!');
    }
  };
</script>
توجه: روی مک معمولا CmdبجایCtrlخواهد بود

روی ویندوز و لینوکس کلیدهای اصلاح‌کننده Alt, ShiftوCtrlوجود خواهد داشت. روی مک یک کلید دیگر نیز وجود دارد: Cmd, متناظر خاصیت metaKey.

در بیشتر اپلیکیشن‌ها هنگامی که در ونیدوز/لینوکس از Ctrl استفاده می‌شود، روی مک Cmd خواهد بود.

به این معنی که: وقتی یک کاربر ویندوز کلید Ctrl+Enter یا Ctrl+A را می‌فشارد، یک کاربر مک باید Cmd+Enter یا Cmd+A را فشار دهد، مشابه برای بقیه کلیدها.

پس اگر میخواهیم ترکیبی مانند Ctrl+کلیک را پشتیبانی کنیم، پس برای مک باید از Cmd+کلیک استفاده کنیم. این ترکیب برای کاربران مک راحت‌تر خواهد بود.

حتی اگر میخواستیم که کاربر مک را وادار کنیم که از Ctrl+کلیک استفاده کند، دشوار خواهد بود. مشکل این است که: یک چپ-کلیک با Ctrl همانند یک right-click شناخته می‌شود، و رویداد contextmenu اتفاق می‌افتد، نه اینکه مانند ویندوز/لینوکس رویداد click اتفاق بیفتد.

پس اگر می‌خواهیم که کاربران همه سیستم‌های عامل احساس راحتی داشته باشند، پس همراه ctrlKey باید metaKey را نیز چک کنیم.

در کد جاوااسکریپت به این معنی است که میخواهیم ‍if (event.ctrlKey || event.metaKey) را چک کنیم.

همچنین دستگاه‌های موبایل نیز وجود دارند

ترکیب‌های کلید‌های کیبورد به عنوان یک قابلیت اضافه خوب هستند. اگر کاربر از کیبورد استفاده کند، کار می‌کنند.

اما اگر دستگاه آنها کیبورد نداشته باشد، پس باید راهی برای زندگی کردن بدون از کلیدهای اصلاح‌کننده باشد.

مختصات: clientX/Y, pageX/Y

همه رویدادهای موس مختصاتی را به دو صورت در اختیار ما قرار می‌دهند:

  1. مربوط به پنجره: clientX و clientY.
  2. مربوط به سند: pageX و pageY.

ما قبلا درباره تفاوت آنها در بخش Coordinates صحبت کرده‌ایم.

به اختصار، مختصات مربوط به سند pageX/Y از گوشه‌ی بالا چپ سند محاسبه می‌شوند و زمانی که صفحه پیمایش شود تغییر نمی‌کنند، درصورتی که clientX/Y از گوشه بالا چپ پنجره فعلی شمرده می‌شوند. زمانی که صفحه پیمایش شود، تفییر می‌کنند.

برای مثال، اگر یک پنجره با اندازه 500x500 داشته باشیم، و اشاره‌گر موس در گوشه بالا چپ باشد، پس clientX و clientY مقدار 0 خواهند داشت، بدون توجه به اینکه صفحه چقدر پیمایش شده باشد.

و اگر اشاره‌گر موس در وسط باشد، پس clientX و clientY مقدار 250 خواهند داشت بدون توجه به اینکه کجای سند قرار دارند. از این نظر مانند position:fixed هستند.

موس را روی قسمت ورودی ببرید تا مقادیر clientX/clientY ببینید (مثال در iframe وجود دارد, پس مقادیر نسبت به آن iframe خواهند بود):

<input onmousemove="this.value=event.clientX+':'+event.clientY" value="موس را روی من ببر">

جلوگیری از انتخاب در هنگام mousedown

دابل کلیک موس یک اثر جانبی دارد که در بعضی از رابطه‌های کاربری ممکن است مزاحم باشد: متن را انتخاب می‌کند.

برای مثال، دابل کلیک کردن روی متن زیر آنرا انتخاب می‌کند که در کنترل‌کندده ما تعریف نشده:

<span ondblclick="alert('dblclick')">من را دوبار کلیک کن</span>

اگر یک نفر کلید چپ موس را فشار دهد، بدون رها کردن آن، اشاره‌گر موس را جابجا کند، بیشتر اوقات متن را انتخاب می‌کند که ممکن است باب میل ما نباشد.

راه های مختلفی برای جلوگیری از آن انتخاب وجود دارد، که می‌توانید در بخش Selection و Range مشاهده کنید.

منطقی‌ترین راه در این مورد به خصوص این است که از رفتار پیش‌فرض مرورگر هنگام mousedown جلوگیری کنیم. این کد از انتخاب هر دو این‌ها جلوگیری می‌کند:

قبل...
<b ondblclick="alert('کلیک!')" onmousedown="return false">
  من را دوبار کلیک کن
</b>
...بعد

اکنون قسمت پررنگ، هنگام دابل کلیک قابل انتخاب نیست و کلیک چپ روی آن، انتخاب کردن متن را آغاز نمی‌کند.‎

توجه داشته باشید: متن داخل آن هنوز قابل انتخاب است. هرچند، انتخاب نباید از روی خود متن، بلکه از قبل یا بعد آن آغاز شود. معمولا کاربران با این رفتار مشکلی ندارند.

جلوگیری از کپی کردن

اگر می‌خواهیم که انتخاب شدن متن‌را به منظور محافظت کردن از اطلاعات صفحه در مقابل کپی شدن انجام دهیم، می‌توانیم از یک رویداد دیگر استفاده کینم: oncopy.

<div oncopy="alert('کپی کردن ممنوع!');return false">
  کاربر عزیز,
  کپی کردن برای شما ممنوع شده است.
  هرچند اگر که اچ‌تی‌ام‌ال یا جاوااسکریپت بلد هستید، می‌توانید هرچه نیاز دارید از سورس صفحه پیدا کنید.
</div>

اگر تلاش کنید که اطلاعات متنی داخل <div> را کپی کنید، کار نمی‌کند، زیرا از رفتار پیش‌فرض مرورگر در هنگام oncopy جلوگیری شده.

قاعدتا کاربر به سورس اچ‌تی‌ام‌ال صفحه دسترسی دارد، و می‌تواند هر اطلاعاتی که بخواهد از آنجا بردارد، اما هرکسی نمی‌داند چطور این‌ کار انجام می‌شود.

خلاصه

رویداد‌های موس این خصوصیات‌را دارند:

  • کلید: button.

  • کلید‌های اصلاح‌کننده (true اگر فشار داده‌شوند): altKey, ctrlKey, shiftKey و metaKey (مک).

    • اگر می‌خواهید که Ctrl را کنترل کنید، کاربران مک‌را فراموش نکنید،‌آنها معمولا از Cmd استفاده می‌کند. پس بهتر این است که if (e.metaKey || e.ctrlKey) چک شود.
  • مختصات مربوط به پنجره: clientX/clientY.

  • مختصاب مربوط به سند: pageX/pageY.

رفتار پیشفرض مروگر در هنگام mousedown انتخاب متن است. اگر این برای رابط کاربری شما مناسب نیست، پس باید از آن جلوگیری شود.

در بخش بعدی ما با جزئیات بیشتری درباره رویدادهایی که حرکت اشاره‌گر موس‌را دنبال می‌کنند، و همچنین با چگونگی شناسایی تغییرات عنصر زیر آن‌ آشنا خواهیم شد.

تمارین

اهمیت: 5

یک لیست بسازید که عناصر آن قابل انتخاب باشند، مانند اپلیکیشن‌های مدیریت فایل.

  • کلیک روی عنصر لیست فقط آن عنصر را انتخاب می‌کند. (کلاس .selected را اضافه کند)، بقیه عناصر باید لغو انتخاب شوند.
  • اگر که کلیک همراه با Ctrl (Cmd برای مک) باشد، پس عمل انتخاب یا لغو انتخاب فقط برای آن عنصر عمل کند، درحالی که بقیه عنصرها تغییری نکنند.

دمو:

پی‌نوشت: برای این تکلیف می‌توانیم در نظر بگیریم که آیتم‌های داخل لیست فقط متن هستند، و نه تگ‌های تو در تو.

پی‌نوشت: از رفتار پیش‌فرض مرورگر که باعث انتخاب متن هنگام کلیک کردن می‌شود جلوگیری کنید.

باز کردن یک sandbox برای تمرین.

نقشه آموزش