For some reason my variable keeps resetting to 2 despite me wanting to increment the variable when a function is called. It's really annoying me and I've refactored the code several times to no avail! It should be simple...
Here is my code:
( function( $ ) {
$( document ).ready( function () {
var count = 2;
var total = <?php echo $loop->max_num_pages; ?>;
if ( count <= total ) {
$( window ).scroll( function() {
if ( $( window ).scrollTop() == $( document ).height() - $( window ).height() ) {
$.ajax({
url: "<?php bloginfo( 'wpurl' ) ?>/wp-admin/admin-ajax.php",
type:'POST',
data: "action=infinite_scroll&page_no=" + count + '&loop_file=forums',
success: function( html ){
$( "#content" ).append( html );
}
});
count++;
}
});
} else {
return;
}
});
})( jQuery );
EDIT: Thanks for your responses so far! Updated code below:
<script type="text/javascript">
pageCount = 2;
total = <?php echo $loop->max_num_pages; ?>;
jQuery( window ).scroll( function() {
if ( jQuery( window ).scrollTop() == jQuery( document ).height() - jQuery( window ).height() ){
console.log( 'Old value: ' + pageCount );
if ( pageCount > total ){
return false;
} else {
loadArticle( pageCount );
}
pageCount++;
console.log( 'New value: ' + pageCount );
}
});
function loadArticle( pageNumber ) {
jQuery.ajax({
url: "<?php bloginfo( 'wpurl' ) ?>/wp-admin/admin-ajax.php",
type:'POST',
data: "action=infinite_scroll&page_no=" + pageNumber + '&loop_file=forums',
success: function( html ){
jQuery( "#content" ).append( html );
}
});
return false;
}
</script>
New value is always 3 and old value is always 2 (output in console) so it's still being reset...
SOLVED: The html callback in the ajax method was causing the issue. Moving the increment into there worked! New code:
( function( $ ) {
pageCount = 2;
total = <?php echo $loop->max_num_pages; ?>;
$( window ).scroll( function() {
if ( $( window ).scrollTop() == $( document ).height() - $( window ).height() ){
if ( pageCount > total ){
return false;
} else {
$.ajax({
url: "<?php bloginfo( 'wpurl' ) ?>/wp-admin/admin-ajax.php",
type:'POST',
data: "action=infinite_scroll&page_no=" + pageCount + '&loop_file=forums',
success: function( html ){
$( "#content" ).append( html );
pageCount++;
}
});
}
}
});
})( jQuery );
two things first:
var can be shortened as such:
var var1 = 'string',
var2 = 'int';
Don't mix php inside JS - it's messy. Create a hidden span and assign data tags to it and call like that
secondarily, that's because the value gets reset whenever you call the function. Place outside, or pass a parameter called count so you can make it more generic and use it throughout your project.
Define count variable outside the function.
e.g.
var count = 2;
( function( $ ) {
$( document ).ready( function () {
var total = <?php echo $loop->max_num_pages; ?>;
if ( count <= total ) {
$( window ).scroll( function() {
if ( $( window ).scrollTop() == $( document ).height() - $( window ).height() ) {
$.ajax({
url: "<?php bloginfo( 'wpurl' ) ?>/wp-admin/admin-ajax.php",
type:'POST',
data: "action=infinite_scroll&page_no=" + count + '&loop_file=forums',
success: function( html ){
$( "#content" ).append( html );
}
});
count++;
}
});
} else {
return;
}
});
})( jQuery );
Your problem here is that the var count is local to your method. This means that it is only alive in that method call. Next time you call your function again, it will create a different count with the value 2 since that is the value you specify on your declaration. Move the variable declaration outside the method and everything should be fine.
Related
I have a couple of jQuery functions that pass PHP data to the JS function using the wordpress wp_localize_scripts function:
function mb_scripts_settings() {
// blanks
$mb_ajax_form_type = $mb_get_page_slug = $mb_redirect = $mb_redirect_time = $mb_form_disable = $mb_array = '';
// get the form type
$mb_ajax_form_type = ( is_front_page() ? 'change' : 'submit' );
// get the page slug from ID
$mb_get_page_slug = get_post_field( 'post_name', get_the_ID() );
// if the page is admin or password
if( is_page( array('admin', 'pw') ) ) {
$mb_redirect = true;
$mb_redirect_time = 3000;
$mb_form_disable = true;
if( is_page('admin') ) {
// generate the url for redirection
$mb_form_area = ( ( is_page('admin') && isset($_GET['mbtab']) ) ? $_GET['mbtab'] : null );
$mb_form_area_url = ( empty($mb_form_area) ? '/' : '/admin/?mbtab=' . $mb_form_area . '&mbform=1' );
$mb_form_area_url = get_home_url( $mb_form_area_url );
}
}
// if the page is front
if( is_front_page() ) {
$mb_redirect = false;
$mb_redirect_time = 0;
$mb_form_disable = false;
$mb_get_page_slug = 'front_page';
$mb_form_area = $mb_form_area_url = null;
}
// build the array
$mb_array = array(
$mb_ajax_form_type,
$mb_get_page_slug,
$mb_redirect,
$mb_redirect_time,
$mb_form_disable
);
return $mb_array;
}
Which would output an array with all the needed data for the JS function:
// create the script
$(function() {
// var
var mb_form_type = mb_mbtheme_js[0],
mb_form_type = '.' + mb_form_type,
mb_get_page_slug = mb_mbtheme_js[1],
mb_redirect = mb_mbtheme_js[2],
mb_redirect_time = mb_mbtheme_js[3],
mb_form_disable = mb_mbtheme_js[4];
// trigger the ajax on form type
// $("#mb_ajax_form") + mb_form_type + ( function( mb_ajax_form ) {
$("#mb_ajax_form").change( function( mb_ajax_form ) {
// stop the default function of buttons
mb_ajax_form.preventDefault();
// do the ajax
mb_ajax_form_js();
});
});
// accept the form ID
function mb_ajax_form_js() {
// get the vriables
var mb_ajax_form_data = new FormData( $("#mb_ajax_form")[0] ),
mb_ajax_form_time = 60,
mb_ajax_form_links = "#mb_ajax_form input, #mb_ajax_form submit, #mb_ajax_form button";
// do the ajax
$.ajax({
method: "POST",
data: mb_ajax_form_data,
contentType: false,
processData: false,
// the before send function
beforeSend: function( before ) {
// lock the form input and select
$( mb_ajax_form_links ).prop( "disabled", true );
},
// the success function
success: function( success ) {
// show the response
$( "#response" ).show().html( success );
// scroll to the top of the container - response divHeight
$( "section.mbcontainer" ).animate({
scrollTop: $( "#response" ).offset().top
}, "slow" );
// re-enable the submit button
// $( mb_ajax_form_links ).prop( "disabled", false );
},
// the complete function
complete: function( complete ) {
// if we are seeing the success message
if( $( "#response div" ).hasClass( "mbsuccessmessage" ) ) {
// the admin or password page conditions
if( mb_get_page_slug == 'admin' || mb_get_page_slug == 'pw' ) {
// set the redirection
setTimeout( function() { window.location.replace( mb_redirect ); }, mb_redirect_time );
// what to do with the form
$( mb_ajax_form_links ).prop( "disabled", mb_form_disable );
}
// the front page conditions
if( mb_get_page_slug == 'front_page' ) {
// set the redirection
setTimeout( function() { $(".mbsuccessmessage").slideUp(); }, mb_redirect_time );
}
}
},
// the error function
error: function( error ) {
// log the error
console.error( error );
}
});
}
However, it doesn't seem to be working as I thought it would when it wasn't being passed via the array and was all hard coded in. Things like the mb_form_type weren't working until I created a new variable with the '.' + mb_form_type.
Now it is spitting an error on the complete: function but I have also tried setting the if statement to compare as String() == String(mb_get_page_slug) == String('admin') but that didn't work either.
Is there something I am missing in the comparisons?
Your issue is one of scope. $(function() {}); creates a closure and you define your vars in that closure. Code outside the closure cant see those variables. To fix this, you have several options, here are 2 that would work:
1) move the variables to outside the closure like this:
// var
var mb_form_type = mb_mbtheme_js[0],
mb_form_type = '.' + mb_form_type,
mb_get_page_slug = mb_mbtheme_js[1],
mb_redirect = mb_mbtheme_js[2],
mb_redirect_time = mb_mbtheme_js[3],
mb_form_disable = mb_mbtheme_js[4];
// create the script
$(function() {
// trigger the ajax on form type
// $("#mb_ajax_form") + mb_form_type + ( function( mb_ajax_form ) {
$("#mb_ajax_form").change( function( mb_ajax_form ) {
// stop the default function of buttons
mb_ajax_form.preventDefault();
// do the ajax
mb_ajax_form_js();
});
});
// accept the form ID
function mb_ajax_form_js() {
// your code here...omitted for brevity
}
2) move your function inside the closure like this (note, anything calling mb_ajax_form_js will also need to be inside the closure):
// create the script
$(function() {
// var
var mb_form_type = mb_mbtheme_js[0],
mb_form_type = '.' + mb_form_type,
mb_get_page_slug = mb_mbtheme_js[1],
mb_redirect = mb_mbtheme_js[2],
mb_redirect_time = mb_mbtheme_js[3],
mb_form_disable = mb_mbtheme_js[4];
// trigger the ajax on form type
// $("#mb_ajax_form") + mb_form_type + ( function( mb_ajax_form ) {
$("#mb_ajax_form").change( function( mb_ajax_form ) {
// stop the default function of buttons
mb_ajax_form.preventDefault();
// do the ajax
mb_ajax_form_js();
});
// accept the form ID
function mb_ajax_form_js() {
// your code here...omitted for brevity
}
});
Update:
For accessing the submit and change functions using a string variable (mb_form_type), you'll need to use the "array access syntax" rather than the dot notation you have tried.
As a simple example, this would work (note that mb_form_type doesnt contain the .):
var mb_form_type = 'change';
$("#mb_ajax_form")[mb_form_type]( function( mb_ajax_form ) {
alert('This will work using array access syntax');
});
here's a working example
I ran two ajax one for post and one for get
This one is for posting form values by serialize.
$(function(){
function showValues() {
jQuery.ajax({
type: "POST",
data: $( "form" ).serialize(),
success: function(data){
var x = <?php echo json_encode($_SESSION['q10']); ?>;
console.log(x);
}
});
}
$( "input[type='checkbox'], input[type='radio']" ).on( "click", showValues );
$( "select" ).on( "change", showValues );
showValues();
});
and I store the values in variable
if(isset($_POST['q10']))
{
if($_POST['q10'] == 2){
$_SESSION['q10']=1;
}else{
$_SESSION['q10']=0;
}
}
then i use another ajax for catching the updated values but it gives me the old values
$(document).ready(function(){
$("#result").click(function(){
$.ajax({
type: 'GET',
success: function(res) {
var session = <?php echo(json_encode($page_session)); ?>;
if(session == 1){
document.getElementById("s1").style.display="block";
document.getElementById("s1").textContent = <?php echo(json_encode($_SESSION['q1'])); ?> ;
}
}
});
});
});
Using jQuery to call an endpoint and populate the data on the frontend is a common task. After searching and using multiple solutions the below is my current blueprint for any ajax calls.
How can I improve the following to be faster and more efficient? I realize doing it in pure javascript will be faster but at this point I assume jQuery will be present.
Frontend - Javascript:
$(document).ready(function()
{
function callEndpoint( call_url, payload ){
return $.ajax({
url: call_url,
type: 'GET',
data: payload
});
}
$( '.get-endpoint' ).click( function() {
sSelected = $( this ).text();
console.log( sSelected );
oRequest = callEndpoint( '/play/endpoint2.php', { 'type': sSelected } );
oRequest.done(function( sJson ) {
aData = JSON.parse( sJson );
$( '.from-endpoint' ).text( aData.text );
});
});
});
Frontend - Html:
<body>
<button class="get-endpoint">Games</button>
<button class="get-endpoint">Books</button>
<button class="get-endpoint">Comics</button>
<div class="from-endpoint">Coming soon...</div>
</body>
Backend - PHP:
$aReturn[ 'text' ] = '';
if( !empty( $_GET ) )
{
if( $_GET[ 'type' ] == 'Games' )
{
$aReturn[ 'text' ] = 'Text for games';
}
else if( $_GET[ 'type' ] == 'Books' )
{
$aReturn[ 'text' ] = 'Text for books';
}
else if( $_GET[ 'type' ] == 'Comics' )
{
$aReturn[ 'text' ] = 'Text for comics';
}
}
$sJson = json_encode( $aReturn, 1 );
header( 'Content-Type: application/json' );
echo $sJson;
I don't think that this code can be more efficient in jQuery.
But you have some options left to give a more efficient feeling :
You can use pagination to get a portion of your data each time. The
less data to load, the quicker it get. And your application will be
more responsive to the user's actions. This solution is a trick for
the user, because it will take in reality more time than before to load all the data.
You can keep previous loaded data so when you click back on a button,
it won't load again the data. But, this can only be used if the data
won't change much between each click. The first time you will click
on a button, it will take the same time as before, but the next time,
it will be immediat.
Be aware that the more HTML code you load, the more it will take time to initiate JavaScript behavior on it.
Looks like your categories won't change often. You can save some bandwidth by using JavaScript localstorage or cookies to cache data. If you plan on connecting to a mysql database at somepoint you can use StoredProcedures which are variablized precompiled statements.
Since you are anyways going to use JSON and jQuery, I would suggest that you should check out the getJSON method of jQuery. I feel that it would reduce some lines of code, though I am not sure if it would help it become more efficient.
Anyways getJSON is just a shorthand of AJAX and I thought I should suggest this.
This could be a good approach for AJAX data transport browser->server->browser. Hope it suites your needs.
jQuery
$( function () {
function fetch( data ) {
var encoding = data.encoding,
url = data.url,
params = data.params,
type = ( data.type ) ? : 'GET',
cache = ( data.cache ) ? : 'false',
async = ( data.async ) ? : 'true';
return $.ajax({
url: url,
async: async,
cache: cache,
data: params,
dataType: encoding,
type: type
});
}
var options = {
url: 'controller.php',
params: {
param_one: value_one,
param_two: value_two,
param_n: value_n
},
encoding: 'json'
};
// Get the JSON feed from the server
$.when( fetch( options ) ).then( function ( response ) {
// Is there anything in the pool?
if ( response ) {
// Store the response and use it in your code
var data = response.data;
console.log( data.responseOne );
console.log( data.responseTwo );
}
});
});
PHP Controller
// Set header to application/json
header( 'Content-type: application/json' );
// Create the DB connection object
$dbc = new mysqli( DB_HOST, DB_USER, DB_PASS, DB_NAME );
// Initialize parameters array
$params = array();
// Store the query variables in an array
$query_type = ( $_GET ) ? : $_POST;
// Run foreach and store the values in an array
foreach ( $query_type as $key => $value ) {
$params[ $key ] = mysqli_real_escape_string( $dbc, $value );
}
// Now you can access passed parameters like $params['param_name']
// This would be the data obtained from DB or some server array processing, whatever
$response = array(
'data' => array(
'response_one' => 'some_value',
'response_two' => 'another_value'
)
);
// Encode the result
echo json_encode( $response );
If you don't want use pure javascript, you can improve your jQuery code with better selectors
For example, you can add an id in <div class="from-endpoint">
You can add tag in selector like this:
$('button.get-endpoint')
You can drop your getEndpoint method and just use the $.get method.
$(document).ready(function()
{
$( '.get-endpoint' ).click( function() {
sSelected = $( this ).text();
console.log( sSelected );
oRequest = $.get('/play/endpoint2.php', { 'type': sSelected });
oRequest.done(function( sJson ) {
aData = JSON.parse( sJson );
$( '.from-endpoint' ).text( aData.text );
});
});
});
You can make your code lint compliant.
$(document).ready(function()
{
$( '.get-endpoint' ).click( function() {
var sSelected = $( this ).text();
console.log( sSelected );
oRequest = $.get('/play/endpoint2.php', { type: sSelected });
oRequest.done(function( sJson ) {
var aData = JSON.parse( sJson );
$( '.from-endpoint' ).text( aData.text );
});
});
});
Use success instead of done & move the callback to it's own function
$(document).ready(function()
{
$( '.get-endpoint' ).click( function() {
var sSelected = $( this ).text();
console.log( sSelected );
$.get(
'/play/endpoint2.php',
{ type: sSelected },
insertData
);
});
});
function insertData( sJson ) {
var aData = JSON.parse( sJson );
$( '.from-endpoint' ).text( aData.text );
}
Use $.getJSON instead of $.get or $.ajax
$(document).ready(function()
{
$( '.get-endpoint' ).click( function() {
var sSelected = $( this ).text();
console.log( sSelected );
$.getJSON(
'/play/endpoint2.php',
{ type: sSelected },
insertData
);
});
});
function insertData( data ) {
$( '.from-endpoint' ).text( data.text );
}
I'm trying to execute the remote code completion example in Jquery Mobile using the following url: http://demos.jquerymobile.com/1.4.0/listview-autocomplete-remote/
I use latest PhoneGap with jquery mobile version 1.4.3
the auto complete javascript code:
$(function() {
$( "#drink_brand_autocomplete" ).on( "filterablebeforefilter", function ( e, data ) {
var $ul = $( this ),
$input = $( data.input ),
value = $input.val(),
html = "";
$ul.html( "" );
if ( value && value.length > 2 ) {
$ul.html( "<li><div class='ui-loader'><span class='ui-icon ui-icon-loading'></span></div></li>" );
$ul.listview( "refresh" );
$.ajax({
url: "http://myalcoholist.com/drink-management/drink/drink-brand-autocomplete",
dataType: "jsonp",
crossDomain: true,
data: {
q: $input.val()
}
})
.then( function ( response ) {
console.log("response");
$.each( response, function ( i, val ) {
html += "<li>" + val + "</li>";
});
console.log(html);
$ul.html( html );
$ul.listview( "refresh" );
$ul.trigger( "updatelayout");
});
}
});
});
in chrome developer console i can see that the ajax call is being executed fine and the server returns a json array.
the .then() is not being executed, no ideas why.
i tried .done() instead but i got the same results.
i don't get any javascript errors.
any ideas?
I used the example from jQuery mobile site Autocomplete source code
It's working fine, but when I tried to give alert in the script inside the listviewbeforefilter event, it's showing the alert 3 times, so when 3 characters are entered, it will prompt around 7-9 times.
Why is it showing so many alerts? I thinks it should prompt only once when the character is inserted.
Here is the code retrun in script for autocomplete:
$( document ).on( "pageinit", "#myPage", function() {
alert("abc");
$( "#autocomplete" ).on( "filterablebeforefilter", function ( e, data ) {
var $ul = $( this ),
$input = $( data.input ),
value = $input.val(),
html = "";
$ul.html( "" );
alert("789");
if ( value && value.length > 2 ) {
$ul.html( "<li><div class='ui-loader'><span class='ui-icon ui-icon-loading'></span></div></li>" );
$ul.listview( "refresh" );
$.ajax({
url: "http://gd.geobytes.com/AutoCompleteCity",
dataType: "jsonp",
crossDomain: true,
data: {
q: $input.val()
}
})
.then( function ( response ) {
alert("123");
$.each( response, function ( i, val ) {
html += "<li>" + val + "</li>";
});
$ul.html( html );
$ul.listview( "refresh" );
$ul.trigger( "updatelayout");
});
}
});
});
Here is the code return in the body tag:
<div data-role="content">
<h3>Cities worldwide</h3>
<p>After you enter <strong>at least three characters</strong> the autocomplete `function will show all possible matches.</p>
<ul id="autocomplete" data-role="listview" data-inset="true" data-filter="true" `data-filter-placeholder="Find a city..." data-filter-theme="a">
</ul>
</div>