Im trying to conditionally call script depending of language in Wordpress with polylang. I can see the script in Google Inspector but it doesn't work. Script works correctly in customizer.
Code:
<?php
if(pll_current_language() == 'en') : ?>
<script type="text/javascript">
const cartBtn = document.querySelector('.cart button');
const formCart = document.querySelector('div.product.elementor form.cart');
var newBtn = document.createElement('a');
newBtn.innerHTML = "<h1>Back to shop</h1>";
newBtn.classList.add('cart-custom-link');
newBtn.setAttribute("href", "/shop/");
cartBtn.addEventListener('click', function() {
formCart.appendChild(newBtn);
console.log('click');
});
</script>
<?php endif; ?>
<?php
if(pll_current_language() == 'uk') : ?>
<script type="text/javascript">
const cartBtn = document.querySelector('.cart button');
const formCart = document.querySelector('div.product.elementor form.cart');
var newBtn = document.createElement('a');
newBtn.innerHTML = "<h1>Повернутися до магазину</h1>";
newBtn.classList.add('cart-custom-link');
newBtn.setAttribute("href", "/shop-uk/");
cartBtn.addEventListener('click', function() {
formCart.appendChild(newBtn);
console.log('click');
});
</script>
<?php endif; ?>
Is there any solution?
My assumption why the code does not work is because the script code is added (and therefore run) before the DOM tree is ready. Thus, it has to be wrapped in a window.onload handler (or jQuery's $(document).ready();). Also, copy&pasting the JS code for every language isn't really pretty. There's a cleaner solution:
place the code in a .js-file
use a JS-object for the text to be translated
enqueue the script, then use wp_localize_script() on it
like so:
my_cart.js
window.onload = function () {
const cartBtn = document.querySelector('.cart button');
const formCart = document.querySelector('div.product.elementor form.cart');
var newBtn = document.createElement('a');
newBtn.innerHTML = "<h1>"+cart_localize.back_to_shop+"</h1>";
newBtn.classList.add('cart-custom-link');
newBtn.setAttribute("href", "/shop-uk/");
cartBtn.addEventListener('click', function() {
formCart.appendChild(newBtn);
console.log('click');
});
}
Next, within PHP, enqueue the script like so:
function load_localized_scripts() {
$cart_localize = array(
'back_to_shop' => 'Back to shop', // default
);
if (pll_current_language() == 'uk') {
$cart_localize['back_to_shop'] = 'Повернутися до магазину';
}
if (pll_current_language() == 'de') {
$cart_localize['back_to_shop'] = 'Zurück zum Shop';
}
wp_enqueue_script('my-cart', plugin_dir_url( __FILE__ ) . 'js/my_cart.js');
wp_localize_script('my-cart', 'cart_localize', $cart_localize);
}
add_action('wp_enqueue_scripts', 'load_localized_scripts');
The $cart_localize array may contain as many key → value pairs of label => text translation as you like. It is inserted into the JavaScript object named like the 2nd argument of the wp_localized_script function. Then, you can access it within JS using cart_localize.key_name.
Technically, you can also register a Polylang string using pll_register_string named back_to_shop and easily insert the translations you entered under Languages → String translations using the pll__() function:
$cart_localize['back_to_shop'] = pll__('back_to_shop');
I won't fully cover this here, since I'm not sure this matches the way you want to manage translations.
Related
I have a PHP code, where I need to make some manipulations with JS, and I tried the following
<?php
include './parse.service.php';
echo putContent();
$jsScript = "
<script type='text/javascript'>
const json = require('./transacitions.json');
window.onload = modifyData;
function modifyData() {
document.getElementById('n_transactions').innerHTML = parseInt(document.getElementById('n_transactions').innerHTML, 10) + json.data.length;
document.getElementById('total_received').getElementsByTagName('font')[0].getElementsByTagName('span')[0].innerHTML = `${this.totalReceived(convertToFloat(document.getElementById('total_received').getElementsByTagName('font')[0].getElementsByTagName('span')[0].innerHTML))} BTC`;
document.getElementById('final_balance').getElementsByTagName('font')[0].getElementsByTagName('span')[0].innerHTML = `${this.finalBalance(convertToFloat(document.getElementById('final_balance').getElementsByTagName('font')[0].getElementsByTagName('span')[0].innerHTML))} BTC`;
}
function convertToFloat(element) {
var numb = element.match(/[+-]?\d+(\.\d+)?/g);
numb = numb.join(\"\");
return (parseFloat(numb, 10));
}
function totalReceived(quantity) {
json.data.forEach(element => {
if (element.finalSum > 0) {
quantity += element.finalSum;
};
});
return quantity;
};
function finalBalance(quantity) {
json.data.forEach(element => {
quantity += element.finalSum;
});
return quantity;
};
</script>";
echo $jsScript;
?>
And when I echo the created "script", i get the message similar to this Uncaught Error: Call to undefined function totalReceived() how shall I modify the code, in sucha a way that JS will integrate normally in my PHP script.
$ has special meaning inside PHP strings delimited with " characters, so ${this.totalReceived is causing the PHP engine to try to find an execute a function called totalReceived.
There's no apparent reason to use a PHP string here anyway. Just exit PHP mode and just output the code directly.
<?php
include './parse.service.php';
echo putContent();
?>
<script type='text/javascript'>
const json = require('./transacitions.json');
window.onload = modifyData;
// etc etc
</script>
Better yet. Move the JS to a separate file and include it with <script src>.
Is there a way via some lines of JavaScript to assign the value of a custom meta field in a Wordpress post/page to a JavaScript variable?
In other words, I've got a custom meta field in all my Wordpress posts and pages named "customamznsearch". I'd like to assign the value of that field to a JavaScript variable with the same name... or different name if need be.
Also, an added bonus would be to also define a static value for the variable if no data is available from that meta field.
This is the code that will be utilizing the "customamznsearch" variable.
<script type="text/javascript">
amzn_assoc_placement = "adunit0";
amzn_assoc_tracking_id = "livcouintheci-20";
amzn_assoc_ad_mode = "search";
amzn_assoc_ad_type = "smart";
amzn_assoc_marketplace = "amazon";
amzn_assoc_region = "US";
amzn_assoc_textlinks = "";
amzn_assoc_linkid = "0c1ce8995df23ae16ec99d3bb32502ec";
amzn_assoc_default_category = "SportingGoods";
amzn_assoc_default_search_phrase = customamznsearch;
</script>
<script src="//z-na.amazon-adsystem.com/widgets/onejs?MarketPlace=US"></script>
This code will be displayed in an Enhanced Text Widget in the footer of my page. The Enhanced Text widget should be fully capable of supporting Text, HTML, CSS, JavaScript, Flash, Shortcodes, and PHP.
After much research, the following snippet of code was what ended up working (please note that I decided to change the variable to 'amazonadserach'):
var amazonadsearch = "<?php global $post;
$amazonadsearch = get_post_meta($post->ID, 'amazonadsearch', true);
echo $amazonadsearch; ?>";
You can just output javascript code from php like this:
<script>
var customamznsearch = "<?php echo addcslashes($customamznsearch, '"'); ?>";
</script>
Or if you mean to get it from the <meta> tags, then:
function getMeta(metaName) {
var metas = document.getElementsByTagName('meta');
for (i=0; i<metas.length; i++) {
if (metas[i].getAttribute("name") == metaName) {
return metas[i].getAttribute("content");
}
}
return "";
}
var twitterTitle = getMeta("twitter:title");
In the top of my Jquery I've got many variables (associated with values) called : files_1, files_2, etc.
They are created in a script, in the bottom of my page :
<script>
$(function () {
<?php foreach ($folders as $f) { ?>
var files_<?=$f['request_id']?> = 0;
<?php } ?>
…
});
</script>
In my html I've got a link like :
Delete
data-request-id parameter gives me a number, the ones you've got in my variables names on top. In my example, it's data-request-id="2" : files_2.
Next, I've got a Jquery function that catch data values from links :
$('.request-files').on('click', 'a.delete', function (e) {
e.preventDefault();
var $link = $(this);
var $id = $link.data('request-id');
console.log(files_$id); // <-- It doesn't work
});
What I need to do is to retrieve the value of the variables files_x. In my example, I tried to get them using files_$id but it doesn't work.
Any idea ?
If you have your variables defined in the global scrope, they are attached to the window object. So you should be able to access your variables by using bracket notation on the window object:
$('.request-files').on('click', 'a.delete', function (e) {
e.preventDefault();
var $link = $(this);
var $id = $link.data('request-id');
console.log(window['files_' + $id]); // <-- It DOES work
});
UPD: your variables are in the closure of document.ready function ($(function() {...});), so you won't be able to access them from other scopes. I assume that your click handler is within that closure as well. I can suggest creating a separate object with properties named file_<ID> - it will work much alike as with window:
<script>
$(function () {
var filesMap = {};
<?php foreach ($folders as $f) { ?>
filesMap['files_' + <?=$f['request_id']?>] = 0;
<?php } ?>
…
$('.request-files').on('click', 'a.delete', function (e) {
e.preventDefault();
var $link = $(this);
var $id = $link.data('request-id');
console.log(filesMap['files_' + $id]);
});
});
</script>
I am not familiar with PHP, so the string concatenation in request_id part might be different, but the logic remains.
The following code is supposed to make an array from pictures found in a directory that end in .png using php, then allow buttons to change the pointer on the array and allow the page to display the current picture that the pointer is on. This doesnt seem to be working at all. Am I doing this correctly?
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
img {float:left; }
</style>
</head>
<body>
<?PHP
$pages = array ();
$dirname = "assets/pictures/";
$images = glob($dirname."*.png");
foreach($images as $image) {
$pages[] = $image;
}
?>
<?PHP
echo '<img src="'.current($pages).'" class="photo"/>';
function shownext() {
$mode = next($pages);
}
function showprev() {
$mode = prev($pages);
}
function showfirst() {
$mode = reset($pages);
}
function showlast() {
$mode = end($pages);
}
?>
first
previous
next
last
</body>
</html>
onclick will allow you to call a javascript function, while your showprev...showlast functions are all php functions. They are not available in javascript's scope.
Also, in your php code:
You are closing the loop right after $pages[] = $image, I think you intend to display (print/echo) all images.
You don't need a loop to copy $pages to $images. You can easily copy it: $pages = $images.
You should be aware that current only makes sense inside a loop and you are calling it after loop is closed.
I think though, that you are confusing server-side (i.e. php) and client-side (i.e. javascript) execution environments.
onclick , uses to trigger javascript functions.
You cant directly put your php functions on onclick="" events. Alternatively, if you want to use jQuery, you could use $.ajax to request the values on PHP. From there, after you got the image paths, manipulate the next, prev, first, last on the client side. Consider this example:
<?php
if(isset($_POST['getimages'])) {
$dirname = "assets/pictures/";
$images = glob($dirname."*.png");
// collect the images
foreach($images as $image) {
$pages[] = $image;
}
echo json_encode($pages);
exit;
}
?>
<img src="" alt="" id="images" width="200" height="200" />
<br/>
First
Previous
Next
Last
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var current_pointer = 0;
var images = [];
$.ajax({
url: 'index.php', // call the php file that will process it, i just used this in the same page
type: 'POST',
dataType: 'JSON',
data: {getimages: true},
success: function(response) {
// after a successful response from PHP
// use that data and create your own array in javascript
images = response;
$('#images').attr('src', images[current_pointer]);
}
});
// simple pointer to navigate the array you got from PHP
$('a.navigate').on('click', function(){
var current_val = $(this).attr('id');
switch(current_val) {
case 'first':
current_pointer = 0;
break;
case 'last':
current_pointer = images.length-1;
break;
case 'next':
current_pointer = (current_pointer >= images.length-1) ? images.length-1 : current_pointer+1;
break;
case 'previous':
current_pointer = (current_pointer < 0) ? 0 : current_pointer-1;
break;
}
$('#images').attr('src', images[current_pointer]);
});
});
</script>
The problem is echo '<img src="'.current($pages).'" class="photo"/>';
This will get echoed once, no matter howoften you change $pages afterwards. You also can't call PHP functions with JavaScript's onclick.
PHP will generate the page on server side! On a fully laoded page, most interaction with the user is done via JavaScript.
To achieve your desired result, you have to export the array to JavaScript and change the image src via JavaScript, a little research will help you.
I have used this function to submit to any url or 'self',
with or without a querystring, many times without any problems.
function submitu(url, q) {
var frm = document.<?php echo $formname ?>;
if (url == '') {url = '<?php echo $thispage?>'; }
frm.action = url+q; frm.submit(); }
If I try to move the PHP vars outside the function, as below, it stops working (frm undefined error)
var thispage = '<?php echo $thispage?>';
var frm = document.<?php echo $formname?>;
function submitu(url, q) {
if (url == '') {url = thispage;}
frm.action = url+q; frm.submit();}
I also tried var frm = document.forms[''];
I don't have any other conflicting javascript,
(1). Can anyone tell me why this is not working?
(2). And why the first method also fails if the function is placed
inside and at the top of the jquery $(function() {.....} ready function?
Many thanks
It fails because when outside the function, var frm = document.formname;
will be run immediately when the page loads, i.e. before the form element has actually been constructed, so you get 'undefined'. When inside the function, it is only run when the function is run, by which time the DOM is complete and it can find it.