let db_alert_interval = false; function close_db_alert(target) { if (db_alert_interval) { const alert = $(".db-alert"); clearTimeout(db_alert_interval); db_alert_interval = null; alert.classList.remove("db-alert-show"); alert.$(".alert-progress").className = "alert-progress"; } } async function set_db_alert(message, type) { const alert = $(".db-alert"); const modal = $(".db-alert-modal"); if (db_alert_interval) { clearTimeout(db_alert_interval); db_alert_interval = null; alert.classList.remove("d-alert-show"); alert.$(".alert-progress").className = "alert-progress"; setTimeout(function () {}, 1000); } const icons = { info: "fa-solid fa-circle-info", failure: "fa-solid fa-circle-exclamation", success: "fa-solid fa-circle-check", }; alert.className = "db-alert db-alert-" + type; alert.$(".db-alert-icon-wrapper i").className = icons[type]; alert.$(".db-alert-type").innerHTML = type.charAt(0).toUpperCase() + type.slice(1); alert.$(".db-alert-msg").innerHTML = message; modal.style.display = "block"; alert.style.transition = " all 1s"; alert.classList.add("db-alert-show"); alert.$(".alert-progress").classList.add("progress-" + type); setTimeout(function () { alert.$(".alert-progress").classList.add("active-progress"); db_alert_interval = setTimeout(function () { alert.classList.remove("db-alert-show"); alert.$(".alert-progress").className = "alert-progress"; clearTimeout(db_alert_interval); db_alert_interval = null; // modal.style.display = "none"; }, 5000); }, 1000); return; } var userOperations = (function () { function _clearColorClasses(element) { element.classList.remove("text-success"); element.classList.remove("text-danger"); element.classList.remove("failed"); } function _setStatus(element, data) { var statusElement = document.querySelector("#" + element + "-verification"); if (data["status-code"] === 200) { statusElement.innerHTML = "OK"; _clearColorClasses(statusElement); statusElement.classList.add("text-success"); if (element === "file") { var button = document.querySelector("#file-verify-button"); if (button !== null) { button.classList.add("d-none"); } var c_link = document.querySelector("#confirm-link"); if (c_link !== null) { c_link.classList.remove("d-none"); } document.querySelector("#verify-text").classList.add("d-none"); } return true; } statusElement.innerHTML = "Failed"; _clearColorClasses(statusElement); statusElement.classList.add("text-danger"); return false; } function _handleCancelAction(data) { window.location = "/dashboard?action=website-monitor"; } function verificationSetStatusByUrl() { const queryString = window.location.search; var urlParams = new URLSearchParams(queryString); url = "/user-request?action=check-url&now=1&url=" + urlParams.get("url"); sendRequest.doGet(url, _setStatus.bind(this, "status")); } function verificationFile() { const queryString = window.location.search; var urlParams = new URLSearchParams(queryString); var input = document.querySelector("#input_identifier"); if (input !== null) { value = input.value; } else { value = "none"; } var inputuid = document.querySelector("#uid"); if (inputuid !== null) { uid = inputuid.value; } else { uid = "none"; } url = "/user-request?action=check-file&now=1&id=" + value + "&url=" + urlParams.get("url") + "&uid=" + uid; sendRequest.doGet(url, _setStatus.bind(this, "file")); } function cancelValidationProcess() { const queryString = window.location.search; var urlParams = new URLSearchParams(queryString); var id = document.querySelector("#uid"); url = "/user-request?action=cancel-verification&now=1&id=" + id.value + "&url=" + urlParams.get("url"); sendRequest.doGet(url, _handleCancelAction.bind(this, "file")); } function setEventListenerss() { var verifyButton = document.querySelector("#file-verify-button"); if (verifyButton !== null) { verifyButton.addEventListener("click", verificationFile); } var cancelButton = document.querySelector("#cancel-verify-button"); if (cancelButton !== null) { cancelButton.addEventListener("click", cancelValidationProcess); } } var API = { verificationSetStatusByUrl: verificationSetStatusByUrl, verificationFile: verificationFile, cancelValidationProcess: cancelValidationProcess, setEventListenerss: setEventListenerss, }; return API; })(); userOperations.setEventListenerss(); const eventObject = { init() { window["set_progress_token"](); this.addEvents(); }, ids: { "delete-project": ["_handleDeleteProjects", "click"], "check-all-projects": ["_handleCheckAllProjects", "click"], }, classes: { "check-project": ["_handleCheckProjects", "click"], }, _handleCheckAllProjects: function (ev) { const boxes = $(".check-project", true); const unchecked = Array.from(boxes).find( (elem) => !elem.hasAttribute("checked") ); boxes.forEach(function (elem) { console.log(unchecked); if (unchecked) { elem.setAttribute("checked", "checked"); } else { elem.removeAttribute("checked"); } }); }, _handleCheckProjects: function (ev) { console.log(ev); ev.target.toggleAttribute("checked"); }, _handleDeleteProjects: function (ev) { if (!confirm("Are you sure you want to delete these projects?")) { return false; } let selected = $(".check-project", true); console.log(selected); selected = Array.from(selected).filter((elem) => elem.hasAttribute("checked") ); if (selected.length < 1) { return; } db_modal(); const ids = Array.from(selected).map((itm) => itm.dataset.id); let data = new FormData(); data.append("projects", ids); const url = "/user-request?action=delete-" + ev.target.closest("button").dataset.type; sendRequest.doPost(url, data, function (data) { db_modal(false); if (data["success"]) { set_db_alert(data["success"], "success"); ids.forEach((elem) => { $(`input[data-id="${elem}"]`).parentElement.parentElement.remove(); }); } else { set_db_alert(data["failure"], "failure"); } }); }, addEvents: function () { const obj = this; for (id in obj.ids) { element = document.querySelector("#" + id); if (element) { element.addEventListener(obj.ids[id][1], obj[obj.ids[id][0]]); } } for (cls in obj.classes) { elements = document.querySelectorAll("." + cls); if (elements) { elements.forEach(function (el) { el.addEventListener(obj.classes[cls][1], obj[obj.classes[cls][0]]); }); } } }, stampsToDates: function () { const stamps = $(".date-holder", true); stamps.forEach(function (elem) { if (isNaN(parseInt(elem.innerHTML.trim()))) { return; } const date = new Date(parseInt(elem.innerHTML.trim()) * 1000); let year = date.getFullYear(); let month = date.getMonth() + 1; let day = date.getDate(); getLength(day) < 2 ? (day = "0" + day) : null; getLength(month) < 2 ? (month = "0" + month) : null; let hours = date.getHours(); let minutes = date.getMinutes(); getLength(minutes) < 2 ? (minutes = "0" + minutes) : null; let final = year + "/" + month + "/" + day + " " + hours + ":" + minutes; elem.innerHTML = final; }); }, }; function create_db_notice(type = "", message, parent = false) { const wrapper = $create("div", false, ["db-notice", type + "-notice"]); const icon = $create("i", false, ["fa-solid", "fa-circle-exclamation"]); const span = $create("span", false, ["notice-message"], message); wrapper.appendChild(icon); wrapper.appendChild(span); if (parent) { parent.querySelector(".db-notice-box").appendChild(wrapper); return false; } else { return wrapper; } } function new_form_data(obj) { const data = new FormData(); for (const key in obj) { data.append(key, obj[key]); } return data; } function current_menu_item() { if (window.location.search) { const items = $("#dashboard-menu a", true); const found = Array.from(items).find( (itm) => itm.href.indexOf(window.location.search) > 0 ); if (found) { found.parentElement.classList.add("selected-menu-item"); const submenu = found.parentElement.nextElementSibling; if (submenu && submenu.classList.contains("d-none")) { found.parentElement.nextElementSibling.classList.remove("d-none"); } } } } function document_scroll() { document.addEventListener( "scroll", function (ev) { // console.log(ev) // dashboard_margin(); }, true ); } function dashboard_margin() { const section = $("#dashboard-menu"); // console.log(section) if (section) { const s_rect = section.getBoundingClientRect(); if (window.scrollY > 0) { section.style.paddingTop = "50px"; } else { section.style.paddingTop = "0"; } } } const ocrRequests = { ...eventObject, ids: { ...eventObject.ids, file: ["_handleFileUpload", "change"], }, classes: { ...eventObject.classes, "delete-ocr": ["_handleDeleteFile", "click"], }, _handleFileUpload: function (ev) { if (check_types()) { names_list(); } else { message = "Some files are not compatible! Make sure your files are " + app.allowed_types.join(", ").toUpperCase() + "."; set_db_alert(message, "danger"); } }, _handleDeleteFile: function (event) { event.preventDefault(); const url = event.target.href; get_request(url, true, function (call_data) { if (call_data["success"]) { event.target.parentElement.parentElement.remove(); $(".user-file-counter").innerHTML = parseInt($(".user-file-counter").innerHTML) - 1; } request_message(call_data, true); }); }, populate_dashboard_table: function (req_file) { const table_body = $("#ocr-results-wrapper table tbody"); const cookies = app.getCookies(); if (!req_file && !cookies["ocr-anon-file"]) { return false; } let file; if (req_file) { file = JSON.parse(req_file); } else if (!app.is_logged && cookies["ocr-anon-file"]) { if (table_body.children.length > 0) { return false; } file = JSON.parse(cookies["ocr-anon-file"]); } else { return false; } const tr = $create("tr"); const name_td = $create("td", false, false, file.file_name); const type_td = $create("td", false, false); const splited = file.file_name.split("."); const type = splited[splited.length - 1]; const obj = $create("object", false, [type + "-icon"]); obj.setAttribute("width", 25); obj.setAttribute("height", 25); obj.setAttribute("data", `/images/${type}-type.svg`); type_td.appendChild(obj); const lang_td = $create("td", false, false, file.language); const date_td = $create("td", false, false, file.created_at); const download_td = $create("td"); const link = $create("a", false, false, "Download"); link.href = file.download_link; download_td.appendChild(link); tr.appendChild(name_td); tr.appendChild(type_td); tr.appendChild(lang_td); tr.appendChild(date_td); tr.appendChild(download_td); //increase counter $(".user-file-counter").innerHTML = parseInt($(".user-file-counter").innerHTML) + 1; //add delete td const delete_td = $create("td"); const a = $create("a", false, false, "Remove"); a.classList.add("text-danger", "delete-ocr"); if (app.is_logged) { a.href = "/user-request?delete-ocr-file=" + file.file_id; } else { a.href = "/user-request?delete-ocr-file=" + file.download_link; } delete_td.appendChild(a); tr.appendChild(delete_td); a.addEventListener("click", this._handleDeleteFile); // table_body.children[0].remove() table_body.appendChild(tr); }, }; //SEO REPORT ---> function update_report_summary(data = false) { const fill_colors = { passed: "#83d195", failed: "#EDAAAC", warning: "#dfc164", }; if (!data) { total_passed = $(".total-passed").innerHTML || 0; total_failed = $(".total-failed").innerHTML || 0; total_warning = $(".total-warning").innerHTML || 0; total_tests = parseInt(total_passed) + parseInt(total_failed) + parseInt(total_warning); } else { total_passed = data["passed"]; total_failed = data["failed"]; total_warning = data["warning"]; total_tests = data["totals"]; } let tests = { passed: total_passed, failed: total_failed, warning: total_warning, }; for (const type in tests) { let indicator = $(".total-" + type); let loader = indicator.parentElement.parentElement.querySelector(".loader"); if (loader) { loader.remove(); indicator.classList.remove("d-none"); } indicator.innerHTML = tests[type] + "/" + total_tests; let percent = (parseInt(tests[type]) / total_tests) * 100; } } function clear_report_nav() { let lists = $(".report-child-nav", true); let collapsibles = $(".collapsible-collapsed", true); let lis = $(".section-li", true); lists.forEach(function (elem) { elem.remove(); }); collapsibles.forEach(function (elem) { elem.classList.remove("collapsible-collapsed"); elem.classList.add("collapsible"); }); lis.forEach(function (elem) { elem.children[0].children[1].innerHTML = "0/0"; }); } function toggle_report_data() { let buttons = $(".toggle-report-data", true); buttons.forEach((elem) => { elem.addEventListener("click", function () { let holder = elem.parentElement.parentElement.children[1]; if (holder.classList.contains("d-none")) { elem.children[0].innerHTML = "Hide Details"; holder.classList.remove("d-none"); } else { elem.children[0].innerHTML = "View Details"; holder.classList.add("d-none"); } }); }); } function toggle_report_info() { let buttons = $(".item-name", true); buttons.forEach((elem) => { elem.addEventListener("click", function () { let holder = elem.parentElement.parentElement.querySelector(".item-info-wrapper"); if (holder.style.maxHeight === "0px" || holder.style.maxHeight == "") { holder.style.maxHeight = "800px"; holder.style.padding = "0 50px 10px 50px"; elem.parentElement.parentElement.style.marginBottom = "15px"; elem.parentElement.parentElement.classList.add("item-info-bg"); } else { holder.style.maxHeight = "0px"; holder.style.padding = "0px"; elem.parentElement.parentElement.classList.remove("item-info-bg"); elem.parentElement.parentElement.style.marginBottom = "0px"; } }); }); } function create_report_nav() { const headings = $(".section-heading", true); const section_navs = $(".section-li", true); let nav_ul = $("#report-nav"); if (!nav_ul) { return false; } nav_ul.parentElement.classList.contains("no-report") ? nav_ul.parentElement.classList.remove("d-none") : null; let recommended_ul = $("#recommended-actions ul"); let lists = [nav_ul, recommended_ul]; lists.forEach(function (el) { if (!el) { return; } el.addEventListener("click", function (ev) { //check if click is on navigation list if ( ev.target.parentElement.classList.contains("section-li") || ev.target.parentElement.classList.contains("report-nav-item-holder") ) { let ul = ev.target.parentElement.querySelector("ul") || ev.target.parentElement.parentElement.querySelector("ul"); let collapsible = ul.previousElementSibling.children[0]; if (ul.style.maxHeight == "0px" || ul.style.maxHeight == "") { ul.style.maxHeight = "500px"; collapsible .closest(".collapsible") .classList.add("collapsible-collapsed"); collapsible.closest(".collapsible").classList.remove("collapsible"); } else { ul.style.maxHeight = "0px"; collapsible .closest(".collapsible-collapsed") .classList.add("collapsible"); collapsible .closest(".collapsible-collapsed") .classList.remove("collapsible-collapsed"); } // const h_name = ev.target.innerHTML.replace(" ", "-").toLowerCase(); // window.scroll(0, findPosition($("#" + h_name))) } else { //check if target contains span. this is for recommended list let is_span = ev.target.querySelector("span"); let span_name; if (is_span) { span_name = is_span.innerHTML .trim() .replace(".", "-") .replaceAll(" ", "-") .toLowerCase() .replace("/", "-"); } else { span_name = ev.target.innerHTML .trim() .replace(".", "-") .replaceAll(" ", "-") .toLowerCase() .replace("/", "-"); } console.log(span_name); window.scroll(0, findPosition($('[data-nav|="' + span_name + '"]'))); } }); }); headings.forEach(function (elem, idx) { let child_ul = document.createElement("ul"); child_ul.classList.add("report-child-nav"); let main_li = Array.from(section_navs).find( (to_find) => to_find.children[0].children[0].innerHTML == elem.children[0].innerHTML ); main_li.appendChild(child_ul); let names = elem.parentElement.querySelectorAll(".item-name"); let passed = 0; names.forEach(function (nm) { let classes = nm.classList; // classes.remove("fw", "item-name") let second_li = document.createElement("li"); let second_span = document.createElement("span"); second_span.classList.add("report-nav-item", classes[2]); classes.contains("passed-test") || classes.contains("info-test") ? passed++ : null; // classes[2] == "passed-test" ? passed++ : null; // classes[2] == "info-test" ? passed++ : null; second_span.innerHTML = nm.innerHTML; second_li.appendChild(second_span); child_ul.appendChild(second_li); }); main_li.children[0].children[1].innerHTML = passed + "/" + names.length; elem.parentElement.querySelector(".section-score").innerHTML = passed + "/" + names.length + " Passed Tests"; }); // $("#left-section").children[0].appendChild(ul) function findPosition(obj) { var currenttop = 0; console.log(obj); if (obj.offsetParent) { do { currenttop += obj.offsetTop; } while ((obj = obj.offsetParent)); return [currenttop - 100]; } } } function toggle_report_section() { const headings = $(".section-heading", true); headings.forEach(function (elem) { elem.addEventListener("click", function () { const wrapper = this.nextElementSibling; console.log(wrapper.style.maxHeight); if (wrapper.style.maxHeight == "0px" || wrapper.style.maxHeight == "") { wrapper.style.maxHeight = "2000px"; this.classList.remove("section-collapse"); this.classList.add("section-collapsed"); } else { this.classList.remove("section-collapsed"); this.classList.add("section-collapse"); wrapper.style.maxHeight = "0px"; } }); }); } // END SEO REPORT <-- //<-- PROJECT HANDLING function set_project_type() { const params = new URLSearchParams(window.location.search); const type = params.get("type"); if (type) { $("#project-type").value = type; $(".service-wrapper", true).forEach((elem) => { elem.classList.remove("selected-service"); }); $(".service-wrapper[data-type='" + type + "']").classList.add( "selected-service" ); } } let projectRequests = function () { function add_events() { let create_project = $("#create-project"); if (create_project) { create_project.addEventListener("click", _handleCreateProject); } let select_p_type = $("#project-type"); if (select_p_type) { select_p_type.addEventListener("change", _handleChangeProjectType); } let sitemap_url = $("#sitemap-url"); sitemap_url.addEventListener("keyup", _handleValidateSitemapUrl); } function display_loader(show) { if (show) { $("#create-project .db-loader-wrapper").style.display = "block"; } else { $("#create-project .db-loader-wrapper").style.display = "none"; } } function _handleValidateSitemapUrl(ev) { const val = ev.target.value; // console.log(isValidUrl(val)); if (!validURL(val)) { return false; } const parts = val.split("."); if (parts[parts.length - 1].toLowerCase() !== "xml") { console.log("Not an xml"); return false; } } async function _handleCreateProject(ev) { display_loader(true); let form_data = get_form_data( $("#create-project-wrapper .selected-service"), true ); if (!form_data) { display_loader(false); return false; } let project_name = $("#project-name").value; if (!project_name) { set_db_alert("Please insert a valid project name!", "failure"); display_loader(false); return false; } if (project_name.length >= 100) { console.log(project_name.length); set_db_alert("Please use a shorter project name!", "failure"); display_loader(false); return false; } form_data.append("project-name", project_name); form_data.append("project-type", $("#project-type").value); let url = "/user-request?action=create-project"; post_form_request(url, form_data, function (data) { display_loader(false); console.log(data); if (data["success"]) { window.location.href = "/dashboard?action=" + $("#project-type").value + "&project=" + data["project"]; } else { set_db_alert(data["failure"], "failure"); } }); } function _handleChangeProjectType(ev) { let wrappers = $(".service-wrapper", true); wrappers.forEach(function (el) { // el.style.display = "none"; el.classList.remove("selected-service"); if (el.dataset.type == ev.target.value) { el.classList.add("selected-service"); } }); } add_events(); }; // END PROJECT HADNLING --> //sitemap monitor requests const sitemapMonitorRequests = { ...eventObject, history_data: [], broken_urls: [], extensions: [], active_menu: true, main_chart: null, ids: { ...eventObject.ids, "check-extensions": ["_handleCheckExtensions", "click"], "sm-save-settings": ["_handleSaveSettings", "click"], "start-monitor": ["_handleToggleMonitors", "click"], "stop-monitor": ["_handleToggleMonitors", "click"], }, classes: { ...eventObject.classes, // "view-more-stats": ["_handleViewMoreStats", "click"], "ext-menu-item": ["_handleExtensionDisplay", "click"], "switch-btn": ["_handleSwitchMonitorStatus", "click"], "sm-monitor-nav": ["_handleChangeMonitorDisplay", "click"], "sm-chart-select": ["_handleChangeCharts", "click"], }, _handleChangeCharts: function (ev) { sitemapMonitorCharts.main_chart.destroy(); const clicked = ev.target.closest(".sm-chart-select"); $(".sm-chart-select", true).forEach(function (elem) { elem.classList.remove("selected-sm-chart"); }); clicked.classList.add("selected-sm-chart"); switch (clicked.dataset.chart) { case "broken-links": sitemapMonitorCharts.createBrokenLinksChart(); break; case "new-links": sitemapMonitorCharts.createNewLinksChart(); break; case "removed-links": sitemapMonitorCharts.createRemovedLinksChart(); break; case "modified-links": sitemapMonitorCharts.createModifiedLinksChart(); break; case "sitemap-status": sitemapMonitorCharts.createStatusChart(); break; } }, _handleToggleMonitors: function (ev) { db_modal(); let selected = $(".check-project", true); selected = Array.from(selected).filter((elem) => elem.hasAttribute("checked") ); if (selected.length < 1) { return; } const ids = Array.from(selected).map((itm) => itm.dataset.id); const mode = ev.target.closest("button").dataset.value; let data = new FormData(); data.append("projects", ids); data.append("mode", mode); const url = "/user-request?action=toggle-monitors"; sendRequest.doPost(url, data, function (data) { db_modal(false); if (data["success"]) { set_db_alert(data["success"], "success"); ids.forEach((elem) => { const row = $(`input[data-id="${elem}"]`).parentElement.parentElement; if (mode == "off") { const status = row.querySelector(".active-monitor"); if (status) { row.querySelector(".next-check").innerHTML = "Monitor Disabled"; status.classList.remove("active-monitor"); status.classList.add("disabled-monitor"); status.innerHTML = "Disabled"; } } else { const status = row.querySelector(".disabled-monitor"); status.classList.add("active-monitor"); status.classList.remove("disabled-monitor"); status.innerHTML = "Active"; } }); } else { set_db_alert(data["failure"], "failure"); } }); }, loading_details: function (show = true, to_blur = false) { const loader = $("#details-loader"); if (show) { sitemapMonitorRequests.active_menu = false; if (to_blur) { to_blur.style.filter = "blur(6px)"; } loader.style.display = "block"; } else { if (to_blur) { to_blur.style.filter = "blur(0)"; } loader.style.display = "none"; sitemapMonitorRequests.active_menu = true; } }, displayDetailsNotice: function ( display = true, detail_box, display_icon = false ) { if (display) { $("." + detail_box + "-wrapper").style.display = "none"; $('div[data-id="' + detail_box + '"]').querySelector( ".db-notice-box" ).innerHTML = ""; $('div[data-id="' + detail_box + '"]').querySelector( ".db-notice-box" ).style.display = "block"; } else { $("." + detail_box + "-wrapper").style.display = "block"; $('div[data-id="' + detail_box + '"]').querySelector( ".db-notice-box" ).style.display = "none"; } //display big icon if (display_icon) { // $('div[data-id="' + detail_box + '"]').querySelector( // ".details-icon-wrapper" // ).style.display = "block"; } else { // $('div[data-id="' + detail_box + '"]').querySelector( // ".details-icon-wrapper" // ).style.display = "none"; } }, getExtensions: function () { const project = $("#project-id").value; const url = "/user-request?action=get-sm-extensions&project=" + project; sitemapMonitorRequests.loading_details( true, $('div[data-id="extensions"]') ); sendRequest.doGet(url, ext_cb); //call back for fetch request function ext_cb(data) { sitemapMonitorRequests.loading_details( false, $('div[data-id="extensions"]') ); if (data["success"]) { if (Object.keys(data["success"]["extensions"]).length > 0) { sitemapMonitorRequests.extensions = data["success"]["extensions"]; sitemapMonitorRequests.displayDetailsNotice(false, "extensions"); sitemapMonitorRequests.displayExtensions(); } else { sitemapMonitorRequests.displayDetailsNotice(true, "extensions", true); create_db_notice( "basic", data["success"]["message"], $('div[data-id="extensions"]') ); } } else { sitemapMonitorRequests.displayDetailsNotice(true, "extensions"); create_db_notice( "error", data["failure"], $('div[data-id="extensions"]') ); } } }, displayExtensions: function () { let counters = { image: 0, news: 0, video: 0, xhtml: 0, }; console.log(this.extensions); for (const url in this.extensions) { for (ext in this.extensions[url]) { let ext_name = ext.split(":")[0]; create_extension_item(url, ext_name, this.extensions[url][ext]); counters[ext_name] += this.extensions[url][ext].length; } } for (counter in counters) { $(`div[data-ext="${counter}"`).querySelector( "span:last-child" ).innerHTML = "(" + counters[counter] + ")"; } function create_extension_item(parent, ext_name, arr) { const wrapper = $create("div", false, [ ext_name + "-item", "extension-item-wrapper", ]); const url_wrapper = $create("div", false, ["extension-url-wrapper"]); const span_url = $create("span", false, ["fw-bold"], "URL:"); const span_link = $create("span", false, ["fw-bold"], parent); url_wrapper.appendChild(span_url); url_wrapper.appendChild(span_link); wrapper.appendChild(url_wrapper); Array.from(arr).forEach((elem, idx) => { const data_wrapper = $create("div", false, ["extension-data"]); //loop through keys for (key in elem) { //if the object has more than one key loop through those keys const container = $create("div"); const name_span = $create("span", false, ["fw-bold"], key + " "); container.appendChild(name_span); // console.log(name_span); if (Object.keys(elem[key]).length > 1) { for (subkey in elem[key]) { if (subkey == "attributes") { for (attr in elem[key]["attributes"]) { const sub_container = $create("div", false, [ "extension-sub-item", ]); const name_span = $create( "span", false, ["fw-bold"], attr + " " ); const val_span = $create( "span", false, false, elem[key]["attributes"][attr] ); sub_container.appendChild(name_span); sub_container.appendChild(val_span); container.appendChild(sub_container); } } else { const sub_container = $create("div", false, [ "extension-sub-item", ]); const name_span = $create( "span", false, ["fw-bold"], subkey + " " ); const val_span = $create( "span", false, false, elem[key][subkey]["value"] || elem[key][subkey] ); sub_container.appendChild(name_span); sub_container.appendChild(val_span); container.appendChild(sub_container); } } } else { const val_span = $create("span", false, false, elem[key]["value"]); container.appendChild(val_span); } data_wrapper.appendChild(container); } wrapper.appendChild(data_wrapper); if (idx < arr.length - 1) { wrapper.appendChild($create("hr")); } $("." + ext_name + "-extension").appendChild(wrapper); }); } }, displayBrokenLinks: function () { const table = $("#sm-links-table"); table.querySelector('thead th[colspan="6"]').innerHTML = "Broken Links (" + this.broken_urls.length + ")"; this.broken_urls.forEach(function (elem) { const row = $create("tr"); const url_td = $create("td", false, ["sm-bl-url"], elem.url); const status_td = $create("td", false, false, elem.response_code); const res_td = $create( "td", false, false, (elem.response_time * 1000).toFixed(2) + "Ms" ); const size_td = $create("td", false, false, formatBytes(elem.page_size)); const redir_td = $create("td", false, false, elem.redirects); row.appendChild(url_td); row.appendChild(status_td); row.appendChild(res_td); row.appendChild(size_td); row.appendChild(redir_td); table.querySelector("tbody").appendChild(row); }); }, getBrokenLinks: async function () { const project = $("#project-id").value; const url = "/user-request?action=get-sm-broken-links&project=" + project; //show loading box sitemapMonitorRequests.loading_details( true, $('div[data-id="broken-links"]') ); sendRequest.doGet(url, bl_cb); //call back for fetch request function bl_cb(data) { sitemapMonitorRequests.loading_details( false, $('div[data-id="broken-links"]') ); if (data["success"]) { sitemapMonitorRequests.broken_urls = data["success"]["links"]; if (data["success"]["links"].length > 0) { sitemapMonitorRequests.displayDetailsNotice(false, "broken-links"); sitemapMonitorRequests.displayBrokenLinks(); } else { sitemapMonitorRequests.displayDetailsNotice( true, "broken-links", true ); create_db_notice( "basic", data["success"]["message"], $('div[data-id="broken-links"]') ); } } else { create_db_notice( "error", data["failure"], $('div[data-id="broken-links"]') ); sitemapMonitorRequests.displayDetailsNotice(true, "broken-links"); } } }, _handleChangeMonitorDisplay: function (ev) { if (sitemapMonitorRequests.active_menu == false) { return false; } const nav_data = ev.target.closest("li").dataset.nav; const displays = $(".sm-details-box", true); const navs = $(".sm-monitor-nav", true); if (nav_data == "broken-links") { if (sitemapMonitorRequests.broken_urls.length == 0) { sitemapMonitorRequests.getBrokenLinks(); } } if (nav_data == "extensions") { if (sitemapMonitorRequests.extensions.length == 0) { sitemapMonitorRequests.getExtensions(); } } displays.forEach(function (elem) { if (elem.dataset.id == nav_data) { elem.style.display = "flex"; } else { elem.style.display = "none"; } }); navs.forEach(function (elem) { if (elem.dataset.nav == nav_data) { elem.classList.add("sm-active-menu-item"); } else { elem.classList.remove("sm-active-menu-item"); } }); }, getHistoryData: async function () { const url = "/user-request?action=get-sm-history"; let data = new FormData(); data.append("sitemap-id", $("#sitemap-id").value); data.append("project-id", $("#project-id").value); await sendRequest.doPost(url, data, (data) => { if (data["success"]) { sitemapMonitorCharts.history_data = data["success"]["data"]; } else { console.log(data["failure"]); } }); }, _handleSaveSettings: async function (ev) { const data = get_form_data($(".sm-settings-wrapper"), true); let url = "/user-request?action=update-monitor-settings"; await sendRequest.doPost(url, data, (data) => { if (data["success"]) { set_db_alert(data["success"], "success"); } else { set_db_alert(data["failure"], "failure"); } }); }, _handleSwitchMonitorStatus: function (ev) { const buttons = $(".switch-btn", true); const clicked_btn = ev.target.closest(".switch-btn"); if (!clicked_btn.classList.contains("active-switch")) { clicked_btn.classList.add("active-switch"); console.log($("#monitor-status")); $("#monitor-status").setAttribute("value", clicked_btn.dataset.value); } buttons.forEach(function (btn) { if (btn !== clicked_btn) { btn.classList.remove("active-switch"); } }); }, _handleViewMoreStats: function (ev) { ev.preventDefault(); const box = ev.target.parentElement.parentElement; const btns = $(".view-more-stats", true); btns.forEach(function (btn) { btn.parentElement.parentElement.style.minHeight = "0"; btn.parentElement.parentElement.style.maxHeight = "0"; }); }, _handleCheckExtensions: async function (ev) { const form_data = new FormData(); form_data.append("to-check", "extensions"); form_data.append("sitemap_id", clicked.dataset.id); await sendRequest.doPost("/seo-check?user=user", form_data, (data) => { // window.location.href = "/dashboard?action=sitemap-page&" + id; }); }, _handleExtensionDisplay: function (ev) { let clicked = ev.target.closest(".ext-menu-item"); // let nav_data = Array.from($(".ext-menu-item", true)).map( // (elem) => elem.dataset.ext // ); let nav_data = $(".ext-menu-item", true); nav_data.forEach(function (nd) { if (nd.dataset.ext !== clicked.dataset.ext) { $("." + nd.dataset.ext + "-extension").style.display = "none"; nd.classList.remove("selected-ext"); } else { nd.classList.add("selected-ext"); } }); if ($("." + clicked.dataset.ext + "-extension").style.display == "none") { $("." + clicked.dataset.ext + "-extension").style.display = "block"; } }, }; const sitemapMonitorCharts = { history_data: [], dates: [], generateChart: function (data, title, legend = true, tooltips = {}) { Chart.register(ChartDataLabels); let chart_dates = []; this.dates.forEach(function (lb) { const date = new Date(parseInt(lb) * 1000); let month = date.toLocaleString("default", { month: "long" }); let day = date.toLocaleString("default", { weekday: "long" }); let hours = date.getHours(); let minutes = date.getMinutes(); let label = day + " " + hours + ":"; if (getLength(minutes) > 1) { label += minutes; } else { label += "0" + minutes; } chart_dates.push(label); }); data["labels"] = chart_dates; this.main_chart = new Chart($("#sm-main-chart"), { type: "bar", data: data, options: { responsive: true, scales: { y: { ticks: { beginAtZero: true, }, }, }, plugins: { legend: { display: legend, labels: { filter: function (item, chart) { return item.text; }, }, }, title: { display: true, align: "center", text: title, font: { size: 25, }, color: "#007CBD", }, datalabels: { anchor: "center", font: { size: "18px", }, formatter: function (value, context) { return value > 0 ? value : ""; }, }, tooltips: tooltips, }, }, plugins: [ChartDataLabels], }); }, createUrlChart: function () { // Chart.register(ChartDataLabels); const chart = $("#sm-url-chart"); if (!chart) { return; } const total_urls = $("#total-urls").value; const total_broken = $("#broken-urls").value; const total_percent = Math.round( ((total_urls - total_broken) / total_urls) * 100 ); const total_percent_broken = Math.round((total_broken / total_urls) * 100); // if( !total) chart_data = { datasets: [ { data: [total_percent, total_percent_broken], backgroundColor: ["lightblue", "#F07475"], hoverOffset: 5, datalabels: { font: { size: "18px", }, formatter: function (value, context) { return value > 0 ? value + "%" : ""; }, }, }, ], labels: ["Good URLs", "Broken URLs"], }; var chartId = new Chart(chart, { type: "pie", data: chart_data, options: { responsive: false, plugins: { legend: { display: true, position: "right", }, title: { display: true, text: ["Total URLs: " + total_urls], color: "#007CBD", font: { size: 25, }, }, tooltip: { callbacks: { label: function (itm) { idx = itm["dataIndex"]; return itm["label"] + " - " + itm["dataset"]["data"][idx] + "%"; }, }, }, }, }, plugins: [ChartDataLabels], }); }, createStatusChart: function () { const statuses = this.history_data.map((itm) => { if (itm["smd_xml_errors"]) { return "XML ERROR"; } else if (!itm["smd_file_status"]) { return -1; } else { return itm["smd_file_status"]; } }); let ok_status_data = { label: "OK", data: [], backgroundColor: "rgba(0, 229, 0, 0.54)", stack: "Stack 0", datalabels: { display: false, }, }; let file_error_data = { label: "File Error", data: [], backgroundColor: "rgba(229, 0, 0, 0.54)", stack: "Stack 0", datalabels: { display: false, }, }; let xml_error_data = { label: "XML Error", data: [], backgroundColor: "purple", stack: "Stack 0", datalabels: { display: false, }, }; let no_data = { stack: "Stack 0", data: [], datalabels: { display: false, }, }; statuses.forEach(function (elem, idx) { if (elem == "XML ERROR") { xml_error_data["data"].push(1); file_error_data["data"].push(0); ok_status_data["data"].push(0); } else { if (parseInt(elem) >= 400) { file_error_data["data"].push(1); xml_error_data["data"].push(0); ok_status_data["data"].push(0); } else if (parseInt(elem) <= 0) { no_data["data"].push(0); } else { ok_status_data["data"].push(1); file_error_data["data"].push(0); xml_error_data["data"].push(0); } } }); let chart_data = { datasets: [ok_status_data, file_error_data, xml_error_data, no_data], }; this.generateChart(chart_data, ["Statuses"]); }, createRemovedLinksChart: function () { const removed_links = this.history_data.map((itm) => itm["smd_removed_links"] !== "0" ? itm["smd_removed_links"] : 0 ); const non_zero = removed_links.filter((itm) => itm > 0); let chart_data = { datasets: [ { data: removed_links, backgroundColor: "#F0C6C6", label: "Removed Links", }, ], labels: [], }; this.generateChart(chart_data, ["Removed Links"], false); }, createModifiedLinksChart: function () { const modified_link = this.history_data.map((itm) => itm["smd_modified_links"] !== "0" ? itm["smd_modified_links"] : 0 ); const non_zero = modified_link.filter((itm) => itm > 0); let chart_data = { datasets: [ { data: modified_link, backgroundColor: "#D9A738", label: "Modified Links", }, ], }; console.log(chart_data); this.generateChart(chart_data, ["Modified Links"], false); }, createBrokenLinksChart: function () { const broken_links = this.history_data.map((itm) => itm["smd_total_broken_links"] !== "0" ? itm["smd_total_broken_links"] : 0 ); const non_zero = broken_links.filter((itm) => itm > 0); let chart_data = { datasets: [ { data: broken_links, backgroundColor: "rgba(229, 0, 0, 0.54)", label: "Broken Links", }, ], labels: [], }; this.generateChart(chart_data, ["Broken Links"], false); }, createNewLinksChart: function () { const new_links = this.history_data.map((itm) => itm["smd_new_links"] !== "0" ? itm["smd_new_links"] : 0 ); const non_zero = new_links.filter((itm) => itm > 0); let chart_data = { datasets: [ { data: new_links, backgroundColor: "rgba(0, 229, 0, 0.54)", label: "New Links", }, ], labels: [], }; this.generateChart(chart_data, ["New Links"], false); }, }; //sitemap monitor requests const sitemapGeneratorRequests = { ...eventObject, url_chart: null, init: function () { eventObject.init.apply(this, arguments); sitemapGeneratorRequests.createPieChart(); if ($("#project-status") && $("#project-status").value == "crawling") { sitemapGeneratorRequests.getProgressData(); } window.onbeforeunload = function () { // if ($("#project-status") == "crawling") { sitemapGeneratorRequests.closeConnection(); // } }; }, ids: { ...eventObject.ids, "generate-sitemap": ["_handleGenerateSitemap", "click"], "stop-generator": ["killProcess", "click"], "extensions-only": ["_handleExtensionsOnly", "click"], "download-links": ["_handleDownloadFile", "change"], "add-ignore": ["_handleAddIgnore", "click"], }, classes: { ...eventObject.classes, "sg-help-section": ["_handleHelpSection", "click"], "remove-ignored": ["_handleRemoveIgnored", "click"], }, _handleAddIgnore: function (ev) { const url = $("#ignore-url-input").value; if (!url) { return false; } const wrapper = $create("div", false, ["ignore-wrapper"]); const span = $create("span", false, ["ignored-url"], url); const btn = $create("i", false, ["fa-solid", "fa-trash"]); btn.addEventListener( "click", sitemapGeneratorRequests._handleRemoveIgnored ); wrapper.appendChild(span); wrapper.appendChild(btn); $("#ignore-url-list").appendChild(wrapper); }, _handleRemoveIgnored: function (ev) { ev.target.parentElement.remove(); }, _handleHelpSection: function (ev) { const btn = ev.target.closest(".sg-help-toggle"); if ( $(".sg-help-notices").style.maxHeight == "0px" || $(".sg-help-notices").style.maxHeight == "" ) { $(".sg-help-notices").style.maxHeight = "1000px"; $(".sg-help-notices").style.marginTop = "10px"; btn.$("i").style.rotate = "90deg"; } else { btn.$("i").style.rotate = "0deg"; $(".sg-help-notices").style.maxHeight = "0"; $(".sg-help-notices").style.marginTop = "0"; } }, _handleDownloadFile: function (ev) { // ev.preventDefault(); if (ev.target.value) { download_file(ev.target.value, "XML File"); } ev.target.value = ev.target.getAttribute("data-val"); // ev.setAttribute("value") }, killProcess: function () { if ($("#project-status").value == "crawling") { if ( !confirm( "Are you sure you want to stop the process? All the progress will be lost!" ) ) { return false; } token = $("#project-id").value; var url = "/user-request?action=kill-process&token=" + token; sendRequest.doGet(url, null); } }, closeConnection: function () { token = $("#project-id").value; var url = "/user-request?action=close-connection&token=" + token; sendRequest.doGet(url, function (cd) { console.log(cd); }); }, getProgressData: async function () { url = "/progress-data?token=" + $("#project-id").value; sitemapGeneratorRequests.xhrRequest(url, false, () => { window.location.reload(); }); }, xhrRequest: function (url, data, done_cb = false) { set_db_alert( "You can close this page and return later when the generator is done!", "info" ); sitemapGeneratorRequests.updateProgress({ tf: 0, ta: 0, tp: 0, tnp: 0, tb: 0, ti: 0, tnx: 0, cu: "-", t: "00:00:00", s: "crawling", }); XHR.addCallback(XMLHttpRequest.OPENED, function (data) {}); XHR.open("POST", url, true); XHR.addCallback(XMLHttpRequest.DONE, function (data) { if (done_cb) { done_cb(data); } }); // $(".sg-process-wrapper").style.maxHeight = "1000px"; // $(".sg-process-wrapper").scrollIntoView(); XHR.addCallback(XMLHttpRequest.LOADING, function (data) { try { const parsed = parse_commaless_json(data); console.log(); const last_item = parsed[parsed.length - 1]; if (last_item["s"] == "crawling") { sitemapGeneratorRequests.updateProgress(last_item); } } catch (e) { console.log("Not a valid Json!"); console.log(e); } }); XHR.send(data); }, updateProgress: function (obj) { $("#sg-current-url").innerHTML = obj["cu"]; $("#sg-current-url").setAttribute("data-value", obj["cu"]); $("#sg-passed-time").innerHTML = obj["t"]; $("#sg-passed-time").setAttribute("data-value", obj["t"]); $("#sg-total-processed").innerHTML = obj["tp"]; $("#sg-total-processed").setAttribute("data-value", obj["tp"]); $("#sg-total-urls").innerHTML = obj["tf"]; $("#chart-total-urls").innerHTML = obj["tf"]; $("#sg-total-urls").setAttribute("data-value", obj["tf"]); $("#sg-broken-urls").innerHTML = obj["tb"]; $("#sg-broken-urls").setAttribute("data-value", obj["tb"]); $("#sg-ignored-urls").innerHTML = obj["ti"]; $("#sg-ignored-urls").setAttribute("data-value", obj["ti"]); $("#sg-not-indexable").innerHTML = obj["tnx"]; $("#sg-not-indexable").setAttribute("data-value", obj["tnx"]); $("#sg-total-not-processed").innerHTML = obj["tnp"]; $("#sg-total-not-processed").setAttribute("data-value", obj["tnp"]); // $("#sg-to-be-processed").innerHTML = obj["to-be-processed"]; $("#sg-added-urls").innerHTML = obj["ta"]; $("#sg-added-urls").setAttribute("data-value", obj["ta"]); sitemapGeneratorRequests.updatePieChart(); }, handleEndRequest: function (obj) { console.log(obj); // $(".sg-process-wrapper").style.maxHeight = "0"; if (obj["status"] == "success") { //change status input value $("#project-status").setAttribute("value", "generated"); $("#project-status").removeAttribute("data-value"); $(".sg-info-wrapper").style.display = "flex"; // $(".sg-info-wrapper").scrollIntoView(); this.updateProgress(obj["data"]["url-data"]); //create chart sitemapGeneratorRequests.updatePieChart(); //change visible status let status_elem = $(".ready-sg") || $(".generated-sg") || $(".crawling-sg"); status_elem.classList.remove("ready-sg"); status_elem.classList.remove("crawling-sg"); status_elem.classList.add("generated-sg"); status_elem.innerHTML = "Generated"; //add download links const download_btn = $("#download-links"); const first_child = download_btn.children[0]; download_btn.innerHTML = ""; download_btn.appendChild(first_child); for (url in obj["data"]["links"]) { const opt = $create("option"); opt.value = obj["data"]["links"][url] + "?v=" + Date.now(); opt.innerHTML = obj["data"]["links"][url]; download_btn.appendChild(opt); } } else { $("#project-status").setAttribute( "value", $("#project-status").dataset.value ); $("#project-status").removeAttribute("data-value"); set_db_alert(obj["message"], "failure"); } }, getIgnoredUrls: function () { const spans = $(".ignored-url", true); let res = ""; spans.forEach((elem) => { res += elem.innerHTML.trim() + "\n"; }); return res; }, _handleGenerateSitemap: async function (ev) { let data = get_form_data($(".sg-settings-section"), true); data.append("sitemap-type", $("#sitemap-type").value); data.append("domain", $("#sg-domain").innerHTML.trim()); data.append("token", $("#token").value); data.append("project", $("#project-id").value); let url = "/user-request?action=generate-sitemap"; let ignored_urls = sitemapGeneratorRequests.getIgnoredUrls(); if (ignored_urls) { data.append("ignored-urls", ignored_urls); } $(".sg-info-wrapper").style.maxHeight = "1000px"; //update page elements let page_status = $(".ready-sg") || $(".generated-sg"); page_status.style.display = "none"; $(".sg-status-loader").removeAttribute("hidden"); $("#project-status").setAttribute("data-value", $("#project-status").value); $("#project-status").setAttribute("value", "crawling"); //start xhr request sitemapGeneratorRequests.xhrRequest(url, data, (data) => { let page_status = $(".ready-sg") || $(".generated-sg"); page_status.style.display = "block"; $(".sg-status-loader").setAttribute("hidden", "hidden"); try { const parsed = parse_commaless_json(data); sitemapGeneratorRequests.handleEndRequest(parsed[parsed.length - 1]); } catch (e) { console.log(e); console.log("Not a valid Json!"); } }); }, _handleExtensionsOnly: function (ev) { ev.target.value == "true" ? (ev.target.value = false) : (ev.target.value = true); }, loading: function (hide = false) { const loader = $("#sg-loader"); const links_holder = $(".download-button-holder"); const status = $("#sgp-status"); if (!hide) { if (loader.classList.contains("d-none")) { loader.classList.remove("d-none"); links_holder.classList.add("d-none"); } status.innerHTML = "Crawling"; } else { if (!loader.classList.contains("d-none")) { loader.classList.add("d-none"); links_holder.classList.remove("d-none"); } } }, updatePieChart() { let total_discovered = $("#sg-total-urls").dataset.value; const data_ids = [ "sg-total-not-processed", "sg-added-urls", "sg-broken-urls", "sg-ignored-urls", "sg-not-indexable", ]; new_data = []; data_ids.forEach(function (id) { const elem = $("#" + id); if (isNaN(elem.dataset.value)) { return; } new_data.push(((elem.dataset.value / total_discovered) * 100).toFixed(2)); }); sitemapGeneratorRequests.url_chart.data.datasets[0].data = new_data; sitemapGeneratorRequests.url_chart.update(); }, generateChartLegend: () => { const legend = $("#sg-chart-legend"); const pieDoughnutLegendClickHandler = Chart.controllers.doughnut.overrides.plugins.legend.onClick; let chart = sitemapGeneratorRequests.url_chart; chart.legend.legendItems.forEach((dataset, index) => { let elem_wrapper = $create("li", false, ["sg-chart-select"]); const wrapper = $create("div", false, ["r-flex"]); const span = $create("span"); const p = $create("p"); const text = document.createTextNode(dataset.text); const checkbox = $create("input"); checkbox.setAttribute("type", "checkbox"); span.style.borderColor = dataset.strokeStyle; span.style.backgroundColor = dataset.fillStyle; elem_wrapper.onclick = (click) => { pieDoughnutLegendClickHandler(click, dataset, chart.legend); const li = click.target.closest(".sg-chart-select"); li.classList.toggle("fade-chart-select"); checkbox.toggleAttribute("checked"); }; if ( text.nodeValue !== "Not processed" && text.nodeValue !== "Added urls" ) { elem_wrapper.click(); checkbox.removeAttribute("checked"); } else { checkbox.setAttribute("checked", "checked"); } p.appendChild(text); wrapper.appendChild(span); wrapper.appendChild(p); elem_wrapper.appendChild(wrapper); elem_wrapper.appendChild(checkbox); legend.appendChild(elem_wrapper); }); }, createPieChart: function () { var chrt = $("#sg-url-chart"); if (!chrt) { return false; } chrt = chrt.getContext("2d"); let total_discovered = $("#sg-total-urls").dataset.value; let total_added = $("#sg-added-urls").dataset.value; let chart_data = {}; if (isNaN(total_added)) { chart_data = { labels: ["No Data Collected"], datasets: [ { data: [100], backgroundColor: ["aqua"], hoverOffset: 5, }, ], }; } else { let labels = []; let data = []; const data_ids = [ "sg-total-not-processed", "sg-added-urls", "sg-broken-urls", "sg-ignored-urls", "sg-not-indexable", ]; chart_data["datasets"] = []; data_ids.forEach(function (id) { const elem = $("#" + id); if (isNaN(elem.dataset.value)) { return; } let label_name = id .replaceAll("-", " ") .replace("sg", "") .replace("total", "") .trim(); label_name = label_name.charAt(0).toUpperCase() + label_name.slice(1); labels.push(label_name); // chart_data["datasets"].push({ // data: ((elem.dataset.value / total_discovered) * 100).toFixed(2), // }); data.push(((elem.dataset.value / total_discovered) * 100).toFixed(2)); }); chart_data["labels"] = chart_data = { labels: labels, datasets: [ { data: data, backgroundColor: [ "gray", "#8ed9a2", "#d67070", "#d5a6f0", "lightgray", ], hoverOffset: 5, }, ], }; } this.url_chart ? this.url_chart.destroy() : null; this.url_chart = new Chart(chrt, { type: "doughnut", data: chart_data, options: { responsive: false, plugins: { legend: { display: false, position: "left", align: "start", labels: { // This more specific font property overrides the global property font: { size: 18, }, }, }, tooltip: { callbacks: { label: function (itm) { idx = itm["dataIndex"]; return itm["label"] + " - " + itm["dataset"]["data"][idx] + "%"; }, }, }, title: { display: false, text: ["Discovered URLs: " + total_discovered], font: { size: 25, }, position: "top", color: "#007CBD", }, datalabels: { anchor: "center", font: { size: "18px", }, formatter: function (value, context) { return value > 0 ? value + "%" : ""; }, }, }, }, plugins: [ChartDataLabels], }); this.generateChartLegend(); }, }; const seoReportRequests = { ...eventObject, report_status: $("#report-status") ? $("#report-status").value : null, classes: { ...eventObject.classes, "toggle-report-data": ["_handleToggleData", "click"], "item-name": ["_handleToggleInfo", "click"], "section-heading": ["_handleToggleSection", "click"], "summary-view-details": ["_handleFilterTests", "click"], }, ids: { ...eventObject.ids, "start-report": ["startReport", "click"], // "recommended-actions ul": ["_handleNavToggle", "click"], "report-nav": ["_handleNavToggle", "click"], }, score_chart: null, _handleFilterTests: function (ev) { const clicked = ev.target.closest("div"); const wrappers = $(".section-item-wrapper", true); wrappers.forEach(function (elem) { console.log(clicked.dataset.value); if (clicked.dataset.value === "all") { elem.style.display = "flex"; } else { if (elem.dataset.value !== clicked.dataset.value) { elem.style.display = "none"; } else { elem.style.display = "flex"; } } }); }, _handleToggleSection: function (ev) { const wrapper = ev.target.nextElementSibling; console.log(wrapper.style.maxHeight); if (wrapper.style.maxHeight == "0px" || wrapper.style.maxHeight == "") { wrapper.style.maxHeight = "2000px"; ev.target.classList.remove("section-collapse"); ev.target.classList.add("section-collapsed"); } else { ev.target.classList.remove("section-collapsed"); ev.target.classList.add("section-collapse"); wrapper.style.maxHeight = "0px"; } }, _handleToggleData: function (ev) { let holder = ev.target.parentElement.parentElement.children[1]; if (holder.classList.contains("d-none")) { ev.target.children[0].innerHTML = "Hide Details"; holder.classList.remove("d-none"); } else { ev.target.children[0].innerHTML = "View Details"; holder.classList.add("d-none"); } }, _handleToggleInfo: function (ev) { let holder = ev.target.parentElement.parentElement.querySelector(".item-info-wrapper"); if (holder.style.maxHeight === "0px" || holder.style.maxHeight == "") { holder.style.maxHeight = "800px"; holder.style.padding = "0 50px 10px 50px"; ev.target.parentElement.parentElement.style.marginBottom = "15px"; ev.target.parentElement.parentElement.classList.add("item-info-bg"); } else { holder.style.maxHeight = "0px"; holder.style.padding = "0px"; ev.target.parentElement.parentElement.classList.remove("item-info-bg"); ev.target.parentElement.parentElement.style.marginBottom = "0px"; } }, _handleNavToggle: function (ev) { //check if click is on navigation list if ( ev.target.parentElement.classList.contains("section-li") || ev.target.parentElement.classList.contains("report-nav-item-holder") ) { let ul = ev.target.parentElement.querySelector("ul") || ev.target.parentElement.parentElement.querySelector("ul"); let collapsible = ul.previousElementSibling.children[0]; if (ul.style.maxHeight == "0px" || ul.style.maxHeight == "") { ul.style.maxHeight = "500px"; collapsible .closest(".collapsible") .classList.add("collapsible-collapsed"); collapsible.closest(".collapsible").classList.remove("collapsible"); } else { ul.style.maxHeight = "0px"; collapsible .closest(".collapsible-collapsed") .classList.add("collapsible"); collapsible .closest(".collapsible-collapsed") .classList.remove("collapsible-collapsed"); } } else { //check if target contains span. this is for recommended list let is_span = ev.target.querySelector("span"); let span_name; if (is_span) { span_name = is_span.innerHTML .trim() .replace(".", "-") .replaceAll(" ", "-") .toLowerCase() .replace("/", "-"); } else { span_name = ev.target.innerHTML .trim() .replace(".", "-") .replaceAll(" ", "-") .toLowerCase() .replace("/", "-"); } console.log(span_name); window.scroll(0, findPosition($('[data-nav|="' + span_name + '"]'))); } function findPosition(obj) { var currenttop = 0; console.log(obj); if (obj.offsetParent) { do { currenttop += obj.offsetTop; } while ((obj = obj.offsetParent)); return [currenttop - 100]; } } }, create_report_nav: function (ev) { const headings = $(".section-heading", true); const section_navs = $(".section-li", true); headings.forEach(function (elem, idx) { let child_ul = document.createElement("ul"); child_ul.classList.add("report-child-nav"); let main_li = Array.from(section_navs).find( (to_find) => to_find.children[0].children[0].innerHTML == elem.children[0].innerHTML ); main_li.appendChild(child_ul); let names = elem.parentElement.querySelectorAll(".item-name"); let passed = 0; names.forEach(function (nm) { let classes = nm.classList; // classes.remove("fw", "item-name") let second_li = $create("li"); let second_span = $create("span", false, [ "report-nav-item", classes[2], ]); // second_span.classList.add("report-nav-item", classes[2]); classes.contains("passed-test") || classes.contains("info-test") ? passed++ : null; // classes[2] == "passed-test" ? passed++ : null; // classes[2] == "info-test" ? passed++ : null; second_span.innerHTML = nm.innerHTML; second_li.appendChild(second_span); child_ul.appendChild(second_li); }); main_li.children[0].children[1].innerHTML = passed + "/" + names.length; elem.parentElement.querySelector(".section-score").innerHTML = passed + "/" + names.length + " Passed Tests"; }); // $("#left-section").children[0].appendChild(ul) }, updateChart: function () { seoReportRequests.score_chart.data.datasets[0].data = [ $(".total-passed").dataset.value, $(".total-failed").dataset.value, $(".total-warning").dataset.value, ]; seoReportRequests.score_chart.data.datasets[0].backgroundColor = [ "#198754", "#DC3545", "#FFC107", ]; seoReportRequests.score_chart.update(); }, addScoreText: function () { const score_messages = { 10: "Awful!", 25: "Very Bad!", 50: "Bad!", 65: "Improvements are required!", 75: "Can do better!", 80: "Pretty good!", 90: "Well Optimised!", 100: "Excellent!", }; let score = $("#score-value").value; let vals = Object.keys(score_messages); highest = vals.find((el) => el > parseInt(score)); const score_text = $("#score-text"); if (highest) { let ind = vals.indexOf(highest); if (ind > 0) { score_text.innerHTML = score_messages[vals[ind - 1]]; } else { score_text.innerHTML = score_messages[10]; } } else { score_text.innerHTML = score_messages[100]; } }, update_report_results: function (results) { if (!results) { return; } if (results.length === undefined) { results = [results]; } for (const elem of results) { $(".progress").style.width = (elem.rs["total-tests"] / 25) * 100 + "%"; $(".indicator").innerHTML = (elem.rs["total-tests"] / 25) * 100 + "%"; $(".total-failed").innerHTML = elem.rs["total-failed"]; $(".total-failed").dataset.value = elem.rs["total-failed"]; $(".total-passed").innerHTML = elem.rs["total-passed"]; $(".total-passed").dataset.value = elem.rs["total-passed"]; $(".total-warning").innerHTML = elem.rs["warnings"]; $(".total-warning").dataset.value = elem.rs["warnings"]; $(".total-tests").innerHTML = elem.rs["total-tests"]; $(".total-tests").dataset.value = elem.rs["total-tests"]; $("#score-value").setAttribute("value", elem.rs.score); $("#score-indicator").innerHTML = elem.rs.score; $("#processing-score").innerHTML = elem.rs.score; let name = elem.ct.test.replace(".", "-").replace("/", "-").toLowerCase(); let item_name = $("[data-nav=" + name + "]"); if (item_name.closest(".section-item-wrapper").dataset.value) { continue; } let item_wrapper = item_name.parentElement.parentElement.parentElement; // item_wrapper.querySelector(".loader").remove(); item_wrapper.querySelector(".loader-wrapper").style.display = "none"; item_name.classList.remove("item-loading"); item_name.classList.add(elem.ct.status + "-test"); item_name .closest(".section-item-wrapper") .setAttribute("data-value", elem.ct.status); if (elem.ct.messages && elem.ct.messages !== "-") { let message_holder = create_message_holder(elem.ct); item_wrapper.appendChild(message_holder); } if (elem.ct.data) { if (elem.ct.data["text-content"]) { let content_wrapper = document.createElement("div"); content_wrapper.classList.add("item-content-wrapper"); let content_holder = display_content(elem.ct.data); content_wrapper.appendChild(content_holder); if (elem.ct.test == "robots" || elem.ct.test == "http-headers") { content_wrapper.classList.add("w-100", "p-0"); content_wrapper .querySelector(".content-holder") .classList.add("w-100"); } item_wrapper.appendChild(content_wrapper); delete elem.ct.data["text-content"]; } if (Object.keys(elem.ct.data).length > 0) { let results_wrapper = document.createElement("div"); results_wrapper.classList.add("check-results-wrapper"); let data_holder = create_results_holder(elem.ct); results_wrapper.appendChild(data_holder); item_wrapper.appendChild(results_wrapper); } } } function create_message_holder(test) { let message_holder = document.createElement("div"); message_holder.classList.add("item-messages-wrapper"); let message_wrapper = document.createElement("div"); message_wrapper.classList.add( test.status + "-audits-messages", "report-messages" ); let span = document.createElement("span"); span.classList.add("d-block"); let message = test.messages; if (message.includes("%value")) { message = message.replace("%value", test.data["value"]); delete test.data["value"]; } span.innerHTML = parse_report_html(message); message_holder.appendChild(message_wrapper); message_wrapper.appendChild(span); return message_holder; } function parse_report_html(text) { return text.replaceAll("[b]", "").replaceAll("[/b]", ""); } function create_results_holder(test) { // console.log(test.test); switch (test.test) { case "most-common-keywords": return common_keywords_table(test.data); case "h2-tags": return simple_seo_list(test.data); case "link-ratio": return simple_seo_list(test.data); case "heading-order": return heading_list(test.data); // case "title": // return meta_tag_display(test.data); // case "description": // return meta_tag_display(test.data); case "google-preview": return google_preview(test.data); case "sitemap": return stiemap_results(test); // case "opengraph": // return check_results(test.data); default: // console.log(test) return check_results(test.data, test.test); } } function meta_tag_display(data) { const holder = $create("div"); const content_span = $create("span"); const info_span = $create("span"); data = data[0]; content_span.innerHTML = data["text-content"]; const info_1 = $create("span"); const info_2 = $create("span"); info_1.innerHTML = data["check-results"]["character-count"]; info_2.innerHTML = data["check-results"]["recommended-limit"]; info_span.appendChild(info_1); info_span.appendChild(info_2); holder.appendChild(content_span); holder.appendChild(info_span); return holder; } function google_preview(data) { let html = `
Keyword | \n\Frequency | \n\Title | \n\Description | \n\H-tags | \n\Density | "; html += "
---|---|---|---|---|---|
${word} | `; for (const key in data[word]) { html += `${data[word][key]} | `; } html += "