كنت أرغب في الأصل في إنشاء تأثير تلميحات الأدوات الذي يجمع بين تحديد الموضع العائم ومتابعة الماوس، لكنني وجدت أن تحديد الموضع وتتبع الماوس لا يزالان مختلفين في بعض الأماكن الرئيسية، لذا يجب أن نفعل ذلك بشكل منفصل.
هذا التأثير في حد ذاته ليس صعبًا للغاية. لقد بذلنا بعض الجهد بشكل أساسي في بنية البرنامج وتوسيعه لجعله أكثر ملاءمة للاستخدام ويمكن استخدامه في أماكن أكثر.
مميزات البرنامج
تنزيل المثال الكامل (انقر للتنزيل)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
<html xmlns=" http://www.w3.org/1999/xhtml ">
<الرأس>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>تأثير موجه تحديد المواقع العائمة لجافا سكريبت</title>
<النص البرمجي>
فار $$ = الوظيفة (المعرف) {
إرجاع "سلسلة" == معرف نوع document.getElementById(id): id;
};
var isIE = navigator.userAgent.indexOf('MSIE')!= -1;
var isIE6 = isIE && ([/MSIE (d).0/i.exec(navigator.userAgent)][0][1] == "6");
var isChrome = navigator.userAgent.indexOf('Chrome')!= -1;
var isSafari = navigator.userAgent.indexOf('AppleWebKit') != -1;
// مع مدخلات من تينو زيجديل، ماتياس ميلر، دييغو بيريني
// http://dean.edwards.name/weblog/2005/10/add-event/
وظيفة addEvent(element, type, Handler) {
إذا (element.addEventListener) {
element.addEventListener(type, Handler, false);
} آخر {
if (!handler.$$guid) Handler.$$guid = addEvent.guid++;
إذا (!element.events) element.events = {};
معالجات var = element.events[type];
إذا (! معالجات) {
معالجات = element.events[type] = {};
إذا (العنصر ["on" + النوع]) {
Handlers[0] = element["on" + type];
}
}
Handlers[handler.$$guid] = Handler;
element["on" + type] = HandleEvent;
}
};
addEvent.guid = 1;
وظيفة إزالة الحدث (العنصر، النوع، المعالج) {
إذا (element.removeEventListener) {
element.removeEventListener(type, Handler, false);
} آخر {
إذا (element.events && element.events[type]) {
حذف element.events[type][handler.$$guid];
}
}
};
دالة HandleEvent(event) {
var returnValue = true;
حدث = حدث ||.fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
معالجات var = this.events[event.type];
لـ (var i في المعالجات) {
this.$$handleEvent = Handlers[i];
إذا (this.$$handleEvent(event) === false) {
returnValue = false;
}
}
إرجاع قيمة الإرجاع؛
};
وظيفة إصلاح الحدث (الحدث) {
event.target=event.srcElement;
إذا (event.type == "mouseout") {
this.event.dependentTarget =event.toElement;
}else if(event.type == "mouseover") {
this.event.dependentTarget = events.fromElement;
}
حدث العودة؛
};
فار تمديد = وظيفة(الوجهة، المصدر) {
لـ (خاصية var في المصدر) {
الوجهة[الخاصية] = المصدر[الخاصية];
}
وجهة العودة؛
}
فار يحتوي على = وظيفة(أ، ب){
return a.contains ?
}
فار بيند = وظيفة(كائن، متعة) {
var args = Array.prototype.slice.call(arguments, 2);
وظيفة العودة () {
return fun.apply(object, args.concat(Array.prototype.slice.call(arguments)));
}
}
var BindAsEventListener = function(object, fun) {
var args = Array.prototype.slice.call(arguments, 2);
وظيفة الإرجاع (الحدث) {
إرجاع fun.apply(object, [event].concat(args));
}
}
فار FixedTips = function(tip, options){
this.Tip = $$(tip);//مربع المطالبة
this._trigger = null;// كائن الزناد
this._timer = null;//Timer
this._cssTip = this.Tip.style;// كود مبسط
this._onshow = false;// سجل حالة العرض الحالية
this.SetOptions(options);
// كائن تلميح العملية
this._cssTip.margin = 0;//تجنب مشاكل تحديد المواقع
this._cssTip.position = "absolute";
this._cssTip.visibility = "hidden";
this._cssTip.display = "block";
this._cssTip.zIndex = 99;
this._cssTip.left = this._cssTip.top = "-9999px";//تجنب أشرطة التمرير في العنصر النائب
// معلمات تصحيح الإزاحة
var iLeft = iTop = 0, p = this.Tip;
بينما (p.offsetParent) {
p = p.offsetParent;
};
this._offsetleft = iLeft;
this._offsettop = iTop;
// استمر في العرض عند الانتقال إلى كائن التلميح
addEvent(this.Tip, "mouseover", BindAsEventListener(this, function(e){
// إذا دخل عنصر خارجي، فهذا يعني أنه حاليًا في مرحلة تأخير الإخفاء، ثم امسح المؤقت لإلغاء الإخفاء.
this.Check(e.dependentTarget) && ClearTimeout(this._timer);
}));
// ie6 مقابض حدد
إذا (isIE6) {
this._iframe = document.createElement("<iframe style='position:absolute;filter:alpha(opacity=0);display:none;'>");
document.body.insertBefore(this._iframe, document.body.childNodes[0]);
};
// يستخدم للإخفاء بالنقر
this._fCH = BindAsEventListener(this, function(e) {
إذا (this.Check(e.target) && this.CheckHide()) {
this.ReadyHide(this._trigger.ClickHideDelay);
};
});
// يستخدم لتشغيل طريقة الإخفاء
this._fTH = BindAsEventListener(this, function(e) {
إذا (this.Check(e.dependentTarget) && this.CheckHide()) {
this.ReadyHide(this._trigger.TouchHideDelay);
};
});
};
FixedTips.prototype = {
_doc: document.documentElement,//تبسيط الكود
// تعيين الخصائص الافتراضية
خيارات الضبط: الوظيفة (خيارات) {
this.options = {// القيمة الافتراضية
ClickShow: صحيح،//ما إذا كان سيتم عرضه في وضع النقر
ClickShowDelay: false,// ما إذا كان عرض النقرة متأخرًا
ClickHide: صحيح،// ما إذا كان وضع النقر مخفيًا
ClickHideDelay: false,// ما إذا كان يجب النقر لإخفاء التأخير
TouchShow: صحيح،//ما إذا كان يتم عرض وضع المشغل
TouchShowDelay: true,// ما إذا كان سيتم تشغيل تأخير العرض
TouchHide: true,// ما إذا كان وضع التشغيل مخفيًا
TouchHideDelay: true,// ما إذا كان سيتم تشغيل تأخير الإخفاء
ShowDelay: 300,//عرض وقت التأخير
HideDelay: 300,//إخفاء وقت التأخير
محاذاة: "clientleft"،//الموضع الأفقي
vAlign: "clienttop"،//الموضع العمودي
مخصص: { يسار: 0، أعلى: 0 },// تحديد المواقع المخصصة
Percent: { left: 0, top: 0 },// تحديد موضع النسبة المئوية المخصصة
التكيف: خطأ، // سواء لتحديد المواقع على التكيف
إعادة الضبط: خطأ، // ما إذا كان سيتم تغيير الموضع أثناء تحديد الموضع التكيفي
onShow: function(){},// يتم تنفيذه عند العرض
onHide: function(){}// يتم تنفيذه عند إخفائه
};
تمديد(this.options, options || {});
},
//تحقق من عنصر الزناد
تحقق: الوظيفة (العنصر) {
// إرجاع ما إذا كان عنصرًا خارجيًا (أي كائن عنصر آخر غير عنصر التشغيل وكائن التلميح نفسه وعناصره الداخلية)
العودة !this._trigger ||
!(
this.Tip === elem ||. this._trigger.Elem === elem ||
يحتوي على (this.Tip، elem) ||. يحتوي على (this._trigger.Elem، elem)
);
},
// جاهز للعرض
عرض جاهز: وظيفة (تأخير) {
ClearTimeout(this._timer);
فار تريجر = this._trigger;
//انقر للإخفاء
Trigger.ClickHide && addEvent(document, "click", this._fCH);
// وضع الزناد مخفي
Trigger.TouchHide && addEvent(this._trigger.Elem, "mouseout", this._fTH);
// ما إذا كان سيتم تأخير التشغيل
إذا (تأخير) {
this._timer = setTimeout(Bind(this, this.Show), Trigger.ShowDelay);
} else { this.Show() };
},
//يعرض
إظهار: الوظيفة () {
ClearTimeout(this._timer);
this._trigger.onShow();// ضعه في المقدمة لتسهيل تعديل السمات
// احسب اليسار والأعلى بناءً على الموضع المحدد مسبقًا والموضع المخصص
فار الزناد = this._trigger، المستقيم = الزناد.Elem.getBoundingClientRect()،
Scrolldoc = isChrome ||.isSafari ؟ document.body : this._doc,
التمرير لليسار = التمريرdoc.scrollLeft، التمرير للأعلى = التمرير للدوك.scrollTop،
customLeft = المشغل.Custom.left، customTop = المشغل.Custom.top،
iLeft = this.GetLeft(rect, Trigger.Align) + customLeft,
iTop = this.GetTop(rect, Trigger.vAlign) + customTop;
// تحديد النسبة المئوية المخصصة
if (trigger.Percent.left) { iLeft += .01 * Trigger.Percent.left * Trigger.Elem.offsetWidth };
if (trigger.Percent.top) { iTop += .01 * Trigger.Percent.top * Trigger.Elem.offsetHeight };
// تحديد موضع النافذة التكيفي
إذا (الزناد. التكيف) {
// معلمات تحديد المواقع الصحيحة
فار maxLeft = this._doc.clientWidth - this.Tip.offsetWidth،
maxTop = this._doc.clientHeight - this.Tip.offsetHeight;
إذا (الزناد.إعادة تعيين) {
// إعادة التموضع التلقائي
إذا (iLeft > maxLeft || iLeft < 0) {
iLeft = this.GetLeft(rect, 2 * iLeft > maxLeft ? "left" : "right") + customLeft;
};
إذا (iTop > maxTop || iTop < 0) {
iTop = this.GetTop(rect, 2 * iTop > maxTop ? "top" : "bottom") + customTop;
};
} آخر {
// الصحيح في الموضع المناسب
iLeft = Math.max(Math.min(iLeft, maxLeft), 0);
iTop = Math.max(Math.min(iTop, maxTop), 0);
};
};
// تعيين الموضع والعرض
this._cssTip.left = iLeft +scrollLeft - this._offsetleft + "px";
this._cssTip.top = iTop +scrollTop - this._offsettop + "px";
this._cssTip.visibility = "visible";
// ie6 مقابض حدد
إذا (isIE6) {
this._iframe.style.left = iLeft +scrollLeft + "px";
this._iframe.style.top = iTop +scrollTop + "px";
this._iframe.style.width = this.Tip.offsetWidth + "px";
this._iframe.style.height = this.Tip.offsetHeight + "px";
this._iframe.style.display = "";
};
// وضع الزناد مخفي
Trigger.TouchHide && addEvent(this.Tip, "mouseout", this._fTH);
},
// احصل على يسار عنصر الزناد النسبي
GetLeft: وظيفة (مستقيم، محاذاة) {
التبديل (align.toLowerCase()) {
حالة "اليسار":
إرجاع rect.left - this.Tip.offsetWidth;
حالة "حق العميل":
return rect.left;
حالة "المركز":
return (rect.left + rect.right - this.Tip.offsetWidth)/2;
حالة "حق العميل":
إرجاع rect.right - this.Tip.offsetWidth;
حالة "الحق" :
تقصير :
return rect.right;
};
},
// احصل على الجزء العلوي بالنسبة لعنصر الزناد
GetTop: وظيفة (مستقيم، فالين) {
التبديل (valign.toLowerCase()) {
الحالة "الأعلى":
إرجاع rect.top - this.Tip.offsetHeight;
حالة "clienttop":
إرجاع rect.top;
حالة "المركز":
return (rect.top + rect.bottom - this.Tip.offsetHeight)/2;
حالة "clientbottom":
إرجاع rect.bottom - this.Tip.offsetHeight;
الحالة "أسفل":
تقصير :
إرجاع المستقيم. أسفل؛
};
},
// الاستعداد للاختباء
إخفاء جاهز: وظيفة (تأخير) {
ClearTimeout(this._timer);
إذا (تأخير) {
this._timer = setTimeout(Bind(this, this.Hide), this._trigger.HideDelay);
} else { this.Hide() };
},
//يخفي
إخفاء: الوظيفة () {
ClearTimeout(this._timer);
// إعداد للإخفاء
this._cssTip.visibility = "hidden";
this._cssTip.left = this._cssTip.top = "-9999px";
// ie6 مقابض حدد
if (isIE6) { this._iframe.style.display = "none" };
// كائن تشغيل العملية
إذا (!!هذا._trigger) {
this._trigger.onHide();
RemoveEvent(this._trigger.Elem, "mouseout"، this._fTH);
}
this._trigger = null;
//إزالة الحدث
RemoveEvent(this.Tip, "mouseout", this._fTH);
RemoveEvent(document, "click", this._fCH);
},
// أضف كائن الزناد
إضافة: وظيفة (عنصر، خيارات) {
// إنشاء كائن الزناد
var elem = $$(elem)، Trigger = Extend(Extend({ Elem: elem }, this.options), options || {});
//انقر للعرض
addEvent(elem, "click", BindAsEventListener(this, function(e){
إذا (trigger.ClickShow) {
إذا (this.CheckShow(trigger)) {
this.ReadyShow(trigger.ClickShowDelay);
} آخر {
ClearTimeout(this._timer);
};
};
}));
// عرض وضع الزناد
addEvent(elem, "mouseover", BindAsEventListener(this, function(e){
إذا (trigger.TouchShow) {
إذا (this.CheckShow(trigger)) {
this.ReadyShow(trigger.TouchShowDelay);
} else if (this.Check(e.dependentTarget)) {
ClearTimeout(this._timer);
};
};
}));
// إرجاع كائن الزناد
الزناد العودة.
},
//إظهار الشيك
CheckShow: الوظيفة (الزناد) {
إذا (ابدأ !== this._trigger) {
// إذا لم يكن نفس كائن التشغيل، فقم بتنفيذ الإخفاء أولاً لمنع التعارضات.
this.Hide(); this._trigger = Trigger;
} آخر { إرجاع خطأ }؛
},
// إخفاء الاختيار
التحقق من الإخفاء: الوظيفة () {
إذا (this._cssTip.visibility === "مخفي") {
// إنها في الأصل حالة مخفية، ولم تعد هناك حاجة لتنفيذ الإخفاء
ClearTimeout(this._timer);
RemoveEvent(this._trigger.Elem, "mouseout"، this._fTH);
this._trigger = null;
RemoveEvent(document, "click", this._fCH);
عودة كاذبة.
} else { إرجاع صحيح };
}
};
</script>
</الرأس>
<الجسم>
<نمط>
.trigger{border:1px Solid #003099; الخلفية:#e2e7ff;}
.تلميح{border:1px Solid #c00000; الخلفية:#ffcccc;
</نمط>
<div style="padding:50px;">
<div id="idTip" class="tip"></div>
<div id="idTrigger1" class="trigger">
<حدد>
<خيار>اختبار</option>
</حدد>
</div>
<ر>
الوضع الأفقي:
<التسمية>
<اسم الإدخال = "nAlign" type = "الراديو" القيمة = "يسار" />
اليسار </التسمية>
<التسمية>
<input name = "nAlign" type = "radio" value = "clientleft" />
يسار العميل </label>
<التسمية>
<اسم الإدخال = "nAlign" type = "راديو" value = "مركز" />
مركز </التسمية>
<التسمية>
<input name = "nAlign" type = "radio" value = "clientright" />
حق العميل </label>
<التسمية>
<اسم الإدخال = "nAlign" type = "راديو" value = "يمين" محدد = "محدد" />
حق </التسمية>
<ر>
الوضع العمودي:
<التسمية>
<اسم الإدخال = "nVAlign" نوع = "راديو" قيمة = "أعلى" />
أعلى </التسمية>
<التسمية>
<اسم الإدخال = "nVAlign" type = "راديو" value = "clienttop" />
العميل العلوي </label>
<التسمية>
<اسم الإدخال = "nVAlign" نوع = "راديو" قيمة = "مركز" />
مركز </التسمية>
<التسمية>
<input name = "nVAlign" type = "radio" value = "clientbottom" />
العميل السفلي </label>
<التسمية>
<اسم الإدخال = "nVAlign" type = "راديو" القيمة = "أسفل" محدد = "محدد" />
أسفل </التسمية>
<ر>
<ر>
الاستهداف المخصص:
غادر:
<input id = "idLeft" type = "text" size = "5" value = "0" maxlength = "3" />
قمة:
<معرف الإدخال = "idTop" نوع = "نص" حجم = "5" قيمة = "0" أقصى طول = "3"/>
<ر>
<ر>
<input id = "idClick" type = "checkbox" محدد = "محدد" />
<label for="idClick">طريقة النقر</label>
<input id = "idTouch" type = "checkbox" محدد = "محدد" />
<label for="idTouch">طريقة التشغيل</label>
<ر>
<ر>
وقت التأخير:
<معرف الإدخال = "idDelayTime" نوع = "نص" حجم = "5" قيمة = "0" أقصى طول = "4"/>
<input id = "idDelay" type = "button" value = "إلغاء التأخير" />
<ر>
<ر>
أمثلة تطبيقات أخرى: <br>
<ر>
<div id="idTest1"> استخدم العنوان: <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/11/17/1334778.html " title="تأثير السحب والإفلات"> اسحب وإسقاط التأثير</a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/12/03/1346386.html " title="تأثير السحب والتكبير"> السحب والتكبير/التصغير التأثير</a > <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/07/21/1247267.html " title="تأثير قطع الصورة"> تأثير قطع الصورة </a > </ديف >
<ر>
<ر>
تأثيرات عرض الصور الرمزية الشائعة: <br>
<ر>
<div id="idTest2"> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/07/06/1236770.html " title="تأثير تبديل انزلاق الصورة"> <img src= "/articleimg/2009/07/6852/r_mx1.jpg" border="0"/></a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/05/ 23/1205642.html " title="تأثير تحويل الصورة"><img src="/articleimg/2009/07/6852/r_mx2.jpg" border="0"/></a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/05/13/1194272.html " title="تأثير عرض الصورة المنزلق"><img src="/articleimg/2009/07/6852/r_mx3.jpg " الحدود = "0"/></a> </div>
<ر>
<ر>
زر الإغلاق: <a id="idTest3" href=" http://www.cnblogs.com/cloudgamer/archive/2009/05/18/TableFixed.html">تأثير تحديد موضع صف الجدول </a>
</div>
<النص البرمجي>
var forEach = function(array, callback, thisObject){
إذا (صفيف. لكل) {
array.forEach(callback, thisObject);
}آخر{
for (var i = 0, len = array.length; i < len; i++) { callback.call(thisObject, array[i], i, array });
}
}
////////////////////////////////////////////////////////
var ft = new FixedTips("idTip");
////////////////////////////////////////////////////////
فار Trigger1 = ft.Add("idTrigger1", {
اون شو: وظيفة () {
// اختبار تحديد المواقع
var sAlign = this.Align, sVAlign = this.vAlign;
forEach(document.getElementsByName("nAlign"), function(o){ if(o.checked){ sAlign = o.value; } });
forEach(document.getElementsByName("nVAlign"), function(o){ if(o.checked){ sVAlign = o.value; } });
this.Align = sAlign;
this.vAlign = sVAlign;
this.Custom.left = $$("idLeft").value |.
this.Custom.top = $$("idTop").value |.
Trigger1.ShowDelay = Trigger1.HideDelay = $$("idDelayTime").value 0 ||.
ft.Tip.innerHTML = sAlign + "<br>" + sVAlign + "<br>" + "left: " + this.Custom.left + "، أعلى: " + this.Custom.top؛
}
});
// اختبار التأخير
$$("idDelayTime").value = Trigger1.ShowDelay;
$$("idDelay").onclick = function(){
إذا (trigger1.TouchShowDelay){
مشغل1.ClickShowDelay = مشغل1.ClickHideDelay =
Trigger1.TouchShowDelay = Trigger1.TouchHideDelay = false;
$$("idDelayTime").disabled = true;
this.value = "ضبط التأخير";
}آخر{
مشغل1.ClickShowDelay = مشغل1.ClickHideDelay =
Trigger1.TouchShowDelay = Trigger1.TouchHideDelay = true;
$$("idDelayTime").disabled = false;
this.value = "إلغاء التأخير";
}
}
//اختبار الطريقة
$$("idClick").onclick = function(){
Trigger1.ClickShow = Trigger1.ClickHide = this.checked;
}
$$("idTouch").onclick = function(){
Trigger1.TouchShow = Trigger1.TouchHide = this.checked;
}
/////////////////////////////////////////////////////////
forEach($$("idTest1").getElementsByTagName("a"), function(o){
var title = o.title;
ft.Add(o, { vAlign: "bottom"، النسبة المئوية: { left: 50, top: 0 }, onShow: function(){ ft.Tip.innerHTML = title; } });
})
/////////////////////////////////////////////////////////
forEach($$("idTest2").getElementsByTagName("a"), function(o){
var img = o.getElementsByTagName("img")[0], title = o.title;
o.title = "";
ft.Add(img, { مخصص: { اليسار: -6, الأعلى: -6 },
اونشو: وظيفة () {
var str = '<a href="' + o.href + '"><img src="' + img.src + '" style="padding-bottom:5px;" border="0"/></ أ>';
str += '<br /><a href="' + o.href + '">' + title + '</a>';
ft.Tip.innerHTML = str;
}
});
})
/////////////////////////////////////////////////////////
ft.Add("idTest3", { ClickHide: false، TouchHide: false، محاذاة: "right"،
اونشو: وظيفة () {
var str = ' <a href=" http://www.cnblogs.com/cloudgamer/archive/2009/03/11/1408333.html "> تأثيرات التدرج اللوني والتدرج</a><br />';
str += ' <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/10/20/1314766.html "> قرص شبكة تقليد 163 لا يوجد نظام تحميل ملفات تحديث</a><br / >';
str += '<input type = "button" onclick = "ft. Hide ()؛" value = "انقر للإغلاق" />'؛
ft.Tip.innerHTML = str;
}
});
</script>
</الجسم>
</html>
جافا سكريبت، تحديد المواقع، العائمة، نصائح، تلميحات الأدوات، نصائح ثابتة، تلميح
وصف البرنامج
كائن نصيحة :
كائن التلميح عبارة عن حاوية تُستخدم لعرض المعلومات السريعة، ويتم تمثيل البرنامج بواسطة سمة التلميح. لا توجد متطلبات لذلك، سيتم إجراء بعض الإعدادات عليه عند تهيئة البرنامج.
قم أولاً بإجراء الإعدادات التالية:
this._cssTip.margin = 0;
this._cssTip.position = "absolute";
this._cssTip.visibility = "hidden";
this._cssTip.display = "block";
this._cssTip.zIndex = 99;
this._cssTip.left = this._cssTip.top = "-9999px";
تم تعيين الهامش على 0 لتجنب بعض مشاكل تحديد الموضع، ويتم استخدام الرؤية للإخفاء بدلاً من العرض لأن البرنامج يحتاج إلى الحصول على عرض الإزاحة وارتفاع الإزاحة للتلميح، كما يحتاج أيضًا إلى ضبط اليسار والأعلى لتجنب ظهور شريط التمرير بسبب الطرف الذي يحتل المساحة.
نظرًا لأن الطرف قد يكون داخل عناصر أخرى موضوعة، يجب تعيين معلمتين لتصحيح الإزاحة:
var iLeft = iTop = 0, p = this.Tip.offsetParent;
بينما (!(ع === document.body || p === document.documentElement)) {
iLeft += p.offsetLeft;
};
this._offsetleft = iLeft;
this._offsettop = iTop;
وأخيرًا، قم بإضافة حدث إلى تمرير الماوس الخاص بـ Tip، والذي سيتم شرحه لاحقًا.