Last active
April 2, 2020 03:49
-
-
Save igorbenic/6f950d98aa037d3923939213d8803d79 to your computer and use it in GitHub Desktop.
How to Create a Sortable WordPress Gallery | http://www.ibenic.com/create-sortable-wordpress-gallery/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.sortable_wordpress_gallery li.attachment { | |
width: 141px; | |
height: 141px; | |
} | |
.sortable_wordpress_gallery { | |
display: block; | |
} | |
.sortable_wordpress_gallery:after { | |
display: table; | |
content: ''; | |
clear: both; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function sortable_image_gallery_media( $imageContainer, $imageInput ) { | |
'use strict'; | |
var file_frame; | |
/** | |
* If an instance of file_frame already exists, then we can open it | |
* rather than creating a new instance. | |
*/ | |
if ( undefined !== file_frame ) { | |
file_frame.open(); | |
return; | |
} | |
/** | |
* If we're this far, then an instance does not exist, so we need to | |
* create our own. | |
* | |
* Here, use the wp.media library to define the settings of the Media | |
* Uploader. We're opting to use the 'post' frame which is a template | |
* defined in WordPress core and are initializing the file frame | |
* with the 'insert' state. | |
* | |
* We're also not allowing the user to select more than one image. | |
*/ | |
file_frame = wp.media({ | |
multiple: true, | |
}); | |
file_frame.on('open',function() { | |
var selection = file_frame.state().get('selection'); | |
var ids = $imageInput.val().split(','); | |
ids.forEach(function(id) { | |
var attachment = wp.media.attachment(id); | |
attachment.fetch(); | |
selection.add( attachment ? [ attachment ] : [] ); | |
}); | |
}); | |
// When an image is selected in the media frame... | |
file_frame.on( 'select', function() { | |
// Get media attachment details from the frame state | |
var attachments = file_frame.state().get('selection').toJSON(); | |
var attachmentIDs = []; | |
$imageContainer.empty(); | |
var $galleryID = $imageContainer.attr("id"); | |
for( var i = 0; i < attachments.length; i++ ) { | |
if( attachments[ i ].type == "image" ) { | |
attachmentIDs.push( attachments[ i ].id ); | |
$imageContainer.append( sortable_gallery_image_create( attachments[ i ], $galleryID ) ); | |
} | |
} | |
$imageInput.val( attachmentIDs.join() ); | |
sortable_gallery_image_remove(); | |
}); | |
// Now display the actual file_frame | |
file_frame.open(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function sortable_gallery_image_create( $attachment, $galleryID ) { | |
var $output = '<li tabindex="0" role="checkbox" aria-label="' + $attachment.title + '" aria-checked="true" data-id="' + $attachment.id + '" class="attachment save-ready selected details">'; | |
$output += '<div class="attachment-preview js--select-attachment type-image subtype-jpeg portrait">'; | |
$output += '<div class="thumbnail">' | |
$output += '<div class="centered">' | |
$output += '<img src="' + $attachment.sizes.thumbnail.url + '" draggable="false" alt="">' | |
$output += '</div>' | |
$output += '</div>' | |
$output += '</div>' | |
$output += '<button type="button" data-gallery="#' + $galleryID + '" class="button-link check asap-image-remove" tabindex="0"><span class="media-modal-icon"></span><span class="screen-reader-text">Deselect</span></button>' | |
$output += '</li>'; | |
return $output; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function sortable_gallery_image_remove( ) { | |
jQuery(".remove-sortable-wordpress-gallery-image").on( 'click', function(){ | |
$id = jQuery(this).parent().attr("data-id"); | |
$gallery = jQuery(this).attr("data-gallery"); | |
$imageInput = jQuery( $gallery + "_input" ); | |
jQuery(this).parent().remove(); | |
var ids = $imageInput.val().split(','); | |
$idIndex = ids.indexOf( $id ); | |
if( $idIndex >= 0 ) { | |
ids.splice( $idIndex, 1 ); | |
$imageInput.val( ids.join() ); | |
} | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($){ | |
$(document).ready(function(){ | |
var imageButton = $(".add-sortable-wordpress-gallery"); | |
sortable_gallery_image_remove(); | |
imageButton.each( function(){ | |
var galleryID = $(this).attr("data-gallery"); | |
var imageContainer = $( galleryID ); | |
var imageInput = $( galleryID + "_input" ); | |
imageContainer.sortable(); | |
imageContainer.on( "sortupdate", function( event, ui ) { | |
$ids = []; | |
$images = imageContainer.children("li"); | |
$images.each( function(){ | |
$ids.push( $(this).attr("data-id") ); | |
}); | |
imageInput.val($ids.join()); | |
} ); | |
$(this).on('click', function(){ | |
sortable_image_gallery_media( imageContainer, imageInput ); | |
}); | |
}); | |
}); | |
})(jQuery) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
add_filter( 'sortable_wordpress_galleries', 'add_sortable_gallery' ); | |
function add_sortable_gallery( $galleries ) { | |
$galleries[] = array( | |
'class' => 'Sortable_WordPress_Gallery', | |
'id' => 'post-metabox', | |
'title' => 'Sortable Gallery' | |
); | |
return $galleries; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
add_filter( 'sortable_wordpress_galleries', 'add_sortable_gallery' ); | |
function add_sortable_gallery( $galleries ) { | |
$galleries[] = array( | |
'class' => 'Sortable_WordPress_Gallery', | |
'id' => 'post-metabox', | |
'title' => 'Sortable Gallery' | |
); | |
$galleries[] = array( | |
'class' => 'Sortable_WordPress_Gallery', | |
'id' => 'post-metabox-2', | |
'title' => 'Sortable Gallery-2' | |
); | |
return $galleries; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
add_filter( 'sortable_wordpress_gallery_post-metabox-2_post_types', 'second_gallery_only_on_page' ); | |
function second_gallery_only_on_page( $post_types ) { | |
return array( 'page' ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* WordPress Gallery Factory | |
*/ | |
class Sortable_WordPress_Galleries { | |
/** | |
* Gallery Defaults | |
* @var array | |
*/ | |
protected $gallery_defaults = array( | |
'class' => 'Sortable_WordPress_Gallery', | |
'id' => '', | |
'title' => '', | |
'context' => '', | |
'priority' => '' ); | |
/** | |
* Galleries that have been registered to use | |
* @var array | |
*/ | |
protected $galleries = array(); | |
/** | |
* Loaded galleries (Gallery objects) | |
* @var array | |
*/ | |
protected $loaded_galleries = array(); | |
/** | |
* Constructor method | |
*/ | |
public function __construct() { | |
add_action( 'init', array( $this, 'collect_galleries') ); | |
add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) ); | |
add_action( 'admin_init', array( $this, 'create_galleries' ) ); | |
add_filter( 'the_content', array( $this, 'render_galleries' ) ); | |
} | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* WordPress Gallery Factory | |
*/ | |
class Sortable_WordPress_Galleries { | |
// ... | |
/** | |
* Enqueuing admin scripts and styles | |
*/ | |
public function admin_scripts() { | |
wp_enqueue_script( 'sortable-gallery-admin-js', plugin_dir_url( __FILE__ ). 'admin.js', array( 'jquery' ) ); | |
wp_enqueue_style( 'sortable-gallery-admin-css', plugin_dir_url( __FILE__ ). 'admin.css' ); | |
} | |
/** | |
* Collect galleries passed to our filter | |
*/ | |
public function collect_galleries() { | |
$this->galleries = apply_filters( 'sortable_wordpress_galleries', $this->galleries ); | |
} | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* WordPress Gallery Factory | |
*/ | |
class Sortable_WordPress_Galleries { | |
// ... | |
/** | |
* Hook our method load_galleries on edit post screens | |
*/ | |
public function create_galleries() { | |
add_action( 'load-post.php', array( $this, 'load_galleries' ) ); | |
add_action( 'load-post-new.php', array( $this, 'load_galleries' ) ); | |
} | |
/** | |
* Create gallery objects to create metaboxes | |
*/ | |
public function load_galleries() { | |
foreach ( $this->galleries as $gallery ) { | |
$gallery = wp_parse_args( $gallery, $this->gallery_defaults ); | |
$class = $gallery['class']; | |
if( $class != '' ) { | |
$this->loaded_galleries[] = new $class( $gallery['id'], $gallery['title'], $gallery['context'], $gallery['priority'] ); | |
} | |
} | |
} | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* WordPress Gallery Factory | |
*/ | |
class Sortable_WordPress_Galleries { | |
// ... | |
/** | |
* Load all the galleries and render each gallery | |
*/ | |
public function render_galleries( $content ) { | |
$this->load_galleries(); | |
foreach ( $this->loaded_galleries as $gallery ) { | |
$content = $gallery->render( $content ); | |
} | |
return $content; | |
} | |
} | |
// Let's power this! Instantiate it where you want just by using this. | |
new Sortable_WordPress_Galleries() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Sortable WordPress Gallery class to create gallery metabox and save it | |
*/ | |
class Sortable_WordPress_Gallery { | |
/** | |
* Unique ID of the metabox | |
* @var string | |
*/ | |
protected $id; | |
/** | |
* Metabox Title | |
* @var string | |
*/ | |
protected $title = ''; | |
/** | |
* Metabox Context | |
* @var string | |
*/ | |
protected $context = 'advanced'; | |
/** | |
* Metabox Priority | |
* @var string | |
*/ | |
protected $priority = 'high'; | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Sortable WordPress Gallery class to create gallery metabox and save it | |
*/ | |
class Sortable_WordPress_Gallery { | |
// ... | |
/** | |
* Hook into the appropriate actions when the class is constructed. | |
*/ | |
public function __construct( $id, $title = '', $context = 'advanced', $priority = 'high' ) { | |
// ID is required | |
if( $id == '' ) { | |
return; | |
} | |
$this->id = $id; | |
// Create title from ID if not provided | |
if( $title == '' ) { | |
$this->title = ucfirst( $id ); | |
} else { | |
$this->title = $title; | |
} | |
// Only valid context can be changed | |
$available_context = array( | |
'advanced', | |
'side', | |
'normal'); | |
if( in_array( $context, $available_context ) ) { | |
$this->context = $context; | |
} | |
// Only valid priorty can be changed | |
$available_priority = array( | |
'default', | |
'high', | |
'low'); | |
if( in_array( $priority, $available_priority ) ) { | |
$this->priority = $priority; | |
} | |
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) ); | |
add_action( 'save_post', array( $this, 'save' ) ); | |
add_filter( 'the_content', array( $this, 'render' ) ); | |
} | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Sortable WordPress Gallery class to create gallery metabox and save it | |
*/ | |
class Sortable_WordPress_Gallery { | |
// ... | |
/** | |
* Adds the meta box container. | |
*/ | |
public function add_meta_box( $post_type ) { | |
// Limit meta box to certain post types. | |
// Can be extended using filter 'sortable_wordpress_gallery_post_types' or | |
// using a dynamic filter 'sortable_wordpress_gallery_METABOX-ID_post_types' | |
$post_types = apply_filters( 'sortable_wordpress_gallery_post_types', array( 'post' ) ); | |
$post_types = apply_filters( 'sortable_wordpress_gallery_' . $this->id . '_post_types', $post_types ); | |
if ( in_array( $post_type, $post_types ) ) { | |
add_meta_box( | |
$this->id, | |
$this->title, | |
array( $this, 'render_meta_box_content' ), | |
$post_type, | |
$this->context, | |
$this->priority | |
); | |
} | |
} | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Sortable WordPress Gallery class to create gallery metabox and save it | |
*/ | |
class Sortable_WordPress_Gallery { | |
// ... | |
/** | |
* Render Meta Box content. | |
* | |
* @param WP_Post $post The post object. | |
*/ | |
public function render_meta_box_content( $post ) { | |
// Add an nonce field so we can check when saving | |
wp_nonce_field( $this->id . '_metabox', $this->id . '_metabox_nonce' ); | |
// Get the gallery saved data | |
$sortable_gallery = get_post_meta( $post->ID, '_' . $this->id . '_sortable_wordpress_gallery', true ); | |
?> | |
<table class="table"> | |
<tr> | |
<th style="vertical-align: top;"> | |
<?php _e( 'Slider Images', 'your_text_domain' ); ?> | |
</th> | |
<td> | |
<!-- Creating a dynamic ID using the metabox ID for JavaScript--> | |
<ul id="<?php echo $this->id; ?>_sortable_wordpress_gallery" class="sortable_wordpress_gallery"> | |
<?php | |
// Getting all the image IDs by creating an array from string ( 1,3,5 => array( 1, 3, 5) ) | |
$gallery = explode(",", $sortable_gallery ); | |
// If there is any ID, create the image for it | |
if( count( $gallery ) > 0 && $gallery[0] != '' ) { | |
foreach ( $gallery as $attachment_id ) { | |
// Create a LI elememnt | |
$output = '<li tabindex="0" role="checkbox" aria-label="' . get_the_title( $attachment_id ) . '" aria-checked="true" data-id="' . $attachment_id . '" class="attachment save-ready selected details">'; | |
// Create a container for the image. (Copied from the WP Media Library Modal to use the same styling) | |
$output .= '<div class="attachment-preview js--select-attachment type-image subtype-jpeg portrait">'; | |
$output .= '<div class="thumbnail">'; | |
$output .= '<div class="centered">'; | |
// Get the URL to that image thumbnail | |
$output .= '<img src="' . wp_get_attachment_thumb_url( $attachment_id ) . '" draggable="false" alt="">'; | |
$output .= '</div>'; | |
$output .= '</div>'; | |
$output .= '</div>'; | |
// Add the button to remove this image if wanted (we set the data-gallery to target the correct gallery if there are more than one) | |
$output .= '<button type="button" data-gallery="#' . $this->id . '_sortable_wordpress_gallery" class="button-link check remove-sortable-wordpress-gallery-image" tabindex="0"><span class="media-modal-icon"></span><span class="screen-reader-text">Deselect</span></button>'; | |
$output .= '</li>'; | |
echo $output; | |
} | |
} | |
?> | |
</ul> | |
<!-- Hidden input used to save the gallery image IDs into the database --> | |
<!-- We are also creating dynamic IDs here so that we can easily target them in JavaScript --> | |
<input type="hidden" id="<?php echo $this->id; ?>_sortable_wordpress_gallery_input" name="_<?php echo $this->id; ?>_sortable_wordpress_gallery" value="<?php echo $sortable_gallery; ?>" /> | |
<!-- Button used to open the WordPress Media Library Modal --> | |
<button type="button" class="button button-primary add-sortable-wordpress-gallery" data-gallery="#<?php echo $this->id; ?>_sortable_wordpress_gallery"><?php _e( 'Add Images', 'your_text_domain' ); ?></button> | |
</td> | |
</tr> | |
</table> | |
<?php | |
} | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Sortable WordPress Gallery class to create gallery metabox and save it | |
*/ | |
class Sortable_WordPress_Gallery { | |
// ... | |
/** | |
* Save the meta when the post is saved. | |
* | |
* @param int $post_id The ID of the post being saved. | |
*/ | |
public function save( $post_id ) { | |
/* | |
* We need to verify this came from the our screen and with proper authorization, | |
* because save_post can be triggered at other times. | |
*/ | |
// Check if our nonce is set. | |
if ( ! isset( $_POST[ $this->id . '_metabox_nonce'] ) ) { | |
return $post_id; | |
} | |
$nonce = $_POST[ $this->id . '_metabox_nonce']; | |
// Verify that the nonce is valid. | |
if ( ! wp_verify_nonce( $nonce, $this->id . '_metabox' ) ) { | |
return $post_id; | |
} | |
/* | |
* If this is an autosave, our form has not been submitted, | |
* so we don't want to do anything. | |
*/ | |
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { | |
return $post_id; | |
} | |
// Check the user's permissions. | |
if ( 'page' == $_POST['post_type'] ) { | |
if ( ! current_user_can( 'edit_page', $post_id ) ) { | |
return $post_id; | |
} | |
} else { | |
if ( ! current_user_can( 'edit_post', $post_id ) ) { | |
return $post_id; | |
} | |
} | |
/* OK, it's safe for us to save the data now. */ | |
$gallery = sanitize_text_field( $_POST[ '_' . $this->id . '_sortable_wordpress_gallery' ] ); | |
// Update the meta field. | |
update_post_meta( $post_id, '_' . $this->id . '_sortable_wordpress_gallery', $gallery ); | |
} | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Sortable WordPress Gallery class to create gallery metabox and save it | |
*/ | |
class Sortable_WordPress_Gallery { | |
// ... | |
/** | |
* Rendering the gallery | |
*/ | |
public function render( $content ) { | |
global $post; | |
// Get our registered post types | |
$post_types = apply_filters( 'sortable_wordpress_gallery_post_types', array( 'post' ) ); | |
$post_types = apply_filters( 'sortable_wordpress_gallery_' . $this->id . '_post_types', $post_types ); | |
// Get current post type | |
$this_post_type = get_post_type( $post ); | |
// If the current post type is also a registered post type, create the gallery | |
if( in_array( $this_post_type, $post_types ) ) { | |
// Get all the image IDs | |
$gallery_images = get_post_meta( $post->ID, '_' . $this->id . '_sortable_wordpress_gallery', true ); | |
if( $gallery_images != '' ) { | |
// If the data retrieved is not empty, create an array | |
$gallery_images_array = explode( ',', $gallery_images ); | |
//Create a gallery container with the 3 column layout | |
$content .= '<div class="gallery gallery-columns-3">'; | |
// For each image ID, create the gallery image | |
foreach ( $gallery_images_array as $image_id ) { | |
$html = wp_get_attachment_image( $image_id ); | |
if( $html == '' ) { | |
continue; | |
} | |
$content .= '<figure class="gallery-item">'; | |
$content .= '<a href="' . get_permalink( $image_id ) . '" target="_blank">'; | |
$content .= $html; | |
$content .= '</a>'; | |
$content .= '</figure>'; | |
} | |
$content .= '</div>'; | |
} | |
} | |
return $content; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment