I'm currently working on a Wordpress site. I'm building a custom plugin that allows for lazy loading of custom post types.
Some of these post types contain shortcodes, that I need to display. I have a primary Javascript file that makes Ajax requests to my PHP code in my plugin, which returns a JSON object containing the shortcode like this:
Object {shortcode: "[embedyt]https://www.youtube.com/watch?&height=300[/embedyt]"}
I'm then trying to display this shortcode on the front-end, since I'm dynamically building HTML blocks based on the JSON response.
However, when I try to output the shortcode to the page via the Javascript, it just displays as text, like this:
Here's my PHP code and Javascript:
$packet = array();
$formatted_url = "[embedyt]" . $youtube_root . $video_id . "&height=300" . "[/embedyt]";
$packet["shortcode"] = do_shortcode($formatted_url);
echo json_encode($packet); // This sends a response back to the Ajax request
And:
$.ajax({
type: 'POST',
url: tlas_lazy_load.ajax_url,
data: {
action: 'tlas_lazy_load',
post_type: post_type,
posts_per_page: 6,
paged: page
},
success: function(packet) {
response = JSON.parse(packet);
for(var i = 0; i < response.length; i++) {
build_lazy_load("#lazy-load-row", packet[i], i);
}
}
});
function build_lazy_load(element, packet, index) {
var block = "";
block += "<div class=\"col-md-4\">";
block += " <div class=\"video-individual\">";
block += " <div class=\"panel panel-default\">";
block += " <div class=\"panel-body\" id=" + index + ">";
block += packet.shortcode;
block += " <\/div>";
block += " <\/div>";
block += " <\/div>";
block += "<\/div>";
$(element).append(block);
};
What gives me hope that this can be done is the answer to this question:
Wordpress: Outputting shortcode with Javascript?
And I'm following along with what that person suggested. However can this be done?
Update:
So I can display the shortcode if I do this in enqueue scripts method:
add_action( 'wp_enqueue_scripts', 'tlas_lazy_load_enqueue_scripts' );
function tlas_lazy_load_enqueue_scripts() {
wp_enqueue_script( 'tlas-lazy-load', plugins_url( 'js/tlas_lazy_load.js', __FILE__ ), array('jquery'), '1.0', true );
wp_localize_script( 'tlas-lazy-load', 'tlas_lazy_load', array(
'ajax_url' => admin_url( 'admin-ajax.php' )
// BELOW
'videos_shortcode' => do_shortcode("[embedyt]" . $youtube_root . $video_id . "&height=300" . "[/embedyt]")
));
}
By setting it as a localized variable which my Javascript can access. The problem is that I have to add the shortcode after this function has already been declared. I tried localizing it later within the file in my above function by doing:
...
$packet = array();
$formatted_url = "[embedyt]" . $youtube_root . $video_id . "&height=300" . "[/embedyt]";
wp_localize_script( 'tlas-lazy-load', 'tlas_lazy_load', array(
'videos_shortcode' => do_shortcode($formatted_url)
));
...
But this didn't work, it simply returned nothing. I'm on the right track (I think?) but I'm not sure how you can dynamically localize a script/Javascript variable.
Related
I have a smart tag inside a hidden field in my WP Forms (written with php - see below) that collects user data, however this significantly slows down the webpage. The div ID is: wpforms-10395-field_107. The url is: https://ellasbubbles.com/contact-us/
My question is, how can I prevent this div from loading until after the page has fully loaded. This way it can load in the background while the user is populating their contact form details
Note: A better solution might be to keep this div empty, and simply populate it with the shortcode on page load?
PHP (currently in functions.php) - Grabs users location details and stores them in a smart tag:
add_shortcode('geo', 'shortcode');
function wpf_dev_register_smarttag( $tags ) {
// Key is the tag, item is the tag name.
$tags['geo'] = 'geo';
return $tags;
}
add_filter( 'wpforms_smart_tags', 'wpf_dev_register_smarttag' );
function wpf_dev_process_smarttag( $content, $tag ) {
$city = do_shortcode('[userip_location type=city]');
$country = do_shortcode('[userip_location type=country]');
$region = do_shortcode('[userip_location type=region]');
$flow = do_shortcode('[track-user-flow]');
// Only run if it is our desired tag.
if ( 'geo' === $tag ) {
$userinfo = '<b>City:</b> ' . $city . "\n" . '<b>Region:</b> ' . $region . "\n" . '<b>Country:</b> ' . $country . "\n" . "\n" . '<b>User Flow:</b> ' . $flow;
// Replace the tag with our link.
$content = str_replace( '{geo}', $userinfo, $content );
}
return $content;
}
add_filter( 'wpforms_smart_tag_process', 'wpf_dev_process_smarttag', 10, 2 );
It looks like I can use:
$(window).load(function(){
$.get("<path to php file>", function(data){
Replace Placeholder code here? (maybe)
});
})
I'm trying to do a dynamic product gallery based on colours in woocommerce product page. When I click on one colour, example on red, i should see Red Gallery's photos.
To do this i replaced all woocommerce gallery block with a new one created by ajax ( who have same classes of old gallery).
The loading of new photos work fine and I get gallery photos based on colour.
But when ajax load new gallery the slider don't work, I think because the woocommere js, who create the slider, is read only on page load.
I think I should reload some Woocommerce JS Function to recreate slider with his functions, but I don't know how.
This is the php file, which one I create a new gallery, called from ajax:
global $product;
$current_id = "";
if(isset($_POST['prodid']) && $_POST['prodid'] != "" ) {
$current_id = $_POST['prodid'];
$product = new WC_Product($current_id);
}
$columns = apply_filters( 'woocommerce_product_thumbnails_columns', 4 );
$post_thumbnail_id = $product->get_image_id();
$wrapper_classes = apply_filters( 'woocommerce_single_product_image_gallery_classes', array(
'woocommerce-product-gallery',
'woocommerce-product-gallery--' . ( $product->get_image_id() ? 'with-images' : 'without-images' ),
'woocommerce-product-gallery--columns-' . absint( $columns ),
'images',
) );
?>
<figure class="woocommerce-product-gallery__wrapper">
<?php
if ( $product->get_image_id() ) {
$html = wc_get_gallery_image_html( $post_thumbnail_id, true );
} else {
$html = '<div class="woocommerce-product-gallery__image--placeholder">';
$html .= sprintf( '<img src="%s" alt="%s" class="wp-post-image" />', esc_url( wc_placeholder_img_src( 'woocommerce_single' ) ), esc_html__( 'Awaiting product image', 'woocommerce' ) );
$html .= '</div>';
}
echo apply_filters( 'woocommerce_single_product_image_thumbnail_html', $html, $post_thumbnail_id ); // phpcs:disable WordPress.XSS.EscapeOutput.OutputNotEscaped
do_action( 'woocommerce_product_thumbnails' );
?>
</figure>
This is the ajax function called on box colour click
function changeGallery(selected_gallery, productID) {
jQuery(function($) {
var select_color = selected_gallery;
var xhttp;
$.ajax({
url : 'https://mysite.it/wp-admin/admin-ajax.php', // AJAX handler
data : { action : 'load_gallery', gallery : select_color, prodid : productID },
type : 'POST',
beforeSend: function() {
},
success : function( result ){
if( result ) {
$('.woocommerce-product-gallery').html(result);
//Reload here some woocommerce JS functions?
}
}
});
});
}
The way to solve issues like this is to look at the WooCommerce source code to see how the plugin initialises the gallery to begin with. Based on this, I think you need to do something like:
jQuery( '.woocommerce-product-gallery' ).each( function() {
jQuery( this ).wc_product_gallery();
} );
See Github: single-product.js for reference.
I had same problem. The dafoxuk answer is correct, you need to reinitialize ProductGallery class on the .woocomorce-product-gallery. The problem was that this element already has a flexslider entity attached to it. To solve this, just remove that element (.woocomorce-product-gallery) and create a new identical one. (Flexslider doesn't have a way to detach itself from the element as far as I know)
This is a part of my WordPress PHP file code, in this I wrote a JavaScript code and I would like to display the names, images from the query.
Names are displayed but images are not displaying, then I added get_template_directory_uri(), after adding get_template_directory_uri() it is showing error in console like this "Uncaught Syntax Error: missing ) after argument list".
All images are stored in WordPress theme image folder.
How to write javascript code to display images?
Please Help me out from this problem.
Thanks.
function partyFunction(){
debugger;
$postdata = {};
$postdata["partyId"]=$("#partydropdown").val();
$.post('<?php echo get_template_directory_uri() ?
>/GetPartiesData.php',$postdata,function (data) {
debugger;
console.log(data);
var stringreplace = data.replace(/['"]+/g, '');
console.log(stringreplace);
var res = stringreplace.split(",");
console.log(res);
$("#partyBody").empty();
$("#partyBody").html('');
$("#partyBody").append("<tr>"+
"<td>"+res[1]+"</td>"+
"<td><img src='"+<?php echo get_template_directory_uri() ?
>/img/++res[2]+"' style='padding:5px;vertical-align: middle;border-style:
none;width:129px;height:109px;' ></td>"+
"<td><img src='"+res[3]+"' style='padding:5px;vertical-align:
middle;border-style: none;width:129px;height:109px;' ></td>"+
"<td><a href='"+res[4]+"' target='_blank'>click here</a></td>"+
"</tr>");
});
}
//Add code in function.php
function theme_directory_uri(){
wp_localize_script( 'ajax-login-script', 'uri_object', array(
'theme_directory_uri' => get_template_directory_uri()
));
}
add_action('init', 'theme_directory_uri');
//get in javascript
var theme_uri = uri_object.theme_directory_uri;
Method 1:
Assign it to a global variable in your php file then call it in javascript
like this at top of your .php file
<script>
template_directory = "<?php echo get_template_directory_uri() ?>"
</script>
then use template_directory like this
$.post(template_directory+'/GetPartiesData.php',$postdata,function (data) {
same like this use in image src also.
Method 2:
Use wordpress enqueue functions
wp_register_script( 'template-directory', 'myscript_url' );
wp_enqueue_script( 'template-directory' );
wp_localize_script( 'template-directory', 'directory_name', array( 'templateUrl' => get_stylesheet_directory_uri() ) );
and use this in your script use like this
template_directory = directory_name.templateUrl;
$.post(template_directory+'/GetPartiesData.php',$postdata,function (data) {
Uncaught SyntaxError: missing )
<img src='"+<?php echo get_template_directory_uri() ?>/img/++res[2]+"'
Replace with:
<img src='<?=get_template_directory_uri()?>/img/"+res[2]+"'
You missed semicolon the end of statement:
<?php echo get_template_directory_uri(); ?>
- ^ just missed
P.S. you have used same line more than once, kindly ensure all lines have been modified.
I'm wondering if there is a way to put my Wordpress attachment link inside of a javascript function. In simple terms, it would function like so:
$attach_url = "<?php echo wp_get_attachment_url(); ?>";
function () {
return $attach_url;
}
More specifically, I'm looking for a way to implement it with Photoswipe's share buttons (full source code here):
$attach_url = = "<?php echo wp_get_attachment_url(); ?>";
(this, function () {
'use strict';
var PhotoSwipeUI_Default =
function(pswp, framework) {
shareButtons: [
{url:'https://www.facebook.com/sharer/sharer.php?u={{attachment_pg_url}}'},
],
getAttachmentPageURL: function ( shareButtonData ) {
return $attach_url;},
parseShareButtonOut: function(shareButtonData, shareButtonOut) {
return shareButtonOut;
},
_updateShareURLs = function() {
var shareButtonOut = '',
shareButtonData,
shareURL,
attachment_pg_url;
for(var i = 0; i < _options.shareButtons.length; i++) {
shareButtonData = _options.shareButtons[i];
attachment_pg_url = _options.getAttachmentPageURL(shareButtonData);
shareURL = shareButtonData.url.replace('{{attachment_pg_url}}', attachment_pg_url );
Any help is much appreciated!
EDIT
Here's my updated code, which is almost working. The js file is interpreting the enqueue script from functions.php. However, the url displayed is <?php echo get_attachment_link(); ?>, rather than the actual link (ex: home.com/attachment-page), which does display correctly when I use this php code in the loop.
How can I get the url to output a link, not the actual php code?
In functions.php:
// Custom Photoswipe Share URL
wp_enqueue_script( 'photoswipe_custom_share_link', get_template_directory_uri() . '/custom_path_here/photoswipe-ui-single-item.js' );
$attach_url = "<?php echo get_attachment_link(); ?>";
wp_localize_script( 'photoswipe_custom_share_link', 'pswp_custom_share', $attach_url );
In the Photoswipe js file (with some extra fixes from my original post):
(this, function () {
'use strict';
var PhotoSwipeUI_Default =
function(pswp, framework) {
shareButtons: [
{url:'https://www.facebook.com/sharer/sharer.php?u={{attach_url}}'},
],
getAttachmentURLForShare: function ( /*shareButtonData */) {
return pswp_custom_share;
},
parseShareButtonOut: function(shareButtonData, shareButtonOut) {
return shareButtonOut;
},
_updateShareURLs = function() {
var shareButtonOut = '',
shareButtonData,
shareURL,
attachment_url;
for(var i = 0; i < _options.shareButtons.length; i++) {
shareButtonData = _options.shareButtons[i];
attachment_url = _options.getAttachmentURLForShare(shareButtonData);
shareURL = shareButtonData.url.replace('{{attach_url}}', encodeURIComponent(attachment_url) );
EDIT
I made the mistake of using quotes in my enqueue script. With the below code, formatting is now correct. The only problem is the url output is "home.com" instead of "home.com/attachment-page."
How can I define the dynamically generated attachment page url outside of the loop? Do I need to echo it?
$attach_url = get_attachment_link($attachment->ID);
EDIT - SOLVED!
I needed to use JavaScript enqueue to get base url of attachment in the loop. (Based on the answer here and with thedarkcoder's help).
In functions.php:
// Custom Photoswipe Share URL
function pswp_custom_share()
{
/* Get the ID of the current post */
global $post;
$ID = $post->ID;
/* register the script */
wp_register_script( 'photoswipe_custom_share_link', get_template_directory_uri() . 'custom_path_here/photoswipe-ui-single-item.js', array('jquery'), false, true );
$attach_url = array(
'attachment_page' => get_attachment_link( $ID )
);
wp_enqueue_script( 'photoswipe_custom_share_link' );
wp_localize_script('photoswipe_custom_share_link', 'attach_url', $attach_url);
}
/* If we're not in the admin section call our function on the wp_enqueue_scripts hook */
if ( !is_admin() ) add_action( "wp_enqueue_scripts", "pswp_custom_share", 10 );
In the Photoswipe js file:
getAttachmentURLForShare: function ( /*shareButtonData */) {
return attach_url.attachment_page;
},
You can use WordPress enqueue script function to achieve this
Please follow below link for detailed info
https://code.tutsplus.com/tutorials/how-to-pass-php-data-and-strings-to-javascript-in-wordpress--wp-34699
Let me know if it resolves your problem
It should be possible in theory as PHP is processed server-side before the javascript runs on client side.
I've noticed your script is missing the attachment ID from the wp_get_attachment_url function.
From the Wordpress API Documentation:
<?php echo wp_get_attachment_url( 12 ); ?>
The first step would be to test the functionality on a basic level by echoing the attachment URL to the page. Once you've done this, you know that you're hooking into the function correctly.
Then assign that value to a JavaScript variable and try running some sort of alert or console log to validate that you can successfully parse the URL to a global JS variable.
Then see if you can access that variable from inside a function. If you can step through each of the above basic steps then it should be more than possible for you to parse this data into the Photoswipe plugin.
Let me know if you get stuck, I will attempt to help in any way I can.
I'm trying to transcribe what my programmer told me. He and I may be doing this all wrong, so I need to make sure he and I am doing it in the right manner. Here is what we are trying to do:
I have a page on a website and within that page, I have a button. When you click on it, I want it to (via AJAX so the page doesn't refresh)
Send data (time capture) to the DB
See that the DB recorded the change and in turn return a different value back to the site
This would in turn change the button, noting that it is in a recording mode.
Think of it in this way, the button is a timer. On click, it records the time in the DB, and in the DB it also changes the state to recording. Since it is in the recording phase, somehow it gets sent back to the website page and changes the button showing that it is recording. Naturally clicking again would stop it and record the time in the DB.
Here is how the snippets are set up (not working I think) ATM:
*sidenote: This is in Joomla
Page:
<script src="js/ajax_link.js" type="text/javascript"></script>
<div id="ajaxlink" onclick="loadurl('php/ticket_timer.php',<?php echo $row->id?>)">Start Time</div>
ajax_link.js
function loadurl(dest,ticket_id) {
jQuery.ajax({
url: dest,
type: "POST",
data: "ticket_id="+ticket_id,
success: function(msg){
alert(msg);
jQuery('#ajaxlink').text("Timer Stop");
}
});
}
ticket_timer.php
<?php
define( '_JEXEC', 1 );
define( 'DS', DIRECTORY_SEPARATOR );
define( 'JPATH_BASE', $_SERVER[ 'DOCUMENT_ROOT' ] );
require_once( JPATH_BASE . DS . 'includes' . DS . 'defines.php' );
require_once( JPATH_BASE . DS . 'includes' . DS . 'framework.php' );
require_once( JPATH_BASE . DS . 'libraries' . DS . 'joomla' . DS . 'factory.php' );
$mainframe =& JFactory::getApplication('site');
$ticket_id = $_POST['ticket_id'];
$user =& JFactory::getUser();
$user_id=$user->get('id');
//DB Query
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(array('id', 'ticket_id', 'user_id', 'times','current_time')));
$query->from($db->quoteName('#__support_ticket_times'));
$query->where($db->quoteName('ticket_id') . ' LIKE '. $db->quote($ticket_id));
$query->where('ticket_id = '. $ticket_id, 'AND')
->where('user_id=' . $user_id );
$db->setQuery($query);
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$results = $db->loadObjectList();
$current_time=$results[0]->current_time;
$times=$results[0]->times;
$id_results = $db->loadColumn();
$db->setQuery($idquery);
$timesString = $times . ',' . date('Y-m-d g:i');
echo($timesString);
if(empty($results[0])){
$values = array(max($id_results)+1, $ticket_id, $user_id, $db->quote(date('Y-m-d g:i')),$db->quote(date('Y-m-d g:i')));
//echo "YOU GET NOTHING, MAKING NEW ROW";
$columns = array('id', 'ticket_id', 'user_id', 'times','current_time');
// Prepare the insert query.
$insert_query = $db->getQuery(true);
$insert_query
->insert($db->quoteName('#__support_ticket_times'))
->columns($db->quoteName($columns))
->values(implode(',', $values));
// Set the query using our newly populated query object and execute it.
$db->setQuery($insert_query);
$db->query();
}else{
//echo("CURRENT TIME" . $current_time);
if($current_time=='0000-00-00 00:00:00'){
echo "NO TIME";
$fields = array(
$db->quoteName('current_time'). '=' . $db->quote(date('Y-m-d g:i'))
);
}
// . $db->quote(date('Y-m-d g:i'))
else{
echo "ADD TIME";
$fields = array($db->quoteName('times') . '=' . $db->quote($timesString) ,
$db->quoteName('current_time'). "='0000-00-00 00:00:00'"
);
}
$update_query = $db->getQuery(true);
$conditions = array(
$db->quoteName('user_id') . '=' . $db->quote($user_id),
$db->quoteName('ticket_id') . '=' . $db->quote($ticket_id)
);
$update_query->update($db->quoteName('#__support_ticket_times'))->set($fields)->where($conditions);
$db->setQuery($update_query);
$db->query();
//echo $update_query;
}
?>
Can anyone suggest how to get the timer to fire back that the timer has started? Are we butchering this and is there a better way to code this?
You need to exchange some data between the PHP and the HTML page. The HTML page can be modified with Javascript, of course. The notation typically used for this kind of an exchange is JSON. In this example, we're using JSON to:
Send a boolean timerRunning to the PHP,
change the value in PHP,
send a reply,
modify the HTML page, and
store the timerRunning value in the HTML element.
So, for starters, we pass some data from the HTML element to Javascript using the HTML5 data- attributes, like this:
<div id="ajaxlink" data-url="php/ticket_timer.php" data-ticketId="<?php echo $row->id; ?> " data-timerRunning="false">Start Time</div>
In your Javascript, we access the parameters set above and send them to your PHP script via AJAX:
jQuery(document).ready(function($){
// Add an 'onClick' handler to the element
jQuery('#ajaxlink').on('click', function(event) {
// Get the url and ticket_id from the element's 'data-' attributes
var url = jQuery(this).data( 'url' );
var data = {
'ticketId' : jQuery(this).data( 'ticketId' ),
'timerRunning' : jQuery(this).data( 'timerRunning' )
}
// Send an AJAX request
jQuery.ajax({
type: 'POST',
url: url,
data: data
}).done( function(response) {
// This runs when the AJAX request succeeds
if ( 'undefined' == typeof( response.timerRunning ) ) {
alert( 'The server didn\'t tell the timer state' );
return;
}
// Store the value in the element
jQuery('#ajaxlink').data( 'timerRunning', response.timerRunning );
// Change the element HTML
if ( response.timerRunning )
jQuery('#ajaxlink').html( 'Stop Timer' );
else
jQuery('#ajaxlink').html( 'Start Timer' );
}).fail( function(jqXHR, textStatus, errorThrown ) {
// This runs when the AJAX request fails
alert( 'The AJAX request failed with the error ' + errorThrown );
});
});
});
In your PHP script, check the timerRunning value and react accordingly:
if ( isset( $_POST['timerRunning'] ) ) { // Check that we got some value for 'timerRunning'
if ( $_POST['timerRunning'] ) {
// The 'timerRunning' value is TRUE, the timer is running, now stop it
your_code_here_to_stop_the_timer();
$reply = array( 'timerRunning' => false );
} else {
// The 'timerRunning' value is FALSE, the timer isn't running, now start it
your_code_here_to_start_the_timer_and_whatever();
$reply = array( 'timerRunning' => true );
}
// Send the correct header for a JSON response
header('Content-type: application/json');
// Send the $reply array encoded as JSON
echo json_encode( $reply );
}