Old Code Using loadjs

Hello everyone,
I’m facing an issue with my code after upgrading to version 2026.
I had previously built this code in version 2025, where it worked perfectly with no issues. It contains multiple parts and interconnected pages, but after the upgrade to 2026, the code no longer works — and it’s a critical part of the platform I use.

Note: I’ve removed some queries and field names for confidentiality and security reasons (e.g., replaced them with TableOne, TableTwo, FieldOne, FieldTwo, etc.).


The first code (in the head section) — Notification Bell

Page_Head

<script type="text/html" class="ew-js-template" data-name="myDropdown" data-method="prependTo" data-target="#ew-navbar-end" data-seq="10">
<li class="nav-item dropdown" id="myDropdownContainer">
  <a class="nav-link" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">
    <i class="fas fa-bell" style="font-size: 17px;"></i>
    <span class="badge text-bg-warning navbar-badge" id="reminder-badge">0</span>
  </a>
  <div class="dropdown-menu dropdown-menu-lg dropdown-menu-end" id="reminder-dropdown-menu" style="max-height: 400px; overflow-y: auto;">
    <span class="dropdown-item dropdown-header" id="reminder-header">0 Notifications </span> 
    <!-- -->
  </div>
</li>
</script>


The second code (in Page_Rendering)

function Page_Rendering(): void
{
    // Include the reminders file directly from the project root
    include_once "get_reminders.php";

    // Example (hidden for confidentiality):
    // $sql = "SELECT FieldOne, FieldTwo FROM TableOne WHERE FieldThree = ?";
}


The third code (in Global > Page with Header/footer > Client Script)

loadjs.ready("load", function () {
  function renderItems(items) {
    if (!items || items.length === 0) return "<div class='p-2 text-muted'>No items found</div>";
    let html = "";
    items.forEach(function(item) {
      const dt = new Date(item.Start);
      const dateStr = dt.toLocaleDateString('en-US');
      const timeStr = dt.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
      const hijriStr = new Intl.DateTimeFormat('en-SA-u-ca-islamic', {
        weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
      }).format(dt);
      let extraInfo = '';
      if (item.Type === "Session") {
        if (item.Mukallaf) extraInfo += `<div class="text-muted small">Assigned to: ${item.Mukallaf}</div>`;
        if (item.Masoul)   extraInfo += `<div class="text-muted small">Project Manager: ${item.Masoul}</div>`;
      }
      html += `
        <div class="dropdown-divider"></div>
        <a href="${item.Url}" class="dropdown-item">
          <i class="fas fa-calendar-check me-2"></i>
          ${item.Title}
          <div class="text-muted small">${dateStr} — <span class="text-primary">${hijriStr}</span> — ${timeStr}</div>
          ${extraInfo}
        </a>
      `;
    });
    return html;
  }

  let styleTag = document.createElement("style");
  styleTag.innerHTML = `
    #reminder-dropdown-menu .nav-tabs .nav-link.active { color: #000 !important; font-weight: bold; }
    #reminder-header { text-align: center !important; font-weight: bold; }
    .next-reminder-info { font-size: 15px !important; font-weight: bold; color: var(--bs-primary) !important; text-align: center; }
  `;
  document.head.appendChild(styleTag);

  ew.templateData = ew.templateData || {};
  ew.applyTemplate("myDropdown", "script", ew.templateData);

  const dropdown = document.getElementById("reminder-dropdown-menu"),
        badge    = document.getElementById("reminder-badge"),
        header   = document.getElementById("reminder-header");

  let taskCount    = taskReminders.length,
      sessionCount = sessionReminders.length,
      eventCount   = eventReminders.length,
      ticketCount  = ticketReminders.length,
      jobCount     = jobReminders.length,
      total        = taskCount + sessionCount + eventCount + ticketCount + jobCount;

  let allReminders = [...taskReminders, ...sessionReminders, ...eventReminders, ...ticketReminders, ...jobReminders],
      now = new Date(), next = null;
  allReminders.forEach(rem => {
    let start  = new Date(rem.Start),
        buffer = new Date(start.getTime() + 10*60000);
    if (buffer >= now && (!next || start < new Date(next.Start))) next = rem;
  });

  let hint = "";
  if (next) {
    if (taskReminders.some(t => t.Start === next.Start)) hint = "Task";
    else if (sessionReminders.some(s => s.Start === next.Start)) hint = "Session";
    else if (eventReminders.some(e => e.Start === next.Start)) hint = "Event";
    else if (ticketReminders.some(t => t.Start === next.Start)) hint = "Ticket";
    else if (jobReminders.some(j => j.Start === next.Start)) hint = "Job Request";
  }

  let duration = "";
  if (next) {
    let diffMs = new Date(next.Start) - now;
    if (diffMs > 0) {
      let m = Math.floor(diffMs / 60000), h = Math.floor(m / 60), mm = m % 60;
      duration = `${h > 0 ? `${h} hour(s) ` : ""}${mm} minute(s)`;
    } else duration = "Now";
  }

  if (badge) badge.innerText = total;
  if (header) {
    header.innerHTML = `
      <div>${total} Reminders</div>
      ${next ? `<div class="next-reminder-info mt-2">Next reminder is: ${hint} in ${duration}</div>` : ""}
    `;
  }

  const tabsHtml = `
    <div onclick="event.stopPropagation()">
      <ul class="nav nav-tabs px-2 pt-2" role="tablist">
        <li class="nav-item"><button class="nav-link active" data-bs-toggle="tab" data-bs-target="#tasks">Tasks (${taskCount})</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#sessions">Sessions (${sessionCount})</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#events">Appointments (${eventCount})</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tickets">Tickets (${ticketCount})</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#jobs">Job Requests (${jobCount})</button></li>
      </ul>
      <div class="tab-content p-2" style="max-height:300px;overflow-y:auto">
        <div class="tab-pane fade show active" id="tasks">${renderItems(taskReminders)}</div>
        <div class="tab-pane fade" id="sessions">${renderItems(sessionReminders)}</div>
        <div class="tab-pane fade" id="events">${renderItems(eventReminders)}</div>
        <div class="tab-pane fade" id="tickets">${renderItems(ticketReminders)}</div>
        <div class="tab-pane fade" id="jobs">${renderItems(jobReminders)}</div>
      </div>
    </div>
  `;
  if (dropdown) dropdown.insertAdjacentHTML("beforeend", tabsHtml);
  if (dropdown) dropdown.addEventListener("click", e => e.stopPropagation());
});


The fourth code (Custom File named get_reminders.php)

(Note: The Custom File option “Include Common Files” is unchecked, and the file is placed in the project root.)

<?php


global $Security, $Conn;

if (!$Security->isLoggedIn()) {
    echo '<style>#myDropdownContainer { display: none !important; }</style>';
    return;
}

$today      = date("Y-m-d");
$after3days = date("Y-m-d", strtotime("+3 days"));
$tomorrow   = date("Y-m-d", strtotime("+1 days"));
$userID = $Security->currentUserID();

// — Tasks
$sql1 = "SELECT FieldOne, FieldTwo, FieldThree FROM TableOne WHERE CAST(FieldThree AS DATE) BETWEEN ? AND ? AND FieldFour = ?";
$stmt1 = $Conn->executeQuery($sql1, [$today, $after3days, $userID]);
$tasks = [];
while ($r = $stmt1->fetchAssociative()) {
    $r["Url"]  = "/tableoneview/{$r['FieldOne']}?showdetail=";
    $r["Type"] = "Task";
    $tasks[] = $r;
}

// — Sessions
$sql2 = "SELECT a.FieldOne, a.FieldTwo, a.FieldThree,
                b.FieldFour AS MukallafName,
                c.FieldFive AS MasoulName
         FROM TableTwo a
         LEFT JOIN TableThree b ON a.FieldSix = b.FieldID
         LEFT JOIN TableFour c ON a.FieldSeven = c.FieldID
         WHERE (a.FieldSix = ? OR c.FieldSeven = ?) AND CAST(a.FieldTwo AS DATE) IN (?, ?)";
$stmt2 = $Conn->executeQuery($sql2, [$userID, $userID, $today, $tomorrow]);
$sessions = [];
while ($r = $stmt2->fetchAssociative()) {
    $r["Title"] = "Case #{$r['FieldThree']}";
    $r["Start"] = $r["FieldTwo"];
    $r["Url"]   = "/tabletwoview/{$r['FieldOne']}?showdetail=";
    $r["Mukallaf"] = $r["MukallafName"] ?? "";
    $r["Masoul"]   = $r["MasoulName"] ?? "";
    $r["Type"] = "Session";
    $sessions[] = $r;
}

// — Appointments
$sql3 = "SELECT a.FieldOne, a.FieldTwo, a.FieldThree, b.FieldFour, b.FieldFive
         FROM TableFive a
         LEFT JOIN TableSix b ON a.FieldSeven = b.FieldEight
         WHERE a.FieldNine = ? AND CAST(a.FieldThree AS DATE) BETWEEN ? AND ?";
$stmt3 = $Conn->executeQuery($sql3, [$userID, $today, $after3days]);
$appointments = [];
while ($r = $stmt3->fetchAssociative()) {
    $r["Title"] = "{$r['FieldTwo']} - {$r['FieldFour']} {$r['FieldFive']}";
    $r["Url"] = "/tablefiveview/{$r['FieldOne']}?showdetail=";
    $r["Type"] = "Appointment";
    $appointments[] = $r;
}

// — Tickets
$sql4 = "SELECT FieldOne, FieldTwo, FieldThree, FieldFour
         FROM TableSeven
         WHERE FieldFive = '1'";

$stmt4 = $Conn->executeQuery($sql4);
$tickets = [];
while ($r = $stmt4->fetchAssociative()) {
    $r["Start"] = $r["FieldThree"];
    $r["Title"] = "{$r['FieldTwo']} (Priority: {$r['FieldFour']})";
    $r["Url"] = "/tablesevenview/{$r['FieldOne']}?showdetail=";
    $r["Type"] = "Ticket";
    $tickets[] = $r;
}

// — Job Requests
$sql5 = "SELECT FieldOne, FieldTwo
         FROM TableEight
         WHERE FieldThree = '1'";

$stmt5 = $Conn->executeQuery($sql5);
$jobs = [];
while ($r = $stmt5->fetchAssociative()) {
    $r["Title"] = "Job Request #" . $r["FieldOne"];
    $r["Start"] = $r["FieldTwo"];
    $r["Url"] = "/tableeightview/{$r['FieldOne']}?showdetail=";
    $r["Type"] = "Job";
    $jobs[] = $r;
}

// — Output variables for JavaScript
echo "<script>";
echo "var taskReminders    = " . json_encode($tasks, JSON_UNESCAPED_UNICODE) . ";";
echo "var sessionReminders = " . json_encode($sessions, JSON_UNESCAPED_UNICODE) . ";";
echo "var eventReminders   = " . json_encode($appointments, JSON_UNESCAPED_UNICODE) . ";";
echo "var ticketReminders  = " . json_encode($tickets, JSON_UNESCAPED_UNICODE) . ";";
echo "var jobReminders     = " . json_encode($jobs, JSON_UNESCAPED_UNICODE) . ";";
echo "</script>";


loadjs is not used any more, make sure you read Migrating to v2026. See especially the “Link” HTTP Headers section.

Can you comment on all the codes? If there are any incorrect or unused codes, please point them out.

As the migration guide says:

You need to remove all JavaScript code using loadjs in your project , just write your JavaScript directly.

If you used loadjs.ready(..., handler) before the required scripts are loaded by <script> tags, you can simply change it to document.addEventListener("DOMContentLoaded", handler) or ew.on("dom", handler) .

1 Like

I tried to experiment with that, but so far the attempts to use the tools have not succeeded. Is there a method or code, for example, that achieves the same effect? And where exactly should the code path be?

Youy may post what you tried for discussion.