In this blog post, we will discuss and resolve the common feature, display the URL preview like Facebook and WhatsApp.
The blog post provides two methods.
- Using WordPress Standards
- Using the Core PHP Curl.
HTML Code for WordPress.
If you have an existing input field, add the following input field class attribute and add the preview output div tag.
<input type="text" class="preview-url-input"> <div id="preview-url-output"></div>
WordPress action and filter functions.
Add this code snippet to your active WordPress theme functions.php file.
add_action('wp_footer', 'url_preview_footer_js');
function url_preview_footer_js(){
$ajax_nonce = wp_create_nonce( "url-preview-ajax-security" );
?>
<script>
(function ($) {
'use strict';
$('.preview-url-input').on("keyup", function() {
$("#output").html("");
$("#loader").show();
var previewAjaxUrl = '<?php echo admin_url('admin-ajax.php') ?>';
var remote_url = $(this).val();
var image_html = '';
var total_images = 0;
var current_image_position = 0;
var data = {
action: 'UrlPreviewAjax',
security: '<?php echo $ajax_nonce; ?>',
url: remote_url
};
$.ajax({
type: 'POST',
dataType: 'json',
url: previewAjaxUrl,
data: data,
beforeSend : function () {
$('#preview-url-loader').html('Processing! Please wait!!');
},
success: function (response) {
console.log(response);
if(response.status == 'error'){
$("#preview-url-output").html(response.msg).show();
$("#preview-url-loader").hide();
} else {
if(response.image_src.length) {
//image_src = response.image_src;
total_images = parseInt(response.image_src.length-1);
current_image_position = total_images;
if(total_images>=0){
image_html = '<div class="image-preview" id="image-preview"><img src="'+response.image_src[current_image_position]+'"></div>';
}
}
var cotent_html = '<div class="text-data"><a class="page-title" href="'+remote_url+'" target="_blank">'+response.title+'</a><div>'+response.body+'</div>';
var responseHTML = '<div class="content-container">'+image_html + cotent_html+'</div>';
$("#preview-url-output").html(responseHTML).show();
$("#preview-url-loader").hide();
}
},
error : function (jqXHR, textStatus, errorThrown) {
//console.log(jqXHR, textStatus, errorThrown);
$("#preview-url-output").html("Problem in extracting data from the remote URL").show();
$("#preview-url-loader").hide();
}
});
});
})(jQuery);
</script>
<?php
}
add_action('wp_ajax_UrlPreviewAjax', 'ajax_get_url_preview');
function ajax_get_url_preview(){
if ( ! check_ajax_referer( 'url-preview-ajax-security', 'security', false ) ){
$returnMessage['msg'] = __('Not able to process. Trying unauthorized data access.', 'preview');
$returnMessage['status'] = 'error';
echo json_encode( $returnMessage );
wp_die();
} else {
if (isset($_POST["url"]) && filter_var($_POST["url"], FILTER_VALIDATE_URL)) {
$endpoint = $_POST["url"];
$response = wp_remote_get( $endpoint, array(
'method' => 'GET',
)
);
$res_body = wp_remote_retrieve_body($response);
// Load HTML to DOM Object
$dom = new DOMDocument();
@$dom->loadHTML($res_body);
// Parse DOM to get Title
$nodes = $dom->getElementsByTagName('title');
$title = $nodes->item(0)->nodeValue;
// Parse DOM to get Meta Description
$metas = $dom->getElementsByTagName('meta');
$body = "";
$feature_img = '';
for ($i = 0; $i < $metas->length; $i ++) {
$meta = $metas->item($i);
if ($meta->getAttribute('name') == 'description') {
$body = $meta->getAttribute('content');
}
else if ($meta->getAttribute('property') == 'og:description' || $meta->getAttribute('name') == 'og:description') {
$body = $meta->getAttribute('content');
}
if ($meta->getAttribute('property') == 'og:image' || $meta->getAttribute('name') == 'og:image') {
$feature_img = $meta->getAttribute('content');
}
}
// Parse DOM to get Images
$image_urls = array();
$images = $dom->getElementsByTagName('img');
if($feature_img == ''){
for ($i = 0; $i < $images->length; $i ++) {
$image = $images->item($i);
$src = $image->getAttribute('src');
if(filter_var($src, FILTER_VALIDATE_URL)) {
$image_src[] = $src;
}
}
}else{
$image_src[] = $feature_img;
}
$output = array(
'title' => $title,
'image_src' => $image_src,
'body' => $body
);
echo json_encode($output);
wp_die();
} else {
$returnMessage['msg'] = __('Not a valid URL.', 'preview');
$returnMessage['status'] = 'error';
echo json_encode( $returnMessage );
wp_die();
}
}
}
add_action('wp_head', 'url_preview_styling' );
function url_preview_styling(){
?>
<style>
#preview-url-output, #preview-url-loader {
display: none;
}
#preview-url-output .content-container {
position: relative;
z-index: 1;
display: grid;
margin-top: 10px;
column-gap: 10px;
}
#preview-url-output .text-data {
grid-column-start: 3;
}
#preview-url-output .image-preview {
grid-column-start: 1;
}
#preview-url-output .image-preview img {
width: 100%;
height: auto;
max-width:320px;
}
#preview-url-output .text-data .page-title {
color: #000;
text-decoration: none;
font-size: 1.2em;
line-height: 30px;
}
</style>
<?php
}
Core PHP Curl code for Ajax response
As per blog post example. Save this code into a php file preview-url-ajax.php.
<?php
if (isset($_POST["url"]) && filter_var($_POST["url"], FILTER_VALIDATE_URL)) {
// Extract HTML using curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $_POST["url"]);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$data = curl_exec($ch);
curl_close($ch);
// Load HTML to DOM Object
$dom = new DOMDocument();
@$dom->loadHTML($data);
// Parse DOM to get Title
$nodes = $dom->getElementsByTagName('title');
$title = $nodes->item(0)->nodeValue;
// Parse DOM to get Meta Description
$metas = $dom->getElementsByTagName('meta');
$body = "";
$feature_img = '';
for ($i = 0; $i < $metas->length; $i ++) {
$meta = $metas->item($i);
if ($meta->getAttribute('name') == 'description') {
$body = $meta->getAttribute('content');
}
else if ($meta->getAttribute('property') == 'og:description' || $meta->getAttribute('name') == 'og:description') {
$body = $meta->getAttribute('content');
}
if ($meta->getAttribute('property') == 'og:image' || $meta->getAttribute('name') == 'og:image') {
$feature_img = $meta->getAttribute('content');
}
}
// Parse DOM to get Images
$image_urls = array();
$images = $dom->getElementsByTagName('img');
if($feature_img == ''){
for ($i = 0; $i < $images->length; $i ++) {
$image = $images->item($i);
$src = $image->getAttribute('src');
if(filter_var($src, FILTER_VALIDATE_URL)) {
$image_src[] = $src;
}
}
} else {
$image_src[] = $feature_img;
}
$output = array(
'title' => $title,
'image_src' => $image_src,
'body' => $body
);
echo json_encode($output);
} else {
$returnMessage['msg'] = 'Not a valid URL';
$returnMessage['status'] = 'error';
echo json_encode( $returnMessage );
}
?>
JavaScript code snippet for Jquery Ajax.
Do not forget to add jQuery CDN or local path before proceeding with this script.
(function ($) {
'use strict';
$('.preview-url-input').on("keyup", function() {
$("#output").html("");
$("#loader").show();
var remote_url = $(this).val();
var image_html = '';
var total_images = 0;
var current_image_position = 0;
$.ajax({
url: "preview-url-ajax.php",
type: "POST",
data: {'url': remote_url},
dataType: "json",
beforeSend : function () {
$('#preview-url-loader').html('Processing! Please wait!!');
},
success: function (response) {
console.log(response);
if(response.status == 'error'){
$("#preview-url-output").html(response.msg).show();
$("#preview-url-loader").hide();
} else {
if(response.image_src.length) {
//image_src = response.image_src;
total_images = parseInt(response.image_src.length-1);
current_image_position = total_images;
if(total_images>=0){
image_html = '<div class="image-preview" id="image-preview"><img src="'+response.image_src[current_image_position]+'"></div>';
}
}
var cotent_html = '<div class="text-data"><a class="page-title" href="'+remote_url+'" target="_blank">'+response.title+'</a><div>'+response.body+'</div>';
var responseHTML = '<div class="content-container">'+image_html + cotent_html+'</div>';
$("#preview-url-output").html(responseHTML).show();
$("#preview-url-loader").hide();
}
},
error : function (jqXHR, textStatus, errorThrown) {
//console.log(jqXHR, textStatus, errorThrown);
$("#preview-url-output").html("Problem in extracting data from the remote URL").show();
$("#preview-url-loader").hide();
}
});
});
})(jQuery);
Preview CSS code snippet
#preview-url-output, #preview-url-loader {
display: none;
}
#preview-url-output .content-container {
position: relative;
z-index: 1;
display: grid;
margin-top: 10px;
column-gap: 10px;
}
#preview-url-output .text-data {
grid-column-start: 3;
}
#preview-url-output .image-preview {
grid-column-start: 1;
}
#preview-url-output .image-preview img {
width: 100%;
height: auto;
max-width:320px;
}
#preview-url-output .text-data .page-title {
color: #000;
text-decoration: none;
font-size: 1.2em;
line-height: 30px;
}
Result




