A newbie here...I am trying to apply a system that allows readers to "infinitely" scroll down to the next posts after finishing a single post so that they don't have to manually click them.
(Like this website does:
https://dancingastronaut.com/2020/12/maceo-plex-confronts-racism-and-diversity-in-latest-single-cinemax/)
I tried the “auto load next post” plugin, but it didn’t work on my theme :(.
I’m currently using the Amphibious theme developed by templatepocket.
https://wordpress.org/themes/amphibious/
This is the biggest part I’m having a struggle with, and I think my website is good to go once it’s applied. I hope someone can help me out here!
Thanks!
You would first need to edit your single post template, usually single.php, and add a trigger when a user scrolls past that point.
<?php $gpNextPost = get_next_post(); ?>
<div class="gp-infinite-scroll" style="display: none;"><?php echo $gpNextPost->ID; ?></div>
Then call an AJAX function to load next post's content and also replace the URL in the browser's address bar.
Here's a rough example:
function gp_infinite_scroll($pid){
if (is_single()) { ?>
<script type="text/javascript" >
jQuery(document).ready(function($) {
$(window).scroll(function() {
var footerPos = $('footer').last().position().top;
var pos = $(window).scrollTop();
if (pos+(screen.height*4) > footerPos) {
if ($(".gp-infinite-scroll").first().hasClass('working')) {
return false;
} else {
$(".gp-infinite-scroll").first().addClass('working');
}
var gpNextPostId = $(".gp-infinite-scroll").first().text();
var data = {
'action': 'gp_is',
'gpNextPostId': gpNextPostId
};
$.post(ajaxurl, data, function(response) {
$(".gp-infinite-scroll").first().replaceWith(response);
}, 'html');
}
// Update new URL
var currUrl = $(".gp-post-header").first().attr("url");
var currTitle = $(".gp-post-header").first().attr("title");
if ($(".gp-post-header").length > 1 && history.pushState) {
for (var i=0; i<$(".gp-post-header").length; i++) {
var trigger = $(".gp-post-header").eq(i).next().position().top;
if (pos+(screen.height/2) >= trigger) {
currUrl = $(".gp-post-header").eq(i).attr("url");
currTitle = $(".gp-post-header").eq(i).attr("title");
}
}
}
if (location.href != currUrl) {
history.pushState({}, currTitle, currUrl);
}
});
});
</script>
<?php }
}
add_action( 'wp_head', 'gp_infinite_scroll' );
function gp_infinite_scroll_callback() {
if (isset($_POST['gpNextPostId']) && $_POST['gpNextPostId']) {
$the_query = new WP_Query(array('p'=>$_POST['gpNextPostId']));
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
// Change to your own Single Post template file
get_template_part( 'template-parts/content', 'single' );
}
}
wp_reset_postdata();
}
wp_die();
}
add_action( 'wp_ajax_gp_is', 'gp_infinite_scroll_callback' );
add_action( 'wp_ajax_nopriv_gp_is', 'gp_infinite_scroll_callback' );
This code is untested but it should get you going. If the above seems too much for you then you migh try some of the related plugins.
Related
I'm trying to create a Wordpress plugin and I'm unable to display error messages using the admin_notices feature.
function gbrew_notice_no_api_key() {
$url = admin_url('admin.php') . '?page=api-key';
?>
<div class="notice-info notice">
<p><?php _e("Please set up your client ID and client secret from the <a href='{$url}'>API Key</a> page first."); ?></p>
</div>
<?php
}
function gbrew_setup_menu() {
# Add the main menu option
add_menu_page('Spruce Beer Dashboard', 'Spruce Beer', 'manage_options', 'spruce-beer', 'gbrew_dashboard');
# Add the sub menu item to manage API keys
add_submenu_page('spruce-beer', 'API Key', 'API Key', 'manage_options', 'api-key', 'gbrew_manage_api_key');
}
function gbrew_dashboard() {
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if(!empty($client_id) && !empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
add_action('admin_notices', 'gbrew_notice_no_api_key');
}
}
# Add the plugin to the sidebar menu
add_action('admin_menu', 'gbrew_setup_menu');
already I think in your first function you can do better to return the HTML and maybe that will fix your problem
function gbrew_notice_no_api_key() {
$url = admin_url('admin.php') . '?page=api-key';
return <<<HTML
<div class="notice-info notice">
<p>Please set up your client ID and client secret from the <a href='$url'>API Key</a> page first.</p>
</div>
HTML;
}
Your calling notices too late, they fire before admin_menu; try this
function gbrew_notice_no_api_key()
{
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
if (empty($client_id) && empty($client_secret)) {
$url = admin_url('admin.php') . '?page=api-key';
?>
<div class="notice notice-success is-dismissible">
<p><?php
_e("Please set up your client ID and client secret from the <a href='{$url}'>API Key</a> page first."); ?></p>
</div>
<?php
}
}
function gbrew_setup_menu()
{
# Add the main menu option
add_menu_page('Spruce Beer Dashboard', 'Spruce Beer', 'manage_options', 'spruce-beer', 'gbrew_dashboard');
# Add the sub menu item to manage API keys
add_submenu_page('spruce-beer', 'API Key', 'API Key', 'manage_options', 'api-key', 'gbrew_manage_api_key');
}
function gbrew_dashboard()
{
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if ( ! empty($client_id) && ! empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
echo "<p>No Api Key Exists";
}
}
# Add the plugin to the sidebar menu
add_action('admin_menu', 'gbrew_setup_menu');
add_action('admin_notices', 'gbrew_notice_no_api_key');
If your also running multisite, might be worth adding: add_action('network_admin_notices', 'gbrew_notice_no_api_key'); as well
It seems to me that the problem is in the gbrew_dashboard function.
function gbrew_dashboard() {
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if(!empty($client_id) && !empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
add_action('admin_notices', 'gbrew_notice_no_api_key');
}
}
In the else statement you add gbrew_notice_no_api_key to admin_notices, but the action is never called. Read this answer about how do_action and add_action work in tandem. In summary,
The do_action() function executes any code that's been hooked with add_action().
I think the simplest solution looks like this:
function gbrew_dashboard() {
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if(!empty($client_id) && !empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
do_action('admin_notices');
}
}
add_action('admin_notices', 'gbrew_notice_no_api_key');
Add gbrew_notice_no_api_key to the action no matter what, then call it with do_action.
You could use a custom action (optional)
However, keep in mind that if you call do_action('admin_notices'), your plugin will call every function hooked to admin_notices, even if they belong to other plugins.
If you are not OK with that, then you could add a custom action instead. Taking gbrew as a prefix to uniquely identify your own hooks, you could add a custom action that will be called only by your plugin. In that case, your code would look like this:
function gbrew_dashboard() {
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if(!empty($client_id) && !empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
// calling your custom action here!!!
do_action('gbrew_admin_notices');
}
}
add_action('gbrew_admin_notices', 'gbrew_notice_no_api_key');
I am trying to debug if parameters are added to my shortcode. Currently, when I add a shortcode to my page and don't add a parameter it errors saying
Updating failed
But I would like to have a more detailed error. How would I do that? I'm working with code snippets and this is a front-end snippet. I noticed that I do get the error when I run the snippet in the back-end but then my entire WP UI disappears which isn't nice. Any tips?
<?php
add_shortcode('taxonomy_dropdown', 'do_taxonomy_dropdown');
function do_taxonomy_dropdown($atts = [])
{
$atts = array_change_key_case((array) $atts, CASE_LOWER);
if(do_validate_parameters($atts)){return;}
$taxonomy = $atts['taxonomy'];
$dependent = $atts['dependent'];
return;
}
function do_validate_parameters($atts = [])
{
$has_parameters = true;
if(!isset($atts['taxonomy'])){
echo "You forgot to add the taxonomy parameter.";
$has_parameters = false;
}
if(!isset($atts['dependent'])){
echo "You forgot to add the dependent parameter.";
$has_parameters = false;
}
return $has_parameters;
}
I think the issue you're having is with the initial portion not checking for the set variable. When I run it with error logging on I see that as an issue. Try this and see if it stops the issue.
add_shortcode('taxonomy_dropdown', 'do_taxonomy_dropdown');
function do_taxonomy_dropdown($atts = [])
{
$atts = array_change_key_case((array) $atts, CASE_LOWER);
if(do_validate_parameters($atts)){return;}
if ( isset($atts['taxonomy'])){
$taxonomy = $atts['taxonomy'];
}
if ( isset($atts['dependent'])){
$dependent = $atts['dependent'];
}
return;
}
function do_validate_parameters($atts = [])
{
$has_parameters = true;
if(!isset($atts['taxonomy'])){
echo "<p>You forgot to add the taxonomy parameter.</p>";
$has_parameters = false;
}
if(!isset($atts['dependent'])){
echo "<p>You forgot to add the dependent parameter.</p>";
$has_parameters = false;
}
return $has_parameters;
}
I currently have a wordpress site setup using woocommerce and gravity forms plugins. I am selling bike wheels and on my product page I use gravity forms to display different customization options. the options are different if they select one wheel or two wheels.
What I'm trying to achieve
I want to add a 5% discount if two wheels are selected and 10% if four+ are selected. This discount is applied to the product as it is added to the cart.
I am attempting to create a custom plugin that uses javascript to get the value from the gravity forms input, and hooks into woocommerce to edit the total price before adding it to the cart.
What I have so far
custom.js
jQuery(document).ready(function () {
jQuery('.cart').submit(function () {
var noOfWheels = jQuery(".rdoWheel input[type='radio']:checked").val();
console.log(noOfWheels)
var data = {
action: 'my_discount',
wheels: noOfWheels
};
jQuery.ajax({
type: 'POST',
url: discountAjax.ajax_url,
data: data,
success: function (data) {
//do nothing
},
});
return false;
});
});
discount.php
add_action('wp_enqueue_scripts', 'load_script');
function load_script() {
wp_enqueue_script('discount', plugin_dir_url( __FILE__ ) . 'custom/custom.js', array( 'jquery' ) );
wp_localize_script('discount', 'discountAjax', array('ajaxurl' => admin_url('admin-ajax.php')));
}
add_action('wp_ajax_woocommerce_discount', 'calculate', 10);
add_action('wp_ajax_nopriv_woocommerce_discount', 'calculate', 10);
function calculate() {
if (isset($_POST['wheels'])) {
global $woocommerce;
$wheels = $_POST['wheels'];
if ($wheels === "1") {
$val = 0;
} elseif ($wheels === "2"){
$val = 10;
}
session_start();
$_SESSION['val'] = $val;
}
}
add_action('woocommerce_before_calculate_totals', 'add_discount');
function add_discount( $cart_object) {
#session_start();
if (isset($_SESSION['val'])) {
$wheels = $_SESSION['val'];
foreach ( $cart_object->cart_contents as $key => $value ) {
$c_price = $value['data']->price;
$discountAmount = $c_price * $wheels/100;
$value['data']->price = $value['data']->price - $discountAmount;
}
//for testing purpose
echo $_SESSION['val'];
echo 'completed';
unset($_SESSION['val']);
}
}
whats happening
It seems the woocommerce function is not firing at all. when i check with firebug I see my ajax request go through okay then nothing else. If i remove everything except for the add_discount function then it goes through and applies the discount. I cant seem to get it to work with javascript/ajax.
I am creating a multilingual website using wordpress as CMS.
i am using qTranslate plugin for multi language support. As soon as i enable the plugin, all formatting of text is lost. i.e. all paragraphs in the editor are merged into a single paragraph.
I have enabled this option in settings: "WordPress should correct invalidly nested XHTML automatically" but there is no change.
Any suggestions please?
Add this code at the end of wp-content\themes\your-theme-name\functions.php:
//************************** PATCH START *****************************
// Fix for qTranslate plugin (that does not retain formatting in pages)
if('html' != wp_default_editor()) {
remove_filter('the_editor_content', 'wp_richedit_pre');
add_filter('the_editor_content', 'wp_htmledit_pre');
}
remove_filter( 'the_content', 'wpautop' );
if ( ! function_exists('tmce_replace') ) {
function tmce_replace() {
$tadv_options = get_option('tadv_options', array());
$tadv_plugins = get_option('tadv_plugins', array());
?>
<script type="text/javascript">
if ( typeof(jQuery) != 'undefined' ) {
jQuery('body').bind('afterPreWpautop', function(e, o){
o.data = o.unfiltered
.replace(/caption\]\ +?<\/object>/g, function(a) {
return a.replace(/[\r\n]+/g, ' ');
});
}).bind('afterWpautop', function(e, o){
o.data = o.unfiltered;
});
}
</script>
<?php
}
add_action( 'after_wp_tiny_mce', 'tmce_replace' );
}
function teslina_tinymce_config( $init ) {
$init['remove_linebreaks'] = false;
$init['apply_source_formatting'] = true;
$init['preformatted'] = true;
$init['remove_redundant_brs'] = false;
return $init;
}
add_filter('tiny_mce_before_init', 'teslina_tinymce_config');
//************************** PATCH END *******************************
write simple post in html mode to test like this :
<p>lorem</p>
<p>ipsum</p>
There is filter in wordpress to format text (plugin, or functions.php) try to find them, else try another plugin like Polylang.
I found a solution here:
http://www.teslina.com/en/748/wordpress/qtranslate-code-syntax-bugfix/
However i suspect that the code added in plugin will be removed when it's updated.
Surely, someone must have an idea of how t get this to work...
My blog is currently set where I have a custom page that displays only posts in a given category. Each post has a toggle button. When the toggle button is pressed, the post hides (the ENTIRE div is hidden with title and all post content). This works as desired.
The page is also set to display 10 posts per page. If I have 11 posts, the 11th is pushed to page 2. This works as desired.
The problem is that when a post is toggled (let's say post 3), I am left with a total of 9 posts on this page, with post 11 remaining on page 2. What I want to have happen is that when post 3 is toggled, post 11 should carry onto page 1, with page 2 essentially disappearing (since there are no posts to display there).
For illustration purposes:
Page 1 displays Posts 1,2,3,4,5,6,7,8,9,10
Page 2 displays Posts 11...and so on.
If Post 3 is toggled:
Page 1 displays Posts 1,2,4,5,6,7,8,9,10,11
Page 2 disappears (unless there is a post 12,13, etc)
Would anyone know how to implement this?
page.php:
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'category_name' => 'post',
'paged' => $paged,
'posts_per_page' => 10
);
query_posts($args);
while (have_posts()) : the_post();
?>
..........the posts are displayed.............
<?php endwhile; ?>
<script type="text/javascript">
var pager = new Imtech.Pager();
$(document).ready(function() {
pager.paragraphsPerPage = 5; // set amount elements per page
pager.pagingContainer = $('#paginate'); // set of main container
pager.paragraphs = $('div.z', pager.pagingContainer); // set of required containers
pager.showPage(1);
});
</script>
toggle.js
$(document).on("click", ".toggle", function(){
postID = $(this).attr('id').replace('toggle_', '');
// Declare variables
value = '0';
myajax();
return false;
});
function myajax(){
// Send values to database
$.ajax({
url: 'check.php',
//check.php receives the values sent to it and stores them in the database
type: 'POST',
data: 'postID=' + postID + '&value=' + value,
success: function(result) {
$('#post_' + postID).toggle();
}
});
}
pagination.js
var Imtech = {};
Imtech.Pager = function() {
this.paragraphsPerPage = 3;
this.currentPage = 1;
this.pagingControlsContainer = '#pagingControls';
this.pagingContainerPath = '#contained';
this.numPages = function() {
var numPages = 0;
if (this.paragraphs != null && this.paragraphsPerPage != null) {
numPages = Math.ceil(this.paragraphs.length / this.paragraphsPerPage);
}
return numPages;
};
this.showPage = function(page) {
this.currentPage = page;
var html = '';
this.paragraphs.slice((page-1) * this.paragraphsPerPage,
((page-1)*this.paragraphsPerPage) + this.paragraphsPerPage).each(function() {
html += '<div>' + $(this).html() + '</div>';
});
$(this.pagingContainerPath).html(html);
renderControls(this.pagingControlsContainer, this.currentPage, this.numPages());
}
var renderControls = function(container, currentPage, numPages) {
var pagingControls = 'Page: <ul>';
for (var i = 1; i <= numPages; i++) {
if (i != currentPage) {
pagingControls += '<li>' + i + '</li>';
} else {
pagingControls += '<li>' + i + '</li>';
}
}
pagingControls += '</ul>';
$(container).html(pagingControls);
}
}
So, any ideas?
My Answer would be to reload the current page with posts through ajax.
there is no problem with generating pagination through javascript and php
you have same behaviour for initial load and subsequent loads(when user hides a post)
you can make the pagination work with jquery pretty easy