Skip to content

Instantly share code, notes, and snippets.

@felipemarcos
Last active August 9, 2024 04:49
Show Gist options
  • Save felipemarcos/21c7f93290e0ea4b5864ac9ec42c43d0 to your computer and use it in GitHub Desktop.
Save felipemarcos/21c7f93290e0ea4b5864ac9ec42c43d0 to your computer and use it in GitHub Desktop.
Breakdance - Loading a page with AJAX and initializing its scripts
/*
* Explanation:
* When rendering a Breakdance Page via ajax, we need to manually append the styles and scripts that are needed for the page to function properly.
* This is because Breakdance pages conditionally load their assets based on the page's content, and we can't predict which assets will be needed if we're loading the page via AJAX.
*/
async function openQuickView() {
const body = new FormData();
const postId = 2928; // The post ID you want to load via AJAX
body.append("action", "breakdance_quickview");
body.append("postId", postId);
const { makeAjaxRequest } = window.BreakdanceFrontend.utils;
const response = await makeAjaxRequest(BreakdanceFrontend.data.ajaxUrl, {
method: "POST",
credentials: "same-origin",
body
});
const { data } = await response.json();
const styles = [...data.styles, ...data.postStyles];
// Show the popup for demonstration purposes, you can remove this line
showMockPopup();
if (data.html) {
// Do your thing with the response HTML
document.querySelector("#quick-view-content").innerHTML = data.html;
}
// Append scripts to the head
const scriptPromises = [];
if (data.scripts) {
data.scripts.forEach(scriptUrl => {
const scriptEle = document.createElement("script");
scriptEle.src = scriptUrl;
const scriptPromise = new Promise((resolve, reject) => {
scriptEle.onload = resolve;
scriptEle.onerror = reject;
});
document.head.appendChild(scriptEle);
scriptPromises.push(scriptPromise);
});
}
// Append styles to the head
const stylePromises = [];
if (styles) {
styles.forEach(styleUrl => {
const linkEle = document.createElement("link");
linkEle.rel = "stylesheet";
linkEle.href = styleUrl;
const stylePromise = new Promise((resolve, reject) => {
linkEle.onload = resolve;
linkEle.onerror = reject;
});
document.head.appendChild(linkEle);
stylePromises.push(stylePromise);
});
}
// Wait for all scripts to load before running inline scripts
await Promise.all(scriptPromises);
await Promise.all(stylePromises);
// Append inline scripts to the body
if (data.inlineScripts) {
data.inlineScripts.forEach(scriptText => {
const scriptEle = document.createElement("script");
scriptEle.textContent = scriptText;
document.body.appendChild(scriptEle);
});
}
}
// Demonstration purposes only
function showMockPopup() {
document.querySelector("#quick-view-popup").style.display = "flex";
}
function mockUI() {
const { isBuilder } = window.BreakdanceFrontend.utils;
if (isBuilder()) return;
document.body.insertAdjacentHTML(
"beforeend",
`
<div id="quick-view-popup">
<div id="quick-view-content"></div>
</div>
<button id="quick-view-trigger">Open Quick View</button
`);
// Add inline styles for demonstration purposes
document.head.insertAdjacentHTML(
"beforeend",
`
<style>
#quick-view-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: none;
justify-content: center;
align-items: center;
}
#quick-view-content {
background-color: white;
padding: 20px;
border-radius: 5px;
max-width: 600px;
}
#quick-view-trigger {
margin: 50px;
}
</style>
`
);
}
// End of demonstration purposes only
document.addEventListener("DOMContentLoaded", () => {
// For demonstration purposes, we're adding a button to the body. Feel free to remove this code in your implementation.
mockUI();
document
.querySelector('#quick-view-trigger')
.addEventListener('click', openQuickView);
});
<?php
/**
* Plugin Name: Breakdance - Cool Quickview
* Description: Load an element via AJAX and initialize its scripts and styles.
* Version: 1.0
* Author: Soflyy
*/
use Breakdance\Render\ScriptAndStyleHolder;
add_action('breakdance_loaded', function () {
\Breakdance\AJAX\register_handler(
'breakdance_quickview',
'cool_quickview_load_breakdance_element_via_ajax',
'none',
false,
[
'args' => [
'postId' => FILTER_VALIDATE_INT
],
],
true
);
});
function getPostsGeneratedCssFilePaths() {
$postsStyles = array_values(ScriptAndStyleHolder::getInstance()->getPostsGeneratedCssFilePaths());
$flattened = [];
foreach ($postsStyles as $item) {
$flattened = array_merge($flattened, array_values($item));
}
return $flattened;
}
function cool_quickview_load_breakdance_element_via_ajax() {
$postId = $_POST['postId'] ?? null;
$html = \Breakdance\Render\render($postId);
$dependencies = ScriptAndStyleHolder::getInstance()->dependencies;
$postStyles = getPostsGeneratedCssFilePaths();
return [
'data' => [
'html' => $html,
'styles' => $dependencies['styles'] ?? [],
'postStyles' => $postStyles,
'scripts' => $dependencies['scripts'] ?? [],
'inlineScripts' => $dependencies['inlineScripts'] ?? []
],
];
}
function cool_quickview_enqueue_script() {
wp_enqueue_script( 'breakdance-quickview', plugin_dir_url( __FILE__ ) . 'main.js' );
}
add_action('wp_enqueue_scripts', 'cool_quickview_enqueue_script');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment