jQuery والتعامل مع DOM

تأثيرات الانزلاق

12 دقيقة الدرس 24 من 30

مقدمة إلى تأثيرات الانزلاق

تخلق تأثيرات الانزلاق رسومًا متحركة عمودية سلسة مثالية للأكورديونات والقوائم المنسدلة واللوحات القابلة للتوسيع والمحتوى القابل للطي. توفر jQuery ثلاث طرق رئيسية للانزلاق تحرك ارتفاع العنصر.

دالة slideDown()

تكشف دالة slideDown() العناصر المخفية عن طريق تحريك ارتفاعها من 0 إلى الحجم الكامل.

الصياغة الأساسية:
<div id="panel" style="display: none;">
    <p>سينزلق هذا المحتوى للأسفل</p>
</div>
<button id="slideDownBtn">انزلاق للأسفل</button>

<script>
$(document).ready(function() {
    $("#slideDownBtn").click(function() {
        $("#panel").slideDown(); // افتراضي: 400 ميلي ثانية
    });
});
</script>
مع المدة والاستدعاء:
// مدة مخصصة
$("#panel").slideDown(1000);

// استخدام الكلمات المفتاحية
$("#panel").slideDown("slow"); // 600 ميلي ثانية
$("#panel").slideDown("fast"); // 200 ميلي ثانية

// مع دالة استدعاء
$("#panel").slideDown(500, function() {
    alert("اللوحة مرئية الآن!");
});

دالة slideUp()

تخفي دالة slideUp() العناصر المرئية عن طريق تحريك ارتفاعها من الحجم الكامل إلى 0.

أمثلة:
<button id="slideUpBtn">انزلاق للأعلى</button>

<script>
$("#slideUpBtn").click(function() {
    $("#panel").slideUp(600);
});

// انزلاق للأعلى مع استدعاء
$("#panel").slideUp(400, function() {
    console.log("تم إخفاء اللوحة");
});

// انزلاق عناصر متعددة للأعلى
$(".collapsible-section").slideUp("slow");
</script>

دالة slideToggle()

تتبدل دالة slideToggle() بذكاء بين slideDown() و slideUp() بناءً على حالة العنصر الحالية.

مثال على التبديل:
<button id="toggleBtn">تبديل اللوحة</button>
<div id="panel">
    <p>انقر فوق الزر لتبديل هذه اللوحة</p>
</div>

<script>
$(document).ready(function() {
    $("#toggleBtn").click(function() {
        $("#panel").slideToggle(500);
    });
});
</script>
💡 نصيحة: تأثيرات الانزلاق مثالية للرسوم المتحركة العمودية. بالنسبة للرسوم المتحركة الأفقية، استخدم animate() مع خصائص العرض (سيتم تغطيتها في الدرس التالي).

مثال عملي: قائمة أكورديون

الأكورديونات هي لوحات محتوى قابلة للطي حيث يكون قسم واحد فقط مفتوحًا في وقت واحد.

<style>
.accordion {
    max-width: 600px;
    margin: 20px auto;
}
.accordion-header {
    background: var(--primary);
    color: white;
    padding: 15px;
    cursor: pointer;
    border: none;
    width: 100%;
    text-align: right;
    font-size: 16px;
    margin-top: 5px;
    transition: background 0.3s;
}
.accordion-header:hover {
    background: var(--primary-light);
}
.accordion-header.active {
    background: var(--primary-light);
}
.accordion-content {
    display: none;
    padding: 15px;
    background: var(--bg-light);
    border: 1px solid var(--border-light);
}
</style>

<div class="accordion">
    <button class="accordion-header">القسم 1</button>
    <div class="accordion-content">
        <p>محتوى القسم 1</p>
    </div>

    <button class="accordion-header">القسم 2</button>
    <div class="accordion-content">
        <p>محتوى القسم 2</p>
    </div>

    <button class="accordion-header">القسم 3</button>
    <div class="accordion-content">
        <p>محتوى القسم 3</p>
    </div>
</div>

<script>
$(document).ready(function() {
    $(".accordion-header").click(function() {
        // إغلاق جميع الأقسام الأخرى
        $(".accordion-content").not($(this).next()).slideUp(300);
        $(".accordion-header").not($(this)).removeClass("active");

        // تبديل القسم الحالي
        $(this).next().slideToggle(300);
        $(this).toggleClass("active");
    });
});
</script>

تطبيق قائمة منسدلة

أنشئ قوائم منسدلة تفاعلية مع رسوم متحركة انزلاق سلسة.

<style>
.menu {
    list-style: none;
    padding: 0;
    margin: 0;
    background: var(--primary);
}
.menu li {
    position: relative;
    display: inline-block;
}
.menu a {
    display: block;
    padding: 15px 20px;
    color: white;
    text-decoration: none;
}
.submenu {
    display: none;
    position: absolute;
    top: 100%;
    right: 0;
    min-width: 200px;
    background: var(--primary-light);
    list-style: none;
    padding: 0;
    margin: 0;
}
.submenu li {
    display: block;
}
</style>

<ul class="menu">
    <li>
        <a href="#">الرئيسية</a>
    </li>
    <li class="has-submenu">
        <a href="#">المنتجات</a>
        <ul class="submenu">
            <li><a href="#">تصميم الويب</a></li>
            <li><a href="#">التطوير</a></li>
            <li><a href="#">الاستشارات</a></li>
        </ul>
    </li>
    <li>
        <a href="#">اتصل بنا</a>
    </li>
</ul>

<script>
$(document).ready(function() {
    $(".has-submenu").hover(
        function() {
            $(this).find(".submenu").stop(true, true).slideDown(200);
        },
        function() {
            $(this).find(".submenu").stop(true, true).slideUp(200);
        }
    );
});
</script>
⚠️ تحذير: استخدم دائمًا stop(true, true) قبل رسوم الانزلاق المتحركة في أحداث التمرير لمنع تراكم قائمة انتظار الرسوم المتحركة عندما يحرك المستخدمون الماوس بسرعة.

قسم الأسئلة الشائعة مع الانزلاق

أنشئ قسم أسئلة شائعة تفاعلي حيث يمكن للمستخدمين توسيع الأسئلة وطيها.

<style>
.faq-item {
    margin-bottom: 10px;
    border: 1px solid var(--border-light);
    border-radius: 5px;
    overflow: hidden;
}
.faq-question {
    background: var(--bg-light);
    padding: 15px;
    cursor: pointer;
    font-weight: bold;
    position: relative;
    transition: background 0.3s;
}
.faq-question:hover {
    background: var(--primary-light);
}
.faq-question:after {
    content: "+";
    position: absolute;
    left: 15px;
    font-size: 24px;
    transition: transform 0.3s;
}
.faq-question.active:after {
    content: "−";
}
.faq-answer {
    display: none;
    padding: 15px;
    background: white;
}
</style>

<div class="faq">
    <div class="faq-item">
        <div class="faq-question">ما هي jQuery؟</div>
        <div class="faq-answer">
            <p>jQuery هي مكتبة JavaScript سريعة وصغيرة وغنية بالميزات.</p>
        </div>
    </div>

    <div class="faq-item">
        <div class="faq-question">لماذا نستخدم jQuery؟</div>
        <div class="faq-answer">
            <p>تبسط jQuery التنقل في مستندات HTML ومعالجة الأحداث وAjax.</p>
        </div>
    </div>

    <div class="faq-item">
        <div class="faq-question">هل jQuery لا تزال ذات صلة؟</div>
        <div class="faq-answer">
            <p>نعم، لا تزال jQuery تُستخدم على نطاق واسع في العديد من مواقع الإنتاج.</p>
        </div>
    </div>
</div>

<script>
$(document).ready(function() {
    $(".faq-question").click(function() {
        // تبديل الإجابة
        $(this).next(".faq-answer").slideToggle(300);

        // تبديل الفئة النشطة
        $(this).toggleClass("active");
    });
});
</script>

بطاقات منتجات قابلة للتوسيع

أنشئ بطاقات منتجات مع أقسام تفاصيل قابلة للتوسيع.

<style>
.product-card {
    width: 300px;
    border: 1px solid var(--border-light);
    border-radius: 8px;
    overflow: hidden;
    margin: 20px;
}
.product-image {
    width: 100%;
    height: 200px;
    object-fit: cover;
}
.product-info {
    padding: 15px;
}
.product-title {
    font-size: 18px;
    font-weight: bold;
    margin-bottom: 10px;
}
.product-price {
    color: var(--primary);
    font-size: 20px;
    font-weight: bold;
}
.product-details {
    display: none;
    padding: 15px;
    background: var(--bg-light);
    border-top: 1px solid var(--border-light);
}
.toggle-details {
    width: 100%;
    padding: 10px;
    background: var(--primary);
    color: white;
    border: none;
    cursor: pointer;
    transition: background 0.3s;
}
.toggle-details:hover {
    background: var(--primary-light);
}
</style>

<div class="product-card">
    <img src="product.jpg" alt="منتج" class="product-image">
    <div class="product-info">
        <h3 class="product-title">منتج مميز</h3>
        <p class="product-price">99.99 دولار</p>
        <button class="toggle-details">عرض التفاصيل</button>
    </div>
    <div class="product-details">
        <h4>المواصفات</h4>
        <ul>
            <li>المادة: فولاذ فاخر</li>
            <li>الوزن: 500 جرام</li>
            <li>الضمان: سنتان</li>
        </ul>
    </div>
</div>

<script>
$(document).ready(function() {
    $(".toggle-details").click(function() {
        var details = $(this).closest(".product-card").find(".product-details");
        details.slideToggle(400);

        // تحديث نص الزر
        if (details.is(":visible")) {
            $(this).text("إخفاء التفاصيل");
        } else {
            $(this).text("عرض التفاصيل");
        }
    });
});
</script>
💡 نصيحة: استخدم is(":visible") للتحقق مما إذا كان العنصر مرئيًا حاليًا، وهو مفيد لتحديث نص الزر أو الأيقونات ديناميكيًا.

الجمع بين تأثيرات انزلاق متعددة

أنشئ تفاعلات معقدة من خلال الجمع بين الانزلاق والتأثيرات الأخرى.

// انزلاق وتلاشي في نفس الوقت
$("#panel").slideDown(500).fadeTo(500, 0.8);

// رسوم متحركة متسلسلة
$("#panel").slideDown(300, function() {
    $("#message").slideDown(300);
});

// انزلاق مع تغيير النص
$("#panel").slideToggle(400, function() {
    if ($(this).is(":visible")) {
        $("#status").text("اللوحة مفتوحة");
    } else {
        $("#status").text("اللوحة مغلقة");
    }
});

📝 تمرين: لوحة تصفية جانبية

المهمة: أنشئ شريطًا جانبيًا قابلًا للطي لموقع تجارة إلكترونية يقوم بـ:

  1. وجود فئات تصفية متعددة (السعر، العلامة التجارية، التقييم، اللون)
  2. يمكن توسيع/طي كل فئة بشكل مستقل
  3. استخدام slideToggle للرسوم المتحركة السلسة
  4. إظهار أيقونة "+" عند الطي، "−" عند التوسيع
  5. وجود زر "مسح جميع الفلاتر" يطوي جميع الأقسام
  6. تذكر آخر فئة تم فتحها

تحدي إضافي: أضف تبديلًا متجاوبًا للجوال ينزلق الشريط الجانبي بأكمله من الجانب الأيسر للشاشة.

اعتبارات الأداء

  • استخدم دائمًا stop() قبل الانزلاق في أحداث التمرير
  • تجنب تحريك عناصر كثيرة جدًا في نفس الوقت
  • استخدم مدد مناسبة (200-600 ميلي ثانية لمعظم الحالات)
  • فكر في استخدام انتقالات CSS للإظهار/الإخفاء البسيط عند الإمكان
  • اختبر على الأجهزة المحمولة حيث يمكن أن تكون الرسوم المتحركة أبطأ

الملخص

  • slideDown() - يكشف العناصر بالرسوم المتحركة العمودية
  • slideUp() - يخفي العناصر بالرسوم المتحركة العمودية
  • slideToggle() - يتبدل بين slideDown و slideUp
  • مثالي للأكورديونات والقوائم المنسدلة والمحتوى القابل للطي
  • استخدم دائمًا stop(true, true) في أحداث التمرير
  • اجمع مع دوال الاستدعاء للرسوم المتحركة المتسلسلة أو المعقدة
  • المدة الافتراضية 400 ميلي ثانية؛ يمكن استخدام "slow" أو "fast" أو ميلي ثانية مخصصة