Using a jQuery script in a .php file and adding a condition - javascript

How can I run the following woodmart theme jquery script based on a php condition?
The jQuery script here asks for age validation on the website and restricts the page if there is no validation.
I just want to use this code for some category products but I don't know how to add condition to jQuery script and I am bad at javascript.
(function($) {
woodmartThemeModule.ageVerify = function() {
if ( typeof Cookies === 'undefined' ) {
return;
}
if ( woodmart_settings.age_verify !== 'yes' || Cookies.get('woodmart_age_verify') === 'confirmed') {
return;
}
$.magnificPopup.open({
items : {
src: '.wd-age-verify'
},
type : 'inline',
closeOnBgClick : false,
closeBtnInside : false,
showCloseBtn : false,
enableEscapeKey: false,
removalDelay : 500,
tClose : woodmart_settings.close,
tLoading : woodmart_settings.loading,
callbacks : {
beforeOpen: function() {
this.st.mainClass = 'mfp-move-horizontal wd-promo-popup-wrapper';
}
}
});
$('.wd-age-verify-allowed').on('click', function(e) {
e.preventDefault();
Cookies.set('woodmart_age_verify', 'confirmed', {
expires: parseInt(woodmart_settings.age_verify_expires),
path : '/',
secure : woodmart_settings.cookie_secure_param
});
$.magnificPopup.close();
});
$('.wd-age-verify-forbidden').on('click', function(e) {
e.preventDefault();
$('.wd-age-verify').addClass('wd-forbidden');
});
};
$(document).ready(function() {
woodmartThemeModule.ageVerify();
});
})(jQuery);
UPDATE
The code here is working now, echo is no more, I also added 999 as priority and it works fine that way.
<?php
add_action( 'wp_footer', 'add_age_verify', 999 );
function add_age_verify() {
if( is_product_category( array( 4201, 4500, 4300 ) ) ) {
?>
<script type="text/javascript"> (function($) {
woodmartThemeModule.ageVerify = function() {
if ( typeof Cookies === 'undefined' ) {
return;
}
if ( woodmart_settings.age_verify !== 'yes' || Cookies.get('woodmart_age_verify') === 'confirmed') {
return;
}
$.magnificPopup.open({
items : {
src: '.wd-age-verify'
},
type : 'inline',
closeOnBgClick : false,
closeBtnInside : false,
showCloseBtn : false,
enableEscapeKey: false,
removalDelay : 500,
tClose : woodmart_settings.close,
tLoading : woodmart_settings.loading,
callbacks : {
beforeOpen: function() {
this.st.mainClass = 'mfp-move-horizontal wd-promo-popup-wrapper';
}
}
});
$('.wd-age-verify-allowed').on('click', function(e) {
e.preventDefault();
Cookies.set('woodmart_age_verify', 'confirmed', {
expires: parseInt(woodmart_settings.age_verify_expires),
path : '/',
secure : woodmart_settings.cookie_secure_param
});
$.magnificPopup.close();
});
$('.wd-age-verify-forbidden').on('click', function(e) {
e.preventDefault();
$('.wd-age-verify').addClass('wd-forbidden');
});
};
$(document).ready(function() {
woodmartThemeModule.ageVerify();
});
})(jQuery); </script>
<?php
}
}

You can send a JQuery ajax call to the php script, the php script then sends it back to the javascript file and then you can easily use the variable within javascript.
$.ajax({
url: 'path/to/your/php/file',
type: 'get',
success: (res) => {
//do things when you get the response
},
error: (err) => {
//do things when you get the error, error is optional
},
})
or you can even simplify it
$.get('url/to/your/script', (res) => {
//do things with the response
})

I copied the jQuery script into the child theme and then <script src='/wp-content/themes/woodmart-child/js/scripts/global/ageVerify.js'></script> to show the jQuery script, while doing this I added the conditions with PHP and now it works fine.
The final version of the code with PHP is like this.
<?php
add_action( 'wp_footer', 'add_age_verify_jquery', 999 );
function add_age_verify_jquery() {
if ( has_term(array('jacket', 'fridge', 'hats', 'magic wand'), 'product_cat')) {
?>
<script src='/wp-content/themes/woodmart-child/js/scripts/global/ageVerify.js'></script>
<?php
}
}
?>

Related

How to add a process bar when you waiting for a response from the server

could someone help me with one problem? I want to add a process bar when you waiting for a response from the server (Django 3.x).
Step to reproduce:
On the page 'A' we have the form.
Enter data to form.
Submit POST request by clicking to button on the page 'A'.
Waiting for getting the result on the page 'A'.
Get the result on the page 'A'.
So, I want to add process bar after 4th and before 5th points on the page 'A'. When you will get the result on the page 'A' it should disappear.
Python 3.7
Django 3.x
You can use nprogress, it's a library used for progress bars. Use this inside the interceptor where you can config it for displaying only when request is in progress until finished.
There are lots of ways to do this. I think using jquery would be easier. Basically you just need to prevent submitting the page and do an Ajax request to server. something like
<script type='text/javascript'>
$(document).ready(function () {
$("form").submit(function (e) {
// prevent page loading
e.preventDefault(e);
$('#loadinAnimation').show();
// preapre formdata
$.ajax({
type: "yourRequestType",
url: "yourUrlEndpoint",
data: formdata,
success: function (data) {
$('#loadinAnimation').hide();
// do rest of the work with data
}
});
});
});
</script>
and show appropriate loading animation in your html part
<div id='loadinAnimation' style='display:none'>
<div>loading gif</div>
</div>
You can also do it using UiKit Library in Javascript on your Django Template Page.
Below code is when a file is Uploaded
In your template file (template.html)
<body>
..
<form>
<progress id="js-progressbar" class="uk-progress" value="0" max="100" hidden></progress>
...
<div class="uk-alert-danger uk-margin-top uk-hidden" id="upload_error" uk-alert></div>
...
</form>
</head>
<script type="text/javascript">
$(document).ready(function(){
var bar = document.getElementById('js-progressbar');
UIkit.upload('.js-upload-list', {
url: '',
name : "customer-docs",
params :{
"csrfmiddlewaretoken":"{{csrf_token}}"
},
method : "POST",
concurrent:1,
allow:'*.(csv|xlsx)',
beforeSend: function (environment) {
console.log('beforeSend', arguments);
// The environment object can still be modified here.
// var {data, method, headers, xhr, responseType} = environment;
},
beforeAll: function (args,files) {
console.log('beforeAll', arguments);
},
load: function () {
console.log('load', arguments);
},
error: function (files) {
console.log("---------------")
},
complete: function () {
console.log('complete', arguments);
},
loadStart: function (e) {
console.log('loadStart', arguments);
bar.removeAttribute('hidden');
bar.max = e.total;
bar.value = e.loaded;
},
progress: function (e) {
console.log('progress', arguments);
bar.max = e.total;
bar.value = e.loaded;
},
loadEnd: function (e) {
console.log('loadEnd', arguments);
bar.max = e.total;
bar.value = e.loaded;
},
completeAll: function (data) {
console.log('completeAll', arguments);
console.log('completeAll', data);
let redirect_loc = ""
setTimeout(function () {
bar.setAttribute('hidden', 'hidden');
}, 1000);
// This is the response from your POST method of views.py
data.responseText = JSON.parse(data.responseText)
if(data.responseText.status == 201){
// swal is another library to show sweet alert pop ups
swal({
icon: data.responseText.status_icon,
closeOnClickOutside: true,
text: data.responseText.message,
buttons: {
Done: true
},
}).then((value) => {
switch (value) {
case "Done":
window.location.href = ""
break;
}
});
}
else if(data.responseText.status == 500){
swal({
icon: data.responseText.status_icon,
closeOnClickOutside: true,
text: data.responseText.message,
buttons: {
Ok: true
},
}).then((value) => {
switch (value) {
case "Ok":
window.location.href = ""
break;
}
});
}
}
});
// This block of code is to restrict user to upload only specific FILE formats (below example is for CSV & XLSX files)
(function() {
var _old_alert = window.alert;
window.alert = function(e) {
console.log(e)
if(e.includes("csv|xlsx") || e.includes("Invalid file type")) {
$("#upload_error").html("Invalid file format. Valid formats are CSV, XLSX").removeClass('uk-hidden')
}else if(e.includes("Internal Server Error")) {
$("#upload_error").html("Internal Server Error Kindly upload Documents again").removeClass('uk-hidden')
}
else {
_old_alert.apply(window,arguments);
$("#upload_error").addClass('uk-hidden').html("")
}
};
})();
});
</script>
On your views.py you can do your computation and once done, you can return a response like below
resp_json = {
"status" : 201,
"status_icon" : "success",
"url" : "/",
"message": message
}
return HttpResponse(json.dumps(resp_json))
For more info on SWAL (Sweet Alerts), visit https://sweetalert.js.org/guides/

jquery for intlTelInput can't add event listener

trying to do something similar to the country code listener drop down but with a text box which should populate with the country code (so that I can subsequently use the value in PHP code).
Adding the event listener doesn't work:
<script>
$(document).ready(function(){
$("#mobile").intlTelInput({
onlyCountries: ["au","ca","us","nz","gb"],
utilsScript: "<?php echo get_template_directory_uri(); ?>/intl-tel-input/build/js/utils.js",
geoIpLookup: function(callback) {
$.get("https://ipinfo.io", function() {}, "jsonp").always(function(resp) {
var countryCode = (resp && resp.country) ? resp.country : "";
callback(countryCode);
});
},
initialCountry: "auto"
}).addEventListener('countrychange', function() {
$("#country_code").value = "changed"
});;
$('#verify').attr('disabled','disabled');
$("#mobile").on('input', function() {
if ($("#mobile").intlTelInput("isValidNumber")) {
$('#verify').removeAttr('disabled');
$("#country_code").innerHTML = "changed"
} else {
$('#verify').attr('disabled','disabled');
}
});
$("#register-form").submit(function() {
$("#mobile").val($("#mobile").intlTelInput("getNumber"));
});
});
</script>
Maybe, it has been months since you asked this question, below is the solution.
You misunderstood the addEventListener. This could be a function of any other Javascript framework. But not jQuery's.
User the below code as a script after the initialization. You can do what your you want with countryData.dialCode which gives you the country code.
jQuery("#mobile").on('countrychange', function(e, countryData){
console.log(countryData.dialCode);
})
Below is the sample countryData which the intlTelInput returns.
{ areaCodes: null, dialCode: "44", iso2: "gb", name: "United Kingdom", priority: 0 }
My working version is (this is based on with jQuery library version of Intelinput)
var mobile_with_country_code = '<?php echo $mobile_with_country_code; ?>';
var mobile_number_input = document.querySelector("#mobile");
mobile_number = window.intlTelInput(mobile_number_input, {
initialCountry: "ae",
separateDialCode: true,
preferredCountries: ["ae","bh","kw","om","qa","sa"],
});
if(mobile_with_country_code != ''){
mobile_number.setNumber(mobile_with_country_code);
}
jQuery('#country_code').val(mobile_number.getSelectedCountryData().dialCode);
mobile_number_input.addEventListener("countrychange", function() {
jQuery('#country_code').val(mobile_number.getSelectedCountryData().dialCode);
});

post callback function synchronization

I'm using datatables and after post I want to refresh the page after changes in the database are done. But for now it's pretty much random if the page refreshes before or after the database is updated. I also tried to add 'success:' to the callback function but this doesn't help.
Script for datatables projects.php:
<script> $(document).ready( function () {
var projects = $('#projects').DataTable({
paging:true, dom: 'Blfrtip', colReorder: true, select: {style: 'single'},
buttons: [
{
text: 'Edit',
action: function () {
$projectID = $(projects.row('.selected').node()).data('id');
if ($projectID === undefined)
{
alert("Please select a project.");
} else {
window.location.href = "../projects/editProject.php?projectID=" + $projectID;
}
}
},
{
text: 'Add',
action: function () {
window.location.href = "../projects/addProject.php";
}
},
{
text: 'Delete',
action: function () {
$projectID = $(projects.row('.selected').node()).data('id');
if ($projectID === undefined)
{
alert("Please select a project.");
} else {
$.post("../projects/deleteProject.php",
{
projectID: $projectID,
function() {
window.location.reload(true);
}
}
);
}
}
}
] }); } ); </script>
deleteProject.php:
<?php
require("../database/dbService.php");
require("../projects/deleteProjectService.php");
session_start();
$connection = connectToDB();
// check if input data is set
if (!isset($_POST['projectID'])){
header("Location: ../projects/projects.php");
exit;
}
// input data
$projectID = $_POST['projectID'];
deleteProject($connection, $projectID);
$_SESSION['message'] = "The project has been deleted!";
?>
You placed callback function in the wrong place, it should have been:
$.post(
"../projects/deleteProject.php",
{ projectID: $projectID },
function(){ window.location.reload(true); }
);

How to run a jQuery code after an angular function was loaded?

Basically I upload an image through angular with ng-file-upload and then I want to display it and initialize a jQuery plugin called Cropper.
How can I run the jQuery code from this one? The only way it works is when I have the $scope.loadedImage loaded before the upload.
HTML:
<img id="cropImage" ng-src="/{{loadedImage}}" />
Angular
$scope.upload = function (dataUrl) {
Upload.upload({
url: '/photocalc/upload/file',
method: 'POST',
file: dataUrl,
}).then(function (response) {
$timeout(function () {
$scope.result = response.status;
$scope.loadedImage = response.data;
jQuery('#cropImage').cropper({
viewMode: 0,
zoomable: false,
dragMode: 'crop',
guides: true,
highlight: true,
cropBoxMovable: true,
cropBoxResizable: true,
crop: function(e) {
// Output the result data for cropping image.
console.log(e.x);
console.log(e.y);
console.log(e.width);
console.log(e.height);
console.log(e.rotate);
console.log(e.scaleX);
console.log(e.scaleY);
}
});
});
}, function (response) {
if (response.status > 0) $scope.errorMsg = response.status
+ ': ' + response.data;
}, function (evt) {
$scope.progress = parseInt(100.0 * evt.loaded / evt.total);
});
}
I would write an own directive which will observe the src attribute and init the cropper when the image loaded.
In my mind the image.onload will only fire once so you would have to remove and place a new image but try it without removing at first :)
edit: as Kevin B said this thought was wrong
angular.module( "$name$" ).directive( "imageCropper", [ function () {
return {
restrict: "A",
link : function ( $scope, $el, $attr ) {
$attr.$observe( "src", function ( src ) {
$el.on( "load", function () {
$timeout( function () {
$scope.result = response.status;
$scope.loadedImage = response.data;
jQuery( '#cropImage' ).cropper( {
viewMode : 0,
zoomable : false,
dragMode : 'crop',
guides : true,
highlight : true,
cropBoxMovable : true,
cropBoxResizable: true,
crop : function ( e ) {
// Output the result data for cropping image.
console.log( e.x );
console.log( e.y );
console.log( e.width );
console.log( e.height );
console.log( e.rotate );
console.log( e.scaleX );
console.log( e.scaleY );
}
} );
} );
} );
} );
}
}
} ] );
For this kind of situation you can use setTimeout and execute your jquery code after a little delay. Because it took a little bit(a very little) of time for angular to bind data in the view. So you need a little delay.
Also I've written a blog post where I've given a generic solution to call a callback function after ng-repeat finish binding all its data. You can try that as well. Check this post here. Let me know if you have any confusion. Thanks.

JEditable, how to handle a JSON response?

Right now, the server response I'm working with sends back a JSON response like this:
{"status":1}
After saving, jeditable places the actual response: {"status":1} on the page. Anyway to get around this issue?
A better solution is to post-process the returned json data before it hits the page.
Suppose your server returns the following json string:
{ "status": 1, "result": "value to be displayed", "other": "some other data" }
and you would like to process the "status" and "other" fields, and display the "result" field in the jeditable input field.
Add the following 2 lines to jquery.jeditable.js:
(around line 95):
var intercept = settings.intercept || function(s) {return s; };
(around line 350, right after " success : function(result, status) {"
result = intercept.apply(self,[result]);
Then, in your own code, do something like the following:
$(some_field).editable(
'/some_url_on_your_server',
{
indicator : "<img src='/images/spinner.gif'>",
tooltip: "Click to edit.",
indicator: "Saving...",
onblur: "submit",
intercept: function (jsondata) {
obj = jQuery.parseJSON(jsondata);
// do something with obj.status and obj.other
return(obj.result);
},
etc.
This allows you do cool stuff like having your server convert abbreviations to full strings etc.
Enjoy!
There's a simple way of doing this by using the callback. .editable() converts any response to a string, so the response has to be converted to a JSON variable. The values can then be retrieved and then written using a '.text()' method. Check the code:
$("#myField").editable("http://www.example.com/save.php", {
submit : 'Save',
cancel : 'Cancel',
onblur : "ignore",
name : "sentText",
callback : function(value, settings) {
var json = $.parseJSON(value);
$("#myField").text(json.sentText);
}
});
This is how I handled the json response.
First, set the datatype using ajaxoptions. Then, handle your data in the callback function. Therein, this.revert is your original value.
oTable.$('td:eq(3)').editable('/admin/products/add_quantity_used', {
"callback" : function(sValue, y) {
var aPos = oTable.fnGetPosition(this);
if($("#dialog-message").length != 0){
$("#dialog-message").remove();
}
if(!sValue.status){
$("body").append('<div id="dialog-message" style="display:none;">'+sValue.value+'</div>');
$( "#dialog-message" ).dialog({
modal: true,
buttons: {
Ok: function() {
$( this ).dialog( "close" );
}
}
});
if(this.revert != '')
oTable.fnUpdate(this.revert, aPos[0], aPos[1]);
else
oTable.fnUpdate("click to edit", aPos[0], aPos[1]);
}else
if(sValue.status)
oTable.fnUpdate(sValue.value, aPos[0], aPos[1]);
},
"submitdata" : function(value, settings) {
return {
"data[users_to_products][users_to_products_id]" : this.parentNode.getAttribute('id'),
"column" : oTable.fnGetPosition(this)[2]
};
},
"height" : "30px",
"width" : "30px",
"maxlength" : "3",
"name" : "data[users_to_products][quantity_used]",
"ajaxoptions": {"dataType":"json"}
}).attr('align', 'center');
So the solution I came up with is similar to what madcapnmckay answered here.
var editableTextArea = $('.editable-textarea');
editableTextArea.editable(submitEditableTextArea, {
type : 'textarea',
cancel : 'Cancel',
submit : 'Save',
name : editableTextArea.attr('id'),
method : 'post',
data : function(value, settings) {
return $.fn.stripHTMLforAJAX(value);
},
event : "dblclick",
onsubmit : function(value, settings) {
//jquery bug: on callback reset display from block to inline
$('.btn-edit').show(0, function(){$(this).css('display','inline');});
},
onreset : function(value, settings) {
//jquery bug: on callback reset display from block to inline
$('.btn-edit').show(0, function(){$(this).css('display','inline');});
}
});
Then the url function is
function submitEditableTextArea(value, settings) {
var edits = new Object();
var result = $.fn.addHTMLfromAJAX(value);
edits[settings.name] = [value];
var returned = $.ajax({
type : "POST",
data : edits,
dataType : "json",
success : function(_data) {
var json = eval( _data );
if ( json.status == 1 ) {
console.log('success');
}
}
});
return(result);
}

Categories