جافا سكريبت حدث عندما يترك الماوس نافذة المتصفح [مكررة

StackOverflow https://stackoverflow.com/questions/1672142

سؤال

هذا السؤال لديه بالفعل إجابة هنا:

أرغب في تشغيل بعض رمز JavaScript عندما يترك الماوس نافذة المتصفح. أحتاج فقط لدعم Safari (WebKit.)

حاولت وضع معالج ماوس في النافذة. يتم استدعاء هذا المعالج بشكل موثوق عندما يترك الماوس نافذة المتصفح. ولكن بسبب الفقاعات، يطلق عليه أيضا عندما يتحرك الماوس بين العناصر في المستند. لا أستطيع معرفة كيفية تحديد متى غادر الماوس في الواقع النافذة وعندما انتقلت فقط بين العناصر.

عندما يترك الماوس النافذة، يتم إنشاء حدث واحد بالضبط، ويبدو أن العنصر المستهدف هو العنصر الذي كان فيه الفأر بالفعل. لذا التحقق لمعرفة ما إذا كان العنصر المستهدف نافذة أو مستند لا يعمل. وانفصل الصفحة بأكملها في div غير مرئية لا تعمل إما: إذا كان div غير مرئي، فلن يكون الماوس أبدا، لذلك لا شيء يتغير.

(يحدث نفس الشيء إذا وضعت المعالج في المستند أو المستند .body، إلا أن المستند بشكل مدهش. لا يحصل Gody على أحداث Mouseover / Mouseout عندما يدخل الماوس أو يترك جزءا فارغا من النافذة، مثل المساحة الرأسية الفارغة التي تم إنشاؤها من خلال وضع عنصر مع أسفل: 0. بالنسبة لهذا المساحة، ستحصل المستند والنافذة على أحداث MouseOver / Mouseout مع الهدفu003Chtml> ، ولكن الوثيقة.body لن.)

بعض الأفكار التي كان لدي:

  • في كل حدث ماوس، احصل على الموضع الفعلي للماوس ومعرفة ما إذا كان في الواقع عبر النافذة. لكنني لا أعرف ما إذا كان هذا ممكن في الواقع، يبدو أنه سيكون صعبا للقضاء على جميع ظروف السباق.
  • قم أيضا بتسجيل معالج MouseOver واكتشف الحالات التي لا يتم فيها المتابعة Mouseout بواسطة (أو متابعها قريبا بواسطة) Mouseover. ولكن هذا سيتطلب توقيت.

نحن نستخدم prototype.js من الناحية المثالية، أود أن أعرب عن الحل من حيث حدث النموذج الأولي .observe، ولكن يمكنني معرفة هذا الجزء.

شكرا لأي اقتراحات!

هل كانت مفيدة؟

المحلول

ملخص: يمكن القيام بذلك نظيفة عن طريق التحقق من خاصية ذات صلة أثناء حدث Mouseout. إذا كانت المهاجر غير ذات صلة ليست طفلا من المستند، فقد ترك الماوس النافذة للتو. من السهل أن نفعل نفسك، ولكن إذا كنت لا ترغب في ذلك، فإن بعض المكتبات (Mootools، النموذج الأولي في المستقبل ..) لديها وظيفة مخبوزة، والبعض الآخر (النموذج الأولي الحالي) لديه امتدادات متوفرة. على أي، يمكنك بدلا من ذلك استخدام Mouseeleave، وهو إصدار غير مقيم من Mouseout.

تفاصيل:

IE لديه أحداث تسمى Mouseenter و Mouseelive هي إصدارات غير الفقاعية من Mouseover و Mouseout. المتصفحات الأخرى لا تفعل ذلك، ولكن إذا فعلت، فإن إعداد مستمع MOUSEIVE على النافذة أو المستند سيفعل الخدعة.

رجل نبيل يدعى كين سنايدر يأتي إلى الإنقاذ:

على Mouseover، تشير خاصية ذات الصلة إلى العقدة التي جاء بها المؤشر. في Mouseout، تتم مراجعة خاصية ذات صلة العقدة التي وضعها المؤشر إليها. النطاق هو العقدة التي يتم إرفاقها بها الحدث. عندما تكون القيمة ذات الصلة ليست طفلا غير جارية، فإن حدث الماوس يعادل حدث Mouseenter وحدث Mouseout يعادل حدث Mouseeave.

-- http://kendsnyder.com/archives/6-mouseenter-and-mouseleave.html.

هذا يجعل من الممكن تنفيذ Mouseenter و Mouseelive في متصفحات أخرى. في الواقع، يوفر كين رمز النموذج الأولي نفسه للقيام بذلك: http://kendsnyder.com/sandbox/enterleave/mouseenterleave.js.

وأشار دوروت في تعليقات أن Mootools تشمل بالفعل شيئا مشابها. (شكرا Duroth.) يبدو وكأنه إصدار النموذج الأولي القادم (1.6.2) قد يتضمن هذه الوظيفة، لكن لا يمكنني العثور على أي شيء محدد.

نصائح أخرى

باستخدام JavaScript فقط، لا النموذج الأولي أو jquery الخ

<html>
<head>
<script type="text/javascript">
  var mouseX = 0;
  var mouseY = 0;
  var counter = 0;
var mouseIsIn = true;
function wireEvent() {
window.addEventListener("mouseout",
    function(e){
        mouseX = e.pageX;
        mouseY = e.pageY;
        if ((mouseY >= 0 && mouseY <= window.innerHeight)
        && (mouseX >= 0 && mouseX <= window.innerWidth))
            return;
        //do something for mouse out
        counter++;
        mouseIsIn = false;
        document.getElementById('in_out').innerHTML='out' + counter;
    },
    false);
window.addEventListener("mouseover",
    function(e){
        if(mouseIsIn)
            return;
        //do something for mouse over
        counter++;
        mouseIsIn = true;
        document.getElementById('in_out').innerHTML='in' + counter;
    },
    false);
}
</script> 
</head>
<body onload="wireEvent();">
<div id="in_out">&nbsp;</div>
<div style="width:300px; height: 200px; background: red;">Dummy element</div>
</body>
</html>

تحديث:
إضافة التحقق من موقف الماوس على mouseout الناتجة عند التحرك في / خارج العناصر داخل الجسم. إذا كان داخل النافذة، mouseout لا يتم تشغيل الحدث.
قدم أيضا علم للحصول على الوضع الحالي للماوس "في" أو "خارج" mouseIsIn. وبعد اذا كانت true, mouseover لن يؤدي أيضا.

ربما يمكنك تعيين مستمع ل Mouseover و Mouseout document, body أو بعض العنصر الآخر الذي يلف المستند بأكمله واستخدام ذلك (عن طريق حفظ أنه حدث ذلك) كعدرة لتحديد ما إذا كان نافذة ماوس صالح في النافذة؟

الفشل في ذلك، يجب أن تعمل الفكرة الأولى الخاصة بك (فيما يتعلق بفحص الموضع) جيدا. أي حدث يمر على طول X / Y حدث الحدث. إذا كان أي شيء أبعد من الارتفاع / عرض النافذة، فقد تركت النافذة الفعلية. إذا كان الأمر سلبيا أي شيء، فقد تركت النافذة. وربما، إذا كان الأمر بالضبط الطول / العرض أو أعلى بالضبط: 0 أو اليسار: 0، ثم تركت النافذة.

عندما يترك الماوس أي عنصر، بما في ذلك النافذة، فإن كائن النافذة سوف يطلق mouseout الحدث وتمرير event كائن جنبا إلى جنب معها.

واحد من العناصر في كائن الحدث يسمى toElement, ، وهو مؤشر العنصر الذي دخل فيه الماوس فقط عند تركه القديم. ولكن عندما يترك الماوس النافذة، لا يوجد مثل toElement لذلك يصبح هذا البند null.

عن طريق اختبار ما إذا كان هذا البند هو أم لا null على mouseout الحدث، يمكنك معرفة ما إذا كان الماوس ترك النافذة. هنا هو الرمز:

window.onmouseout=function(event){ 
  if(event.toElement===null) console.log('the mouse left the window'); 
}

مشكلتك تأتي من أحداث Mouseout التي يتم إنشاؤها للعناصر داخل النافذة، والذي ثم الفقاعة كما هو موضح في W3C الأحداث المواصفات. وبعد يمكنك التحقق من العنصر الذي تم إطلاقه في الواقع

function mouseoutFunction(event) {
  event = event || window.event;
  var sender = event.srcElement || event.target;
}

هنا الحل الخاص بي بناء على الموقت. يستخدم الموقت هنا أساسا لإعطاء فرصة لمعالجات الأحداث الأخرى (على وجه التحديد، في وقت محدد) للتنفيذ قبل أن تقرر أن Mosue خارج النافذة. إن مهلة 1ms (في الواقع حوالي 33 مللي ثانية، يوجد دقة مؤقتة كحد أدنى) يعطي القليل من الوقت لحدوث الماوس إذا لم يكن ذلك بالفعل.

var inWin=0;
window.onmouseout = function(e)
{
   inWin--;
   setTimeout(checkIfOut, 1);
}
window.onmouseover = function(e)
{
   inWin++;
}

function checkIfOut()
{
   if(!inWin)
   {
     //Yay! Mouse is out of the window (probably)
   }
}

يمكنك استخدام onmouseout الحدث على نافذة بدلا من ذلك

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top