2019-08-17, 11:55 AM
(This post was last modified: 2019-08-23, 08:35 PM by Harry K.. Edited 4 times in total.)
Hi guys,
Quick tutorial here on how to create some very simple and easy to use post preview using AJAX. I found a very handy jQuery function called .load(), which allows us to send an ajax request with parameters requesting a specific element on the page. I wanted to give it a try with something so I decided to create a little post preview java script plugin for MyBB. I wrote this based on the MyBB Community forums, not the default theme so please let me know if there are any compatibility issues.
As far as I'm aware, this won't be supported in IE11 due to the use of async await, however this could easily be modified to fix that, or use a polyfill.
The plugin stores fetched previews in an object ready for re-use to prevent sending too many requests.
On with the tutorial..
We're going to be using a data selector "[data-preview-post]" to target the posts we want to be able to preview. With this in mind we need to add this selector to each posts subject line.
Go to forumdisplay_thread:
- Find:
Once we have our selectors setup, we need to include the post_previews.js JavaScript file. Download the file, edit the config options and add to your jscripts folder, then point to it in your footer template before the closing </body> tag:
You can also add the js directly to your headerinclude template:
Finally, we need to style our previews. Here is some basic CSS to get you started, but there are endless possibilities!
Add to the bottom of global.css:
Please enjoy! This can be modified to work with any post's/content you like, this is just a very simple implementation.
Here is a gif of it working on MyBB.com
![[Image: EpZWeVM.gif]](https://camo.mybb.com/3bb58f3e6bb26f97a740c4d644dd6040d9046a00/68747470733a2f2f692e696d6775722e636f6d2f45705a5765564d2e676966)
Here is a good example of some of the things you can accomplish with the script above. The possibilities are endless, allowing you to provide a more user friendly, speedy and intuitive experience for your users. The JavaScript is on github if you would like to try and accomplish similar, the customisation were written for a heavily modified (and locally hosted) theme, so don't expect it to work without any edits!
Quick tutorial here on how to create some very simple and easy to use post preview using AJAX. I found a very handy jQuery function called .load(), which allows us to send an ajax request with parameters requesting a specific element on the page. I wanted to give it a try with something so I decided to create a little post preview java script plugin for MyBB. I wrote this based on the MyBB Community forums, not the default theme so please let me know if there are any compatibility issues.
As far as I'm aware, this won't be supported in IE11 due to the use of async await, however this could easily be modified to fix that, or use a polyfill.
The plugin stores fetched previews in an object ready for re-use to prevent sending too many requests.
On with the tutorial..
We're going to be using a data selector "[data-preview-post]" to target the posts we want to be able to preview. With this in mind we need to add this selector to each posts subject line.
Go to forumdisplay_thread:
- Find:
<span class="{$inline_edit_class} {$new_class}" id="tid_{$inline_edit_tid}">
- Replace with:<span class="{$inline_edit_class} {$new_class}" id="tid_{$inline_edit_tid}" data-preview-post="{$inline_edit_tid}">
Once we have our selectors setup, we need to include the post_previews.js JavaScript file. Download the file, edit the config options and add to your jscripts folder, then point to it in your footer template before the closing </body> tag:
<script src="{$mybb->asset_url}/jscripts/post_preview.js" defer></script>
Download from github: https://github.com/XigeTime/MyBB-Post-PreviewYou can also add the js directly to your headerinclude template:
<script>const post_preview = {
saved_posts: {},
options: {
/*
Fetch URL is the target thread's URL. This works with both the standard MyBB URL's and
SEO URL's. Any URL that has a unique thread id should work.
Grab any threads URL then replace the thread id with ${tid} then paste in the fetch URL section.
For example;
- https://example.com/thread-1111.html
becomes: https://example.com/thread-${tid}.html
- https://example.com/showthread.php?tid=1111
becomes: https://example.com/showthread.php?tid=${tid}
*/
// fetch url: tid => `https://example.com/showthread.php?tid=${tid}`
fetch_url: tid => `https://example/thread-${tid}.html`,
preview_class: "post_preview", // Class name for the container of the post preview.
fetch_selectors: {
body: ".post_body", // Class name of the post content
author: ".author_avatar", // Class name of the author's section.
},
preview_css: {
height: 100,
width: 500,
margin: 30, // distance in pixels the preview box should be from the post title
}
},
get_post: async (el,url) => {
url = `${url} ${post_preview.options.fetch_selectors.body}:eq(0)`;
await new Promise((resolve,reject) => {
$(el).load(url, (response,status,xhr) => {
if (status == "error") reject(xhr);
resolve(response);
})
})
.catch(xhr => console.log(`Unable to fetch post content: ${xhr.status}, ${xhr.statusText}`));
return el;
},
get_author: async (el,url) => {
url = `${url} ${post_preview.options.fetch_selectors.author}:eq(0)`;
await new Promise((resolve,reject) => {
$(el).load(url, { limit: 1 }, (response,status,xhr) => {
if (status == "error") reject(xhr);
resolve(response);
});
})
.catch(xhr => console.log(`Unable to fetch content: ${xhr.status}, ${xhr.statusText}`));
return el;
},
get_preview: async post => {
// create container for our post and author sections of the preview
let post_container = document.createElement("div");
let author = document.createElement("div");
author.setAttribute("class", "post_author");
// build fetch url
let url = post_preview.options.fetch_url(post);
// fetch post and author content
post_container = await post_preview.get_post(post_container, url);
author = await post_preview.get_author(author, url);
return { a: author, p: post_container };
},
preview: async e => {
if (!e) return;
// remove any lingering previews
post_preview.remove_previews();
let selector = e.target.closest("[data-preview-post]");
// build preview container
let preview_container = document.createElement("div");
preview_container.setAttribute("class", post_preview.options.preview_class);
// add a loader to the preview container for time being
let loader = document.createElement("span");
loader.id = "preview_loader";
loader.innerText = "Loading preview...";
preview_container.appendChild(loader);
// output preview with loader & position correctly against link
selector.appendChild(preview_container);
$(preview_container).css({
height: post_preview.options.preview_css.height + "px",
width: post_preview.options.preview_css.width + "px",
bottom: 40 + "px"
});
// extract requested post id from link url
let post_id = selector.dataset.previewPost;
// if we have already loaded this preview use that data otherwise send ajax request for page
let post;
if (!post_preview.saved_posts[post_id]) {
// send request
post = await post_preview.get_preview(post_id);
// save data so we don't need to request it again
post_preview.saved_posts[post_id] = post;
} else {
// if data is already available, simply use that
post = post_preview.saved_posts[post_id];
}
// remove loader and output our fetched data
loader.outerHTML = null;
post_preview.output_preview(preview_container,post)
},
output_preview: (container,output) => {
container.appendChild(output.a);
container.appendChild(output.p);
},
remove_previews: () => {
$("." + post_preview.options.preview_class).remove();
}
}
// add hover handler
$(document).ready(() => {
$("[data-preview-post]").hover((e) => {
post_preview.preview(e);
}, () => {
post_preview.remove_previews();
})
})</script>
Make sure you configure the options at the top of the javascript file!Finally, we need to style our previews. Here is some basic CSS to get you started, but there are endless possibilities!
Add to the bottom of global.css:
[data-preview-post] { position: relative }
.post_preview {
position: absolute;
background: white;
border-radius: 4px;
border: 1px solid #d4d4d4;
box-shadow: 1px 1px 3px #d4d4d4;
overflow: hidden;
display: flex;
align-items: flex-start;
justify-content: center;
padding: .5rem;
}
.post_preview > div:not(.post_author) {
padding: 0 10px;
height: 100%;
overflow: hidden;
}
.post_preview .post_body {
all: unset;
}
.post_preview > .post_author img {
border-radius: 100px;
height: 50px;
width: 50px;
}
.post_preview div br {display:none}
Please enjoy! This can be modified to work with any post's/content you like, this is just a very simple implementation.
Here is a gif of it working on MyBB.com
Here is a good example of some of the things you can accomplish with the script above. The possibilities are endless, allowing you to provide a more user friendly, speedy and intuitive experience for your users. The JavaScript is on github if you would like to try and accomplish similar, the customisation were written for a heavily modified (and locally hosted) theme, so don't expect it to work without any edits!