jQuery code called from PHP won't execute - javascript

I'm developing a Wordpress site that (of course) is composed of multiple PHP templates. The particular template fragment I'm having problems with is called with this line:
<script id="templatehidden">
<?php get_template_part( 'fragments/calculator', 'row-sa' ); ?>
</script>
And the contents of calculator-row-sa.php are:
<div class="form-row pricingrow select-multiple">
<div class="form-controls">
<img class="remove-field-sa" style="float: left; margin-right: 30px;" src="http://45.32.89.214/wp-content/uploads/2016/04/minus.png">
<i style="margin-left: 50px;" class="cardinal"></i>
<select name="field-followers[]" class="select followerselect">
<?php foreach ( $options as $option ) : ?>
<option value="<?php echo $option[ 'value' ] ?>"><?php echo $option[ 'label' ] ?></option>
<?php endforeach; ?>
</select>
<b class="fa fa-caret-down" aria-hidden="true" style="color: #747474";></b>
<span class="acctprice"></span>
</div><!-- /.form-controls -->
And the jQuery code behind it is
$('.remove-field-sa').click(function () {
$(this).closest('.form-row').remove();
});
My problem is with the img element inside the php. When the page first loads, it does its job and removes the row it's on. However, after I add more rows, no javascript code seems to execute within .form-content anymore. Any ideas on what's wrong?

Assuming that you are adding the rows using javascript, you need event delegation: At the moment you bind your even handler, the elements don't exist and when you add them, the click event is not automatically binded to these new elements unless you use event delegation.
You can easily change that using for example:
$('.form-content').on('click', '.remove-field-sa', function () {
$(this).closest('.form-row').remove();
});
Note that here the .form-content element has to be present on page-load. If it is not, you could also use something like:
// Any parent element that is present at page-load and will contain the child elements will do.
$('body').on('click', '.remove-field-sa', function () {
$(this).closest('.form-row').remove();
});

Related

I want to hide <div> section "softdown" if custom field is not specified

I want to hide the Div section if the custom field is not selected or empty!
<div class="softdown">
<span class="postdownlink">
<i class="fa fa-download" aria-hidden="true"></i>
<?php echo get_post_meta($post->ID, 'postdownlink', true); ?>
</span>
</div>
Within PHP, you can check if a variable is empty using a function called empty.
So, you could do something like this:
<?php if(!empty($iamempty)){ ?>
<h1>I won't be shown</h1>
<? } ?>
So, for you to implement this into your code, you could do the following.
<?php if(!empty(get_post_meta($post->ID, 'postdownlink', true))){ ?>
<div class="softdown">
<span class="postdownlink">
<i class="fa fa-download" aria-hidden="true"></i>
<?php echo get_post_meta($post->ID, 'postdownlink', true); ?>
</span>
</div>
<? } ?>
The above code will only display the div (The HTML content between the PHP tags) if the get_post_meta returns a value that is not empty.
If it needs to be done in real time, you can do that this way:
This can be added to the top of your JS file:
var inputChange = function (){
($('input#photo').val().length === 0) {
// Hide the element On keyup check the value of the input if length is 0 meaning empty hide the div otherwise show.
$('div.sofdown').hide(); // Using hide()
//Or using fadeOut();
$('div.sofdown').fadeOut(1000);
}
}
//Initiate to hide the div if there is no text in input.
inputChange();
After that initial state will be hidden
This should be add at the end of the JS file
$('input#photo').keyup(function() {
//Call function
inputChange();
}

JavaScript Function Call With OnClick

I have a simple function that works when it is hard coded, but when I try to pass a second parameter into it, it doesn't work. I am calling the function with the onclick and using the id => thumbnail to get the value. Any suggestions?
Hard Coded Example (Works)
<script>
function clearFileInputField(tagId) {
document.getElementById(tagId).innerHTML = document.getElementById(tagId).innerHTML;
$('.thumbnail').val("");
}
</script>
<div id="thumbnail_div" class="row">
<?php echo $form->labelex($model,'thumbnail'); ?>
<?php echo $form->textfield($model,'thumbnail', array(placeholder => "No file chosen", readonly => true, 'class' => 'thumbnail')); ?><br>
<?php echo $form->filefield($model,'thumbnail'); ?>
<?php echo $form->error($model,'thumbnail'); ?>
<input type="checkbox" onclick = "clearFileInputField('thumbnail_div')" href="javascript:noAction();"> Remove Thumbnail
</div>
Parameters Passed (Not Working)
<script>
function clearFileInputField(tagId, div) {
document.getElementById(tagId).innerHTML = document.getElementById(tagId).innerHTML;
$('.div').val("");
}
</script>
<div id="thumbnail_div" class="row">
<?php echo $form->labelex($model,'thumbnail'); ?>
<?php echo $form->textfield($model,'thumbnail', array(placeholder => "No file chosen", readonly => true, 'id' => 'thumbnail')); ?><br>
<?php echo $form->filefield($model,'thumbnail'); ?>
<?php echo $form->error($model,'thumbnail'); ?>
<input type="checkbox" onclick = "clearFileInputField('thumbnail_div', 'thumbnail')" href="javascript:noAction();"> Remove Thumbnail
</div>
You are almost there. In your code, the paramenter div is converted to string. Instead of that, try the code given below,
<script>
function clearFileInputField(tagId, div) {
document.getElementById(tagId).innerHTML =
document.getElementById(tagId).innerHTML;
$('.'+div).val("");
}
</script>
$('.div').val("");
^^^^^^
That's a string, not a variable. You're trying to find elements that have class="div".
You need to concatenate the variable with a string containing the dot.:
$('.' + div).val("");
$('.div').val("");
That part is close but not going to work as you might have intended. You instead should have it one of two ways,
$('.'+div).val("");
or,
$(div).val("");
With option 1, you are using a string for the period and concatenating it with the value of the variable div
With option 2, you will need to change the passed parameter to include a period before it.
You could easily get rid of your inline handler and just create a simple event handler.
jQuery(function(){
// Bind a handler to any button with the class remove_thumbnail
$('.remove_thumbnail').change(function(){
if (this.checked) {
$(this)
// go up to parent row
.parents('.row')
// find the thumbnail
.find('.thumbnail')
.val("");
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="thumbnail_div" class="row">
<input type="text" class="thumbnail" value="foo">
<input type="checkbox" class="remove_thumbnail"> Remove Thumbnail
</div>
The advantages here are that you separate content and behavior and do not introduce functions into the global scope.
try this (with script placed underneath the markup):
<div id="thumbnail_div" class="row">
<?php echo $form->labelex($model,'thumbnail'); ?>
<?php echo $form->textfield($model,'thumbnail', array(placeholder => "No file chosen", readonly => true, 'id' => 'thumbnail')); ?><br>
<?php echo $form->filefield($model,'thumbnail'); ?>
<?php echo $form->error($model,'thumbnail'); ?>
<input type="checkbox" onclick = "clearFileInputField('thumbnail_div', 'thumbnail')" href="javascript:noAction();"> Remove Thumbnail
</div>
<script>
function clearFileInputField(tagId, div) {
document.getElementById(tagId).innerHTML = document.getElementById(tagId).innerHTML;
$('.'+div).val("");
}
</script>

Select an ID from a parent element in JQuery

I want to access the id of the parent element. This code I am using and it's not working
var tag_id= $('.tag').closest('.tag').attr('id');
alert(tag_id)
This is my html
<div class='tag' id='<?php echo "$id";?>'>
<span class='tagName' id='<?php echo "$tag_name";?>'>Something</span>
</div>
I am not using .click() or .hover()
Probably the html div is in a while loop so 10 records will come from the database and it shows the same id for all records
EDIT:
I have another var but I didn't include this is it:
var tag_name = $('.tag').children('.tagName').attr('id');
its the name of the tag even though it's coming same for all tags
I tried the code from the answer for the second one and it didn't work
Html:
<div class='tag' id="<?php echo $id;?>">
<span class='tagName' id="<?php echo $tag_name;?>">Something</span>
</div>
Jquery
$('.tag').find('.tagName').attr('id'); // get child id
$('.tag').attr('id'); // parent id
Try this :
var tag_id= $('.tag').attr('id');
alert(tag_id)

jQuery + PHP Dynamically Created Content

I am working on an ecommerce site and the products are being dynamically generated with foreach loop, within each product there are product options, when the product option is selected I my intended behaviour is for the price to update.
I have this working, however jQuery is updating every instance of the price on the page and the select option only works for the first item generated. How do I add/bind the jQuery to the object/every product and have the price change on individual basis?
<?php
foreach($items as $item):
<?php echo $the_name ?>
<select id="choose">
foreach($selection as $select):
<option value="$some_var" data-value="$the_price">$some_var</option>
endforeach;
</select>
<div id="price"><?php echo $the_price ?></div>
endforeach;
?>
<script type="text/javascript">
jQuery('#choose').change(function (event) {
jQuery('#price').html(jQuery('#choose option:selected').data('value'));
}).change();
</script>
Working Code
After playing about for a while, and taking into consideration the other comments below, this code works.
<script type="text/javascript">
jQuery('.choose').change(function (event) {
var $t = jQuery(this);
var price = $t.find('option:selected').data('value');
$t.parents('form').find('.price').html(price);
}).change();
</script>
ID's are unique. Because 'choose' is in a loop, you've got multiple choose ID's, which isn't helping things. Same with the 'price'. So, let's change it a bit:
<?php
foreach($items as $item):
<?php echo $the_name ?>
<select class="choose">
foreach($selection as $select):
<option value="$some_var" data-value="$the_price">$some_var</option>
endforeach;
</select>
<div class="price"><?php echo $the_price ?></div>
endforeach;
?>
<script type="text/javascript">
jQuery('.choose').change(function (event) {
jQuery(this).next().html(jQuery(this).data('value'));
}).change();
</script>
Explanation:
Since you can have more than one choose, you then need to do a bit of DOM navigation to get the price that is relative to the select. So, whenever a select box is changed it will look for the next element in the DOM tree that is a sibling , which if your code snippet is complete will be the price element, and then update the html to that value. One thought though - you may want to use text instead of html, unless you have HTML in your prices. Also, when you're inside an event (unless you've done something special to rebind the scope), in jQuery this will refer to the element that the event fired on. So, jQuery(this) will return a jQuery reference to the element that was changed.
<?php
foreach($items as $item):
<?php echo $the_name ?>
<select class="choose">
foreach($selection as $select):
<option value="$some_var" data-value="$the_price">$some_var</option>
endforeach;
</select>
<div class="price"><?php echo $the_price ?></div>
endforeach;
?>
<script type="text/javascript">
jQuery('.choose').change(function (event) {
jQuery$(this).parent().next(".price").html(jQuery('#choose option:selected').data('value'));
}).change();
</script>

Watching for when any element changes

I have a rather unique issue in jquery to solve. I have a div wrapper:
<div class="formWrapper"></div>
This contains a set of elements that should, when they change (doesn't matter which element changes) - should (for example) be stored in a data object, and that object logged to the console - for now.
So:
<div class="formWrapper">
<div class="floatRight">
<div>
<label>Select a Project Manager</label>
<select class="projectManager">
<?php foreach($projectManagers as $name){ ?>
<option><?php echo $name; ?></option>
<?php } ?>
</select>
</div>
<div>
<label>Select a Division</label>
<select class="division">
<?php foreach($divisions as $division){ ?>
<option><?php echo $division['division_name']; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="floatLeft">
<div>
<label>Select a Client</label>
<select class="client">
<?php foreach($clients as $client){ ?>
<option><?php echo $client['client_company_name']; ?></option>
<?php } ?>
</select>
</div>
<div>
<label>Choose a Date</label>
<input type="text" class="date" placeholder="Click to choose a date"/>
</div>
</div>
</div>
Pretty simple to see whats going on. But what if projectManager changes or divison or ... both, or all the elements, a simple change() might work for one element but I need to watch all the element and dynamically update a data object such that each time an element changes, the console spits out a different data object.
The end goal
Have a data object, for example data = {pm : pm_selected_value} for if the user JUST selects pm and then, if they change division - the data object should update to should: data = {pm : pm_selected_value, divsion: division_selected_value} and so on ...
I know how to get the value of each element, I don't know how to create a dynamic data object like this while watching each element.
The catch, and I think change() from reading the docs does this, is that even if I have a data object like this:
data = {pm : pm_selected_value, divsion: division_selected_value}
and I go an update the pm (so selecting a different pm), the data object should instantly update to reflect that change:
data = {pm : pm_selected_NEW_value, divsion: division_selected_value}
Now I can apply .change() to each element - but is there no way to apply it to a div to say - "excuse me mr JavaScript - please watch all form elements inside here for change, k thanks."
What you are looking to do it listen for any select value to get changed within the <div class="formWrapper"></div> so you should target the <div> and attach the change event to child <select>s
var choices = new Object();
$('.formwrapper').on('change', 'select', function(){
choices[$(this).attr('name')] = $(this).val();
console.log(choices);
});
One thing you should do is provide a unique name="" for each <select> so that you know what you are dealing with inside of the anonymous function()

Categories