
Drag and Drop Page Builders make it easy to build responsive grid-based page content that adapts to mobile devices. It’s a whole new way of content creation that’ll help you create your home, contact, about us or any other page where a linear layout wonโt convey your message.
There are many advanced page builders such as Visual Composer and Elegant Page Builder.
In this tutorial I will show you how to create a simple drag and drop page builder. This can be helpful in many cases.
We will create a page builder in 5 simple steps with around 220 lines of code. Let’s get started
Gridster.js
We will use Gridster jQuery library to create our drag and drop page layout builder. It allows you to build intuitive draggable layouts by spanning elements in multiple columns. You can even dynamically add and remove elements from the grid.
Enqueue Gridster
Here is the code to enqueue Gridster in WordPress admin pages.
function load_admin_scripts()
{
wp_enqueue_style("gridster-style", "https://cdn.rawgit.com/ducksboard/gridster.js/master/dist/jquery.gridster.min.css", false);
wp_enqueue_script("jquery-gridster", "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js", false);
wp_enqueue_script("gridster-script", "https://cdn.rawgit.com/ducksboard/gridster.js/master/dist/jquery.gridster.min.js", false);
wp_enqueue_style("gridster-script-extra", "https://cdn.rawgit.com/ducksboard/gridster.js/master/dist/jquery.gridster.with-extras.min.js", false);
}
add_action("admin_enqueue_scripts", "load_admin_scripts");
?>
Here we are loading all the files from CDN but while creating a plugin for production use, you need to load them from filesystem.
Embed Drag and Drop Page Builder in Post Edit Screen
We will add drag and drop page builder in WordPress post edit pages. Here is code to do that
function meta_box_markup($object)
{
wp_nonce_field(basename(__FILE__), 'page-builder');
?>
<a href="javascript:add_widget();">Add Box</a>
<br>
<div style="background-color: grey; width: 750px;" class="gridster">
<ul></ul>
</div>
<input type="text" name="complete_layout_data" id="complete_layout_data" style="display: none">
<?php wp_editor("", "gridster_edit", array("tinymce" => false)); ?> <br><a href="javascript:save_edit();">Save Content</a>
<script type="text/javascript">
var gridster = null;
var currently_editing = null;
var saved_data = <?php echo json_encode(get_post_meta($object->ID, 'complete_layout_data', true)); ?>;
$(function(){
$(".gridster ul").gridster({
widget_base_dimensions: [200, 200],
resize: {
enabled: true,
stop: save,
axes: ['x']
},
draggable: {
stop: save
},
serialize_params: function($w, wgd){
var obj = {col: wgd.col, row: wgd.row, size_x: wgd.size_x, size_y: wgd.size_y, content: decodeURIComponent($w[0].getAttribute("data-content"))} ;
return obj;
}
});
gridster = $(".gridster ul").gridster().data('gridster');
saved_data = JSON.parse(saved_data);
for(var iii = 0; iii < saved_data.length; iii++)
{
gridster.add_widget("<li style='background-color: black; list-style: none;' data-content=""+encodeURIComponent(saved_data[iii].content)+""><button onclick="remove_widget(event);">Remove Box</button><button onclick="edit(event);">Edit</button></li>", saved_data[iii].size_x, saved_data[iii].size_y);
}
save();
});
function add_widget()
{
gridster.add_widget("<li style='background-color: black; list-style: none;' data-content=""><button onclick="remove_widget(event);">Remove Box</button><button onclick="edit(event);">Edit</button></li>", 1, 1);
save();
}
function remove_widget(e)
{
e.srcElement.parentNode.setAttribute("id", "remove_box");
gridster.remove_widget($('.gridster li#remove_box'));
save();
e.preventDefault();
}
function edit(e)
{
currently_editing = e.srcElement.parentNode;
document.getElementById("gridster_edit").value = decodeURIComponent(e.srcElement.parentNode.getAttribute("data-content"));
e.preventDefault();
}
function save_edit()
{
currently_editing.setAttribute("data-content", encodeURIComponent(document.getElementById("gridster_edit").value));
save();
}
function save()
{
var json_str = JSON.stringify(gridster.serialize());
document.getElementById("complete_layout_data").value = json_str;
}
</script>
<?php
}
function my_custom_meta_box()
{
add_meta_box("page-builder", "Page Builder", "meta_box_markup", "post", "normal", "default", null);
}
add_action("add_meta_boxes", "my_custom_meta_box");
?>
This is how the code works:
- We created a custom meta box to display the page builder.
div
element with classgridster
is the page builder container.- We have a button to add more layout elements and also every layout item has a remove button to remove it.
- We displayed the WordPress text editor using
wp_editor
function. This will hold contents of layout items. - Every layout item has an edit button to add or edit its contents. After clicking edit, you need to add contents to text area and then click “save content” button below the text area to save the content of the layout item.
- The invisible input element holds the complete layout and contents of every individual element in it.
Here is how it looks in admin panel
Now we need to save the value of the input field i.e., save the page builder configuration and content.
Save Custom Meta Box
Here is the code to save the layout and content
function save_my_custom_meta_box($post_id, $post, $update)
{
if (!isset($_POST["page-builder"]) || !wp_verify_nonce($_POST["page-builder"], basename(__FILE__)))
return $post_id;
if(!current_user_can("edit_post", $post_id))
return $post_id;
if(defined("DOING_AUTOSAVE") && DOING_AUTOSAVE)
return $post_id;
$slug = "post";
if($slug != $post->post_type)
return;
$complete_layout_data = "";
if(isset($_POST["complete_layout_data"]))
{
$complete_layout_data = $_POST["complete_layout_data"];
}
else
{
$complete_layout_data = "";
}
update_post_meta($post_id, "complete_layout_data", $complete_layout_data);
}
add_action("save_post", "save_my_custom_meta_box", 10, 3);
?>
Display the Page on Frontend
We created a custom meta box to build content of a page by drag and drop functionality. Now we need to display the content on frontend. To display the content we need to parse the custom meta box data and display accordingly. Here is the code to filter the content of posts
function page_builder_content_filter($content)
{
global $post;
if("post" == get_post_type())
{
$builder_content = json_decode(get_post_meta($post->ID, 'complete_layout_data', true));
$current_row = 0;
foreach($builder_content as $key => $value)
{
$con = $value->content;
$col = $value->col;
$row = $value->row;
$size_x = $value->size_x;
if($row == $current_row)
{
$content = $content . "";
if($size_x == 1)
{
$content = $content . "<div class='gridster-box gridster-box-width-one'>";
}
else if($size_x == 2)
{
$content = $content . "<div class='gridster-box gridster-box-width-two'>";
}
else if($size_x == 3)
{
$content = $content . "<div class='gridster-box gridster-box-width-three'>";
}
$content = $content . $con . "</div>";
}
else
{
if($current_row != 0)
{
$content = $content . "<div class='clear'></div></div>";
}
$content = $content . "<div class='gridster-box-holder'>";
$current_row = $row;
if($size_x == 1)
{
$content = $content . "<div class='gridster-box gridster-box-width-one'>";
}
else if($size_x == 2)
{
$content = $content . "<div class='gridster-box gridster-box-width-two'>";
}
else if($size_x == 3)
{
$content = $content . "<div class='gridster-box gridster-box-width-three'>";
}
$content = $content . $con . "</div>";
}
}
$content = $content . "</div>";
}
return $content;
}
add_filter("the_content", "page_builder_content_filter");
?>
Here we are just mirroring the backend created layout on frontend. Now we need to apply CSS to style and position the content.
Style and Position the Layout Builder Content
Here is the responsive CSS code to position the columns and content
function frontend_inline_css() {
$custom_css = "
.gridster-box-holder{
}
.gridster-box{
display: inline-block;
float: left;
}
.gridster-box-width-one{
width: 33%;
}
.gridster-box-width-two{
width: 66%;
}
.gridster-box-width-three{
width: 99%;
}
.clear{clear: both;}
@media only screen and (min-width: 320px) and (max-width: 768px) {
.gridster-box{
display: block;
float: none;
}
.gridster-box-width-one{
width: 100%;
}
.gridster-box-width-two{
width: 100%;
}
.gridster-box-width-three{
width: 100%;
}
}
";
echo "<style>".$custom_css."</style>";
}
add_action("wp_footer", "frontend_inline_css");
?>
Conclusion
We created quite a powerful responsive page builder. Now go ahead and extend its functionality. Now you can build a page builder which is more suitable for your site instead of using a third-party page builder.