شريط الإهداءات التلقائي

كود جيفري

عضو جديد
عضو انكور
شريط الإهداءات من الأفكار المحببة في المنتديات العربية، فهو يمنح الأعضاء مساحة لإرسال التحيات والرسائل القصيرة لبعضهم ويضفي جوًا اجتماعيًا دافئًا على المنتدى. هذا الكود يعرض في شريط علوي الإهداءات المرتبطة بموضوع معين، ويتيح لكل عضو وضع رسالته فيه وليس للإداريين فقط، ويمكنك تسميته "شريط الإهداءات" أو "شريط الرسائل القصيرة" أو أي اسم تفضله. ويتميز بذكاء في الفلترة، إذ يتجاهل تلقائيًا الردود القصيرة جدًا التي لا تتجاوز ثلاثة أحرف، والإهداءات التي تحتوي على ابتسامات أو صور فقط دون نص، كما يمنع ظهور الروابط والاقتباسات وأكواد البرمجة داخل الشريط.

مثال على الكود​

شريط إهداءات متحرك أعلى المنتدى يعرض رسائل الأعضاء القصيرة


شرح تركيب الكود​

يتم التركيب في أربع خطوات فقط:

1- قالب المواضيع
اذهب إلى قالب viewtopic_body وابحث عن التالي:

HTML:
{postrow.displayed.MESSAGE}

واستبدله بـ:

HTML:
<div class="post-conan">{postrow.displayed.MESSAGE}</div>

2- كود HTML
أضف كود HTML في أي مكان تريد أن يظهر فيه شريط الإهداءات، في القوالب أو في العناصر المستقلة:

HTML:
<!--  شريط الإهداءات   -->
<div class="ehdaa-box">
<!-- HTML -->
<div class="ehdaa-red"></div>          
<div class="ehdaa-black"></div>          
<div class="ehdaa-green"></div>  
<div class="ehdaa-reset"></div>
<!-- jQuery -->
<script>
  $(document).ready(function() {
    const defaultColor = '#1873c3'; 
    const savedColor = localStorage.getItem('ehdaaColor');
    if (savedColor) {
      $('.ehdaa-box').css('background', savedColor);
    } else {
      $('.ehdaa-box').css('background', defaultColor);
    }
    $('.ehdaa-red').on('click', function() {
      const color = '#951006';
      $('.ehdaa-box').css('background', color);
      localStorage.setItem('ehdaaColor', color);
    });
    $('.ehdaa-black').on('click', function() {
      const color = '#241e1d';
      $('.ehdaa-box').css('background', color);
      localStorage.setItem('ehdaaColor', color);
    });
    $('.ehdaa-green').on('click', function() {
      const color = '#3b833e';
      $('.ehdaa-box').css('background', color);
      localStorage.setItem('ehdaaColor', color);
    });
    $('.ehdaa-reset').on('click', function() {
      $('.ehdaa-box').css('background', defaultColor);
      localStorage.removeItem('ehdaaColor');
    });

  });
</script>


          
  
 <div class="ehdaa-header" style="display:flex; justify-content:space-between; align-items:center;">
                          <a class="ehdaa-title-link" href="#">شريط الإهداءات</a>                          
 <div>
                                                  
 <button style="margin-left:10px;" class="ehdaa-add-btn" id="toggleAnimation">
                      تبديل الحركة                      
 </button>
                            <a href="#" id="openReplyModal" class="ehdaa-add-btn">أضف إهداءك</a>                          
 </div>
                                              
 </div>
                                              
 <div class="ehdaa-body">
                                                
 <div id="ehdaa-content" class="ehdaa-content" style="height: 80px; overflow: hidden; position: relative;">
                                                  
 <div class="active-animation" id="ehdaa-inner" style="position:absolute; white-space:nowrap; left:0;">
                                          
 </div>
                                                  
 <div hidden="" id="ehdaa-typewriter" style="position:absolute; top:0; right:0; width: 100%; height: 30px;">
                                          
 </div>
                                                  
 <div hidden="" id="ehdaa-rise" style="position:absolute; top:0; right:0; width: 100%; height: 30px; text-align: right; font-size: 18px; font-weight: bold; color: white; line-height: 30px; padding-right: 10px; box-sizing: border-box;">
                                          
 </div>
                                                
 </div>
                                              
 </div>
</div>
                      
<!--                                   نافذة منبثقة                                   -->
<div id="replyModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.; justify-content:center; align-items:center; z-index:9999;">
                                              
 <div style="width:90%; max-width:700px; height:80%; background:#fff; border-radius:8px; position:relative; overflow:hidden; display:flex; flex-direction: column;">
                                                
 <div class="modal-header">
                      إضافة إهداء                      
 </div>
                                                
 <button id="closeReplyModal" style="position:absolute; top:10px; left:10px; background:#e74c3c; color:#fff; border:none; border-radius:50%; width:30px; height:30px; font-size:18px; cursor:pointer; z-index:10;">
                      ×                      
 </button>
                                                
 <div id="iframeContainer" style="flex:1; width:100%; height:100%; overflow:hidden;">
                                          
 </div>
                                              
 </div>
</div>
 <style>
.ehdaa-box {
  background: #1873c3;
  color: white;
  padding: 10px;
  font-family: 'Tajawal', Arial, sans-serif;
  margin: 10px auto;
  max-width: 100%;
  box-sizing: border-box;
  direction: rtl;
  border-radius: 8px;
}

#ehdaa-inner img,
#ehdaa-typewriter img,
#ehdaa-rise img {
  height: auto;
  width: auto;
  max-height: 28px;
  min-height: 20px;
  vertical-align: middle;
  margin: 0 3px;
  display: inline-block !important;
}
.ehdaa-item {
  display: inline-block; /* يجعل العنصر في سطر واحد */
  white-space: nowrap;   /* يمنع الانكسار لسطر جديد */
  vertical-align: middle;
  /* بقية التنسيق */
}
.ehdaa-red,.ehdaa-black, .ehdaa-green,.ehdaa-reset {
  cursor: pointer;
    padding: 10px;
    border-radius: 100px;
    display: inline-block;
}
.ehdaa-red {
    background: #951006;
}
.ehdaa-black {
    background: #241e1d;
}
.ehdaa-green {
    background: #3b833e;
}
.ehdaa-reset {
    background: #1873c3;
}
.ehdaa-username {
  font-weight: bold;
  margin-left: 5px;
  color: #f1c40f;
  white-space: nowrap;  /* أيضاً لمنع الانكسار */
}
div#replyModal {
    justify-content: center;
    z-index: 999999999999999999999;
}
.ehdaa-header { font-weight: bold; margin-bottom: 5px; font-size: 16px; }
.ehdaa-title-link { color: white !important; text-decoration: none !important; font-weight: bold; font-size: 16px; }
.ehdaa-title-link:hover { color: #f1c40f !important; cursor: pointer; text-decoration: underline; }
.ehdaa-add-btn { background-color: #ffffff; color: #2c3e50; padding: 5px 10px; border-radius: 4px; text-decoration: none; font-weight: bold; font-size: 14px; cursor: pointer; transition: all 0.3s; border: none; }
.ehdaa-add-btn:hover { background-color: #f1c40f; color: #fff; }
.ehdaa-content {
    border: dotted #a3a3a3 1px;
    direction: rtl;
    background: #00000054;
}
.ehdaa-item {
  display: inline-flex !important;
  align-items: center;
  white-space: nowrap;
  vertical-align: middle;
  color: white;
  padding-left: 50px;
  font-size: 18px;
  line-height: 30px;
}
div#ehdaa-inner {
    line-height: 4;
}   
.ehdaa-username {
  font-weight: bold;
  margin-left: 5px;
  color: #f1c40f;
  white-space: nowrap;
}
#ehdaa-typewriter { font-size: 18px; color: white; line-height: 30px; padding-right: 10px; padding-left: 10px; font-weight: bold; white-space: nowrap; animation: showEhdaa 1s ease; position: absolute; direction: rtl; text-align: right; right: 0; left: 0; width: 100%; }
#ehdaa-rise { position: absolute; top: 0; right: 0; width: 100%; height: 30px; color: white; font-size: 18px; font-weight: bold; line-height: 30px; padding-right: 10px; direction: rtl; text-align: right; }
@keyframes showEhdaa { 0% { opacity: 0; transform: translateY(-10px) scale(0.95); } 100% { opacity: 1; transform: translateY(0) scale(1); } }
.modal-header { text-align: right; font-size: 24px; font-weight: bold; color: #000; padding: 15px 20px; border-bottom: 1px solid #ddd; user-select: none; }
</style>

3- كود الجافا سكريبت
أضف كود الجافا في جميع الصفحات:

JavaScript:
$(function () {  
  const topicId = yyyyy; 
$(function () {
  const firstPageUrl = `/t${topicId}-topic`;

  $.get(firstPageUrl, function (html) {
    const doc = new DOMParser().parseFromString(html, "text/html");
    const pageLinks = $(doc).find("a[href*='-topic'][href*='p']");
    let maxPage = 1;
    pageLinks.each(function () {
      const href = $(this).attr("href");
      const match = href.match(/p(\d+)-topic/);
      if (match) {
        const pageNum = parseInt(match[1]);
        if (pageNum > maxPage) maxPage = pageNum;
      }
    });

    const allMessages = [];

    function fetchPage(pageNum, callback) {
      const url = pageNum === 1 ? firstPageUrl : `/t${topicId}p${pageNum}-topic`;
      $.get(url, function (pageHtml) {
        const pageDoc = new DOMParser().parseFromString(pageHtml, "text/html");
        const posts = $(pageDoc).find(".post, .post-wrap, table.tborder").get();

        posts.forEach((post, index) => {
          // تخطي أول رد فقط في الصفحة الأولى
          if (pageNum === 1 && index === 0) return;

          const $post = $(post);
          let username = "عضو مجهول";

          const nameEl = $post.find(".name strong").first();
          if (nameEl.length && nameEl.text().trim()) {
            username = nameEl.text().trim();
          } else {
            const selectors = [
              "span.post-author-name", ".username", ".postprofile strong", ".postprofile dt", ".post-author",
              ".author", ".poster", ".user-basic-info strong", ".post-header .author a", ".post-header .user a"
            ];
            for (const sel of selectors) {
              const el = $post.find(sel).first();
              if (el.length && el.text().trim()) {
                username = el.text().trim();
                break;
              }
            }
          }

          let message = "";
          let body = $post.find(".postbody").first();
          if (!body.length) body = $post;

          // إزالة التوقيع إن وجد
          body.find(".signature, .sig, .user-signature, .post-signature, .signature_div, .post-signature-container, .siggy").remove();

          // هنا نأخذ المحتوى كاملاً مع الوسوم (html) للسماح بعرض صور الابتسامات
          const contentSelectors = [".post-conan"];
          for (const sel of contentSelectors) {
            const el = body.find(sel).first();
            if (el.length && el.html().trim().length > 5) {
              message = el.html().trim();
              break;
            }
          }

         // تنظيف نص الرسالة من بعض العبارات غير المرغوبة، نستخدم هنا نسخة النص فقط
            let plainMessage = $("<div>").html(message).text();
            plainMessage = plainMessage
            .replace(/^رد\s*:\s*/i, "")
  .replace(/\d{1,2}\/\d{1,2}\/\d{2,4}/g, "")
  .replace(/\d{1,2}:\d{2}(:\d{2})?/g, "")
  .replace(/من طرف.*$/i, "")
  .replace(/Postado/gi, "")
  .replace(/اليوم في/gi, "")
  .replace(/أمس في/gi, "")
  .replace(/AM|PM|Today|Yesterday/gi, "")
  .replace(/عدل\s+سابقا\s+من\s+قبل.*?(\n|$)/gi, "")
  .trim();

          const forbidden = [
            "تستطيع إضافة مواضيع",
            "تستطيع الرد",
            "تستطيع إرفاق ملفات",
            "تستطيع تعديل مشاركات",
            "تذكير بمساهمة فاتح الموضوع",
            "تم تحرير هذا الرد",
            "مساهمة ادارية",
            "هذا الموضوع يحتوي على",
            "إشراف المنتدى"
          ];

          if (
            plainMessage.length > 5 &&
            username !== "عضو مجهول" &&
            !forbidden.some(p => plainMessage.includes(p))
          ) {
            if (plainMessage.length > 150) plainMessage = plainMessage.slice(0, 150).trim() + "…";
            // احتفظ بالمحتوى HTML الأصلي (message) للعرض مع صور الابتسامات
            allMessages.push({ username, message, plainMessage });
          }
        });

        callback();
      });
    }

    let currentPage = 1;
    function fetchAllPages() {
      if (currentPage > maxPage) {
        // إزالة التكرارات بناءً على (username + plainMessage)
        const uniqueMessages = [];
        const seen = new Set();

        for (const item of allMessages.reverse()) {
          const key = item.username + "::" + item.plainMessage;
          if (!seen.has(key)) {
            seen.add(key);
            uniqueMessages.push(item);
          }
        }

        renderEhdaas(uniqueMessages.slice(0, 5)); // عرض آخر 5 فريدة فقط
        return;
      }
      fetchPage(currentPage, function () {
        currentPage++;
        fetchAllPages();
      });
    }

    fetchAllPages();

    function renderEhdaas(messages) {
      if (!messages.length) {
        $("#ehdaa-content").text("لا توجد إهداءات بعد.");
        return;
      }

      // إزالة تكرار اسم العضو في بداية الرسالة إذا كان موجود
      messages.forEach(item => {
        const prefix1 = item.username + ": ";
        const prefix2 = item.username + " : ";
        let tempMsg = item.message;
        // نص بسيط بدون HTML لفحص البداية
        const tempMsgText = $("<div>").html(tempMsg).text();
        if (tempMsgText.startsWith(prefix1)) {
          // حذف اسم العضو من بداية النص فقط (HTML معقد؟ هنا نزيل فقط النص من البداية)
          const regex = new RegExp("^" + prefix1.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
          tempMsg = tempMsg.replace(regex, "");
        } else if (tempMsgText.startsWith(prefix2)) {
          const regex = new RegExp("^" + prefix2.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
          tempMsg = tempMsg.replace(regex, "");
        }
        item.message = tempMsg.trim();
      });

      const $container = $("#ehdaa-inner");
      const $typewriter = $("#ehdaa-typewriter");
      const $rise = $("#ehdaa-rise");
      const $content = $("#ehdaa-content");

      $container.html(messages.map(item =>
        `<span class="ehdaa-item" title="${$("<div>").text(item.username + ": " + item.plainMessage).html()}">
           <span class="ehdaa-username">${item.username}:</span> ${item.message}
         </span>`
      ).join(""));

      let pos = -$container.outerWidth();
      const viewportWidth = $content.outerWidth();
      let scrolling = true;

      function scroll() {
        if (scrolling) {
          pos++;
          if (pos > viewportWidth) {
            pos = -$container.outerWidth();
          }
          $container.css("left", pos + "px");
        }
        requestAnimationFrame(scroll);
      }

      $container.css("left", pos + "px");

      let currentIndexType = 0;
      let typeWriterTimeout;

      function typeWriter(text, element, delay, callback) {
        let i = 0;
        function typing() {
          if (i <= text.length) {
            element.html(text.slice(0, i));
            i++;
            typeWriterTimeout = setTimeout(typing, delay);
          } else if (callback) {
            typeWriterTimeout = setTimeout(callback, 2500);
          }
        }
        typing();
      }

      function stopTypeWriter() {
        clearTimeout(typeWriterTimeout);
      }

      function showNextType() {
        const item = messages[currentIndexType];
        const fullText = `<span class="ehdaa-username">${item.username}:</span> ${item.message}`;
        const newItem = $('<div class="ehdaa-item"></div>');
        $typewriter.html(newItem);
        typeWriter(fullText, newItem, 100, function () {
          currentIndexType = (currentIndexType + 1) % messages.length;
          showNextType();
        });
      }

      let currentIndexRise = 0;
      let riseTimeout;

      function showNextRise() {
        const item = messages[currentIndexRise];
        const fullText = `<span class="ehdaa-username">${item.username}:</span> ${item.message}`;
        $rise.html(fullText);
        $rise.css({ opacity: 1, top: '30px' });
        $rise.animate({ top: '0px', opacity: 1 }, 800, 'swing', () => {
          riseTimeout = setTimeout(() => {
            $rise.animate({ top: '-30px', opacity: 0 }, 800, 'swing', () => {
              currentIndexRise = (currentIndexRise + 1) % messages.length;
              showNextRise();
            });
          }, 2500);
        });
      }

      function stopRise() {
        clearTimeout(riseTimeout);
        $rise.stop(true, true);
      }

      let savedAnimation = localStorage.getItem('ehdaa-currentAnimation');
      let currentAnimation = savedAnimation ? parseInt(savedAnimation, 10) : 1;

      function activateAnimation(animationNum) {
        if (animationNum === 1) {
          scrolling = true;
          $container.show().addClass("active-animation");
          $typewriter.hide().html('');
          stopTypeWriter();
          $rise.hide().html('');
          stopRise();
          pos = -$container.outerWidth();
          scroll();
        } else if (animationNum === 2) {
          scrolling = false;
          $container.hide().removeClass("active-animation");
          $rise.hide().html('');
          stopRise();
          $typewriter.show();
          currentIndexType = 0;
          showNextType();
        } else if (animationNum === 3) {
          scrolling = false;
          $container.hide().removeClass("active-animation");
          $typewriter.hide().html('');
          stopTypeWriter();
          $rise.show();
          currentIndexRise = 0;
          showNextRise();
        }
      }

      activateAnimation(currentAnimation);

      $("#toggleAnimation").on("click", function () {
        currentAnimation++;
        if (currentAnimation > 3) currentAnimation = 1;
        localStorage.setItem('ehdaa-currentAnimation', currentAnimation);
        activateAnimation(currentAnimation);
      });

      $content
        .on("mouseenter", () => scrolling = false)
        .on("mouseleave", () => scrolling = true);
    }
  });

  $('.ehdaa-title-link').attr('href', `/t${topicId}-topic`);
  $('#openReplyModal').on('click', function (e) {
    e.preventDefault();
    const iframe = document.createElement('iframe');
    iframe.src = `/post?mode=reply&t=${topicId}`;
    iframe.frameBorder = "0";
    iframe.style.width = "100%";
    iframe.style.height = "100%";
    $('#iframeContainer').html(iframe);
    $('#replyModal').css('display', 'flex');
  });

  $('#closeReplyModal').on('click', function () {
    $('#replyModal').hide();
  });

  $('#replyModal').on('click', function (e) {
    if (e.target === this) $(this).hide();
  });
});
});

4- ربط الشريط بموضوع الإهداءات
لاحظ وجود القيمة yyyyy في كود الجافا. أنشئ موضوعًا جديدًا بعنوان مثل "موضوع الإهداءات"، ثم انسخ رقم الموضوع من الرابط وضعه مكان yyyyy في الكود.

مكان رقم الموضوع في رابط المتصفح لاستخدامه في كود شريط الإهداءات


إضافة اجتماعية بامتياز تقرّب الأعضاء من بعضهم وتمنح منتداك روحًا حيوية في كل زيارة. ألّف الكود وصمّمه العضو msrooor22، مع الشكر للعضو Lufy على ملاحظاته في تحسينه.

صاحب الكود: msrooor22، وعدّله وحسّنه كونان2000 بالاستعانة بالذكاء الاصطناعي
 

رأيك جزء من المعرفة.

أضف تجربتك أو سؤالك، فالنقاش يكمل الفكرة.

في هذا الموضوع

صاحب النقاش

كود جيفري
كود جيفريعضو جديد

معرفة تكبر بالنقاش

وجدت معلومة مفيدة؟ أضف تجربتك أو سؤالك ليساعد النقاش أعضاء آخرين.

أكمل رحلتك

كود يخفي أي جزء من المساهمة عن الزواركود الروابط أو الزيارات الأخيرة في المنتدىتمييز المساهمات حسب الجهاز (الهواتف والكمبيوترات)
عودة
أعلى