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
Related
I am using ajax to validate user credentials after i have validated the user has input data into the required fields but afterwords the form is not being submitted. I have created a variable submit_form which is supposed to determine if the default form action is performed or not but when set it to true and console log it, it still seems to continue it's default value of false, why is it like that and how can change it so my form can submit after the username and password are correct.
Here is my screenshot of the console in the browser
Here is a my code:
/*global $*/
/*global _*/
$(document).ready(function() {
'use strict';
$('#login-form').on('submit', function(event) {
var form_items = {
username: { required: true, name: 'Username' },
password: { required: true, name: 'Password' },
token: {}
};
var $login_form = $(this);
var submit_form = false;
var errors;
var display = '';
var data;
var validation = new Validation( form_items );
validation = validation.check( $login_form['context'] );
// If any element has the class for errors, remove the class
$('.has-error').removeClass('has-error');
if ( validation.passed() ) {
data = JSON.stringify( validation.getData() );
$.ajax({
method: "POST",
url: "ajax/login.ajax.php",
data: { info: data }
}).done(function( response ) {
response = JSON.parse(response);
// if the error list display is there, remove it
$('.bg-danger').parent().remove();
if ( _.has(response, 'errors') ) {
errors = response['errors'];
display = '<div class="form-group"><ul class="bg-danger">';
if ( _.isArray(errors) || _.isObject(errors) ) {
_.each( errors, function(elem, index, list) {
display += '<li>' + elem + '</li>';
});
} else {
display += '<li>' + errors + '</li>';
}
display += '</ul></div>';
$login_form.prepend( display );
} else {
submit_form = true;
}
});
console.log( submit_form );
} else {
// if the error list display is there, remove it
$('.bg-danger').parent().remove();
errors = validation.getErrors();
display = '<div class="form-group"><ul class="bg-danger">';
_.each( errors, function(elem, index, list) {
var $form_element = $('#'+index); // get form element
$form_element.parent().parent().addClass('has-error');
display += '<li>' + elem + '</li>';
});
display += '</ul></div>';
$login_form.prepend( display );
}
if ( !submit_form ) {
event.preventDefault();
}
});
});
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.
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 am building coupon website. I need to trigger ajax action based on url of page. Let me explain.
For example, if user goes to page website_url/?coupon_id=99 - he gets page website_url and popup with ajax action inside it (ajax gets data for coupon post type with id=99 and show it's values).
If user goes to page website_url/page1/?coupon_id=99 - he gets page website_url/page1/ and the same popup.
You can see this logic in action on some coupon websites, for example, coupondunia.in
I created ajax action, it's working
function coupon_get_code(){
$couponid = $_GET['couponid'];
$code = get_post( $couponid );
if( !empty( $code ) ){
$offer_coupon = get_post_meta( $code->ID, 'coupon', true );
$response .= '<div class="coupon_modal_coupon">'.$offer_coupon.'</div>';
}
else{
$response = __( 'Offer does not exists', 'textdomain' );
}
echo $response ;
die;
}
add_action('wp_ajax_ajax_code', 'coupon_get_code');
add_action('wp_ajax_nopriv_ajax_code', 'coupon_get_code');
Currently I made triggering ajax action based on click, like this
// Coupon Modal
$( '.offer_coupon.masked_coupon:not(.expired_coupon)' ).live("click", function(e){
var $this = $(this);
var couponid = $this.data('couponid');
$.pgwModal({
url: translation.ajax_url + "?action=ajax_code&couponid=" + couponid,
titleBar: false,
ajaxOptions : {
success : function(response) {
if (response) {
$.pgwModal({ pushContent: response });
} else {
$.pgwModal({ pushContent: 'An error has occured' });
}
}
}
});
});
But how to trigger this ajax request based on url?
You could get the last number characters from the URL on page load (equal to the coupon id), instead of getting it on click from the data attribute.
$(window).on('load', function() {
// Get the last numbers from the current page URL using Regex
var couponid = window.location.href.match(/\d+$/);
$.pgwModal({
url: translation.ajax_url + "?action=ajax_code&couponid=" + couponid,
titleBar: false,
ajaxOptions : {
success : function(response) {
if (response) {
$.pgwModal({ pushContent: response });
} else {
$.pgwModal({ pushContent: 'An error has occured' });
}
}
}
});
});
Put the jQuery in a file named ajax-coupon.js and conditionally enqueue the script.
// Conditionally enqueue your script only if the template coupons.php is used to display the page.
function my_scripts_method() {
// Register your script location, dependencies and version
wp_register_script('ajax-coupon', get_template_directory_uri() . '/js/ajax-coupon.js', array('jquery'), '1.0' );
// Check if the current page is using coupons.php, if so, load the script.
if ( is_page_template( 'coupons.php' ) ) {
wp_enqueue_script('ajax-coupon');
}
}
add_action('wp_enqueue_scripts', 'my_scripts_method');
I think I found function which can help me. Testing now.
function GetURLParameter(sParam){
var sPageURL = window.location.search.substring(1);
var sURLVariables = sPageURL.split('&');
for (var i = 0; i < sURLVariables.length; i++)
{
var sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == sParam)
{
return sParameterName[1];
}
}
}
So my ajax trigger can be like this
var coupontrigger = GetURLParameter("couponid");
if(coupontrigger){
$.pgwModal({
url: translation.ajax_url + "?action=ajax_code&couponid=" + coupontrigger,
titleBar: false,
ajaxOptions : {
success : function(response) {
if (response) {
$.pgwModal({ pushContent: response });
} else {
$.pgwModal({ pushContent: 'An error has occured' });
}
}
}
});
};
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?