I am setting up a shop for a photographer and have his different product options setup as variations. I want to allow the user to successfully add the product to cart without having to select all available variations.
here is an example of attribute/terms I have setup as variations:
so the customer should be allowed to select one option (variation) and add to cart. Currently it fails and says I need to select a variation from each attribute
So my question is simple: How do I make it where all variation selections are not required?
My Approach: there are a few things I think may work. First I think there is probably an action or hook I can plug in to to make this not required. OR I could possibly use jquery to modify the add to cart url so when a user clicks the add to cart button that the product id and variation id get passed to the url which I imagine would add that variation only to cart.
Any thoughts?
UPDATE:
I have attempted to manage this through some jQuery. I have it where it will only allow one input to be selected and a class is added or removed depending on selection. When user hits the add to cart button it will get all .not-active input name attributes into an array. I know the following url will work: http://my-url.com/?add-to-cart=976&variation_id=1186&attribute_pa_downloads=print-300dpi&attribute_pa_high-definition-aluminum=0&attribute_pa_photo-tiles=0&attribute_pa_canvas-gallery-wraps=0&attribute_pa_custom-prints=0 so I needed a way to make this dynamic. Currently Im stuck on how to build my url to include all the POST parameters so it passes validation and will add to cart. With that said, given the code below how can I build out my url so it redirects with all parameters and adds to cart (building out the url is the only thing I dont think I have working.)
var selectedName;
var selectedValue;
//Shop only allow one radio to be checked
$('input.selectOne').on('change', function(){
$('input.selectOne').not(this).prop('checked', false).removeClass('active').addClass('not-active');
$(this).addClass('active').removeClass('not-active');
selectedName = $(this).attr('name');
selectedValue = $(this).val();
});
$('.single_add_to_cart_button').click(function(e){
e.preventDefault();
console.log(selectedName);
console.log(selectedValue);
//Works :http://my-url.com/?add-to-cart=976&variation_id=1186&attribute_pa_downloads=print-300dpi&attribute_pa_high-definition-aluminum=0&attribute_pa_photo-tiles=0&attribute_pa_canvas-gallery-wraps=0&attribute_pa_custom-prints=0
var productID = $('input[name="product_id"]').val();
var variationID = $('input[name="variation_id"]').val();
var location = window.location.href; //Get URL to redirect to cart
var emptyOptions = [];
$('.not-active').map(function() {
return this.name;
}).each(function(i, str) {
if (!~$.inArray(str, emptyOptions) && str != selectedName) emptyOptions.push(str: '0&');
});
console.log(emptyOptions);
alert(location + 'add-to-cart=' + productID + '&variation_id=' + variationID + '&' + $.each(emptyOptions));
});
JSFiddle
For anyone else looking I ended up solving this issue with jQuery and the Woocommerce Radio Buttons Plugin.
In my local JS file I added this and it will handle allow for one selection and then create the add to cart url.
var selectedName;
var selectedValue;
//Shop only allow one radio to be checked
$('input.selectOne').on('change', function(){
$('input.selectOne').not(this).prop('checked', false).removeClass('active').addClass('not-active');
$(this).addClass('active').removeClass('not-active');
selectedName = $(this).attr('name');
selectedValue = $(this).val();
});
$('.single_add_to_cart_button').click(function(e){
e.preventDefault();
//console.log(selectedName);
//console.log(selectedValue);
//Works :http://my-url.com/?add-to-cart=976&variation_id=1186&attribute_pa_downloads=print-300dpi&attribute_pa_high-definition-aluminum=0&attribute_pa_photo-tiles=0&attribute_pa_canvas-gallery-wraps=0&attribute_pa_custom-prints=0
var productID = $('input[name="product_id"]').val();
var variationID = $('input[name="variation_id"]').val();
var location = window.location.href; //Get URL to redirect to cart
var emptyOptions = {};
$('.not-active').map(function() {
return this.name;
}).each(function(i, str) {
if (!~$.inArray(str, emptyOptions) && str != selectedName) emptyOptions[str] = 0;
});
//console.log(emptyOptions);
window.location = location + '?add-to-cart=' + productID + '&variation_id=' + variationID + '&' + selectedName + '=' + selectedValue + '&' + $.param(emptyOptions);
});
Related
On my clients WooCommerce website we run a script that forces shipping-cost calculation on the cart-page:
add_action('wp_head','prevent_proceed_to_checkout');
function prevent_proceed_to_checkout() {
echo ' <script>
jQuery(function(){
jQuery(".woocommerce-cart .wc-proceed-to-checkout a.checkout-button").on("click",function(e){
var _this = this;
alert("Bitte berechne die Versandkosten!");
e.preventDefault();
jQuery(".shipping-calculator-form .button").on("click",function(){
jQuery(_this).off();
});
});
});
</script>';
}
I need to change this so that it is not executed if there are no physical products in the cart. I tried using javascript to check if .woocommerce-shipping-totals - class is in the dom, but I was not successful with the solution I came up with.
Any ideas?
I solved this now by adding an if-statement to the onclick-function that basically checks, if the ".woocommerce-shipping-totals"-class is beeing displayed on the page as soon as the checkout-button is clicked. Here is the code i added: (right before the alert)
var shipping = document.getElementsByClassName("woocommerce-shipping-totals").length;
if (shipping > 0) {
One new column added to DB by me to add descriptions to attributes in Opencart and i can easily add/edit descriptions from admin panel but i have a problem in product_form page. I want to add automatically attribute description to every product when i choose attribute name.
In Opencart admin can choose attributes for products from autocomplete box but every time admin should add attribute descriptions manually. For example attribute 'Gold'. Every time when admin choose attribute 'Gold' he have to add description for gold manually. I want to retrieve attribute description from DB column 'protext' to automatically fill related textarea when admin. So when selected 'Gold' from input box related text should be appear in related textarea for description.
This is code that edited by me in product form but doesn't work.
your help will be appreciated.
function attributeautocomplete(attribute_row) {
$('input[name=\'product_attribute[' + attribute_row + '][name]\']').autocomplete({
'source': function(request, response) {
$.ajax({
url: 'index.php?route=catalog/attribute/autocomplete&token=<?php echo $token; ?>&filter_name=' + encodeURIComponent(request),
dataType: 'json',
success: function(json) {
response($.map(json, function(item) {
return {
category: item.attribute_group,
label: item.name,
label2: item.protext,
value: item.attribute_id
}
}));
}
});
},
'select': function(item) {
$('input[name=\'product_attribute[' + attribute_row + '][name]\']').val(item['label']);
$('input[name=\'product_attribute[' + attribute_row + '][attribute_id]\']').val(item['value']);
$('input[name=\'related\']').val('');
}
$('textarea[name=\'product_attribute[' + attribute_row + '][product_attribute_description][text]\']').autocomplete({
'append': function(item) {
$('textarea[name=\'product_attribute[' + attribute_row + '][product_attribute_description][text]\']').val(item['protext']);
}
});
}
For this you have to change code in Controller file from where ajax is returning result. Path Admin > Controller > Catalog > Attribute -> function autocomplete(). Add "protext" code after name row or after any other key you want (I wrote 1 so that you can find code in file and can add after this)
'name' => strip_tags(html_entity_decode($result['name'], ENT_QUOTES, 'UTF-8')),
line
'protext' => html_entity_decode($result['protext'], ENT_QUOTES, 'UTF-8'),
This is how, you will get this in tpl file.
Database is already fetching with * so you don't need to change any code there.
You already added code for tpl so it will work fine.
Note - It's better to make these changes using vqmod or ocmod. My OC version 2.0.2.0
So i have a 'total' field at the bottom of this column.
Above this field are checkboxes, when ticked, the 'total' should update by adding the price of that checkbox, and when unticked, the price should be removed.
So something similar to http://www.tepilo.com/#packages-anc
the below code updates the price when checkbox is clicked
it does nothing when unclicked
when clicked again, it adds to the new current price
$('.col-2 input[type="checkbox"]').on('click', function() {
var attribute_name = $(this).val();
var attribute_price = settings.wsapo_custom[0][attribute_name].price;
var current_price_total = $(".col-2 #update-price").text();
var new_price = parseInt(current_price_total) + parseInt(attribute_price);
console.log(new_price);
$(".col-2 #update-price").text(new_price);
});
thanks in advance
Using the onchange or change function in jquery will suffice here. Check if the checkbox is checked and then just change the data accordingly.
Demo on JSFIDDLE: http://jsfiddle.net/lrojas94/t9d04oeb/
Code:
$('input[type="checkbox"]').change(function(){
var actual = parseInt($('p').text());
if($(this).is(':checked'))
actual+= 100;
else
actual-=100;
$('p').text(actual);
});
And feel free to read the docs about this function: http://api.jquery.com/change/
Here is what I'm doing.
I have a set of divs. Each set of divs can contain a section header and a list of items. Each item has a price associated with it. So item 1 under section Demolition has a price of 150.00. Item 2 under section Demolition has a price of 200.00. Next to each item is an input field that the user can type in a numeric value. That value is then multiplied by the item price. So next to item 1(150.00) is a field where I enter 2. In the next div I then display the total. So 150.00 x 2 = 300.00.
I can do this for each item under the section. I then sum the entire items into one global price next to the sections.
Here is a sample of what I'm doing:
$(document).ready(function() {
$(".demolition_num").each(function() {
$(this).keyup(function(){
calculateDemSum();
});
});
});
function calculateDemSum() {
var sum = 0;
$(".demolition_num").each(function(){
if(!isNaN(this.value) && this.value.lenth != 0){
var unitCost = $(".unit_cost1").text();
var _parent = $(this).parent();
var total = _parent.prev().html();
sum += parseFloat(this.value * total);
var subtotal = this.value * total;
$(_parent).next().html(this.value * total);
}
else if (this.value.length !=0){
}
});
$(".cost1").text(sum.toFixed(2));
$("#cost1").val(sum.toFixed(2));
}
You can view all the code here: http://jsfiddle.net/pmetzger/Xeu2T/3/
As you can see in the jquery that right now I have to call each section independently
of the others since I do not want to calculate all of the fields, just the one I'm modifying.
So the question is, can I avoid having to add each sections input type id as the key up to trigger the calculations and make sure the totals get placed correctly?
Note: This code could be duplicated, but the data associated is going to be different. So on the next clients list it might not be Demolition, but Demo and so forth.
Any help will be greatly appreciated.
First of all a couple of pointers:
You don't need to bind events within an each() loop, simply
binding it to a standard selector will bind to all elements that fit
that selector.
You also have multiple <tr> elements with the same id.
You don't need a size attribute on hidden tags
New working fiddle here and the code:
$(document).ready(function()
{
// Bind the event
$("#calc").on("keyup", "input[type='text']", function()
{
calculateSum(this);
});
});
function calculateSum(element)
{
var sum = 0;
var $this = $(element);
var targetClass = $this.attr("class");
// Process each element with the same class
$("." + targetClass).each(function()
{
var thisVal = $(this).val();
// Count invalid entries as 0
if(isNaN(thisVal) || thisVal.length === 0)
{
thisVal = 0;
}
else
{
thisVal = parseFloat(thisVal);
}
// Get the unit cost and calculate sub-total
var unitCost = parseFloat($(this).parent().prev("td.unit_cost").text());
var subTotal = thisVal * unitCost;
sum += subTotal;
$(this).parent().next("td").text(subTotal);
});
var $item = $this.closest("tr").prevAll(".item").first();
$item.find("input.section_cost").val(sum.toFixed(2));
$item.find("td.section_cost").text(sum.toFixed(2));
}
Note that I have modified your HTML slightly - I changed the multiple <tr id="item"> to use classes, I moved where these rows were to better target your subsection totals, I added classes to the subsection totals (both hidden inputs and displayed values), I added a class to your unit value fields and I added an id to the table.
I am writing a small invoice application in Yii. I have the database for the model item. The item database is something like this
+++++++++++++++++
| InvoiceItems |
+++++++++++++++++
+ id +
+ name +
+ description +
+ unit_cost +
+ quantity +
+ tax +
+ total +
+++++++++++++++++
Now, in item model I have made a dropdown list where I am fetching all the item name with its unit_cost, quantity, tax etc in Ajax. In order to do the total, I have the business logic as:
unit_cost will be multiplied by quantity
Tax will then be added to the total.
The total should finally pop up in the total field in the _form.php file.
For the calculation, I have written this jQuery script:
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("#InvoiceItems_unit_cost, #InvoiceItems_quantity, #InvoiceItems_tax").on('keyup',function(event){
var subtotal = jQuery("#InvoiceItems_quantity").val() * jQuery("#InvoiceItems_unit_cost").val();
var total = subtotal + (subtotal * jQuery("#InvoiceItems_tax").val() / 100);
jQuery("#InvoiceItems_total").val(total);
});
});
</script>
This is working fine when I am manually inserting the values but it's not working when the values are coming from the database. I am totally stuck.
UPDATE
When I am trying to see the value after fetching from the database through ajax in console tab of firefox just like console.log("#InvoiceItems_quantity").val(), it is showing an empty string.
Ajax code to fetch data from the database in form of json
<?php echo $form->dropDownList($customers,'customer_name',CMap::mergeArray(CHtml::listData(Customers::model()->findAll(), 'customer_name', 'customer_name'
),
array(
'empty'=>array('Select'=>'- - Choose One - -'),
'id'=>'Customers_name',
'ajax'=> array(
'type'=>'GET',
'id'=>'abc',
'url'=>$this->createUrl('Invoices/customerdetails'),// action that will generate the data
'data'=>'js:"customer_name="+$(this).val()',// this is the data that we are sending to the action in the controller
'dataType'=>'json',// type of data we expect back from the server
'success'=>'js:updateFieldsCustomers',// a javascript function that will execute when the request completes
'beforeSend'=>'js:function(){
if($("#Customers_name").val() == "create_customer_link") {
addCustomers();
$("#dialogCustomers").dialog("open");
return false;
}
}',
),
'options'=>array(
'create_customer_link' => array('class'=>'create-link'),
)
)
);?>
<?php
Yii::app()->clientScript->registerScript('update','
function updateFieldsCustomers(data, textStatus, jqXHR){
// select each input field by id, and update its value
$("#InvoiceItems_unit_cost").val(data.unit_cost);
$("#InvoiceItems_quantity").val(data.quantity);
$("#InvoiceItems_discount").val(data.discount);
// similarly update the fields for the other inputs
}
');
?>
Recent Update
When I tried for console.log("#InvoiceItems_quantity").val() I saw that it is showing the actual value of that field after change. Means when one value is selected it is showing the value of previous entered value in console panel. I think all this is working as I have used on change function but when I am using .select its not working at all.Not any value is showing in console panel.
I got the solution for this question. It should be like this
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("#Product_name").ajaxComplete(function(event,request,settings){
var subtotal = jQuery("#InvoiceItems_quantity").val() * jQuery("#InvoiceItems_unit_cost").val();
var total = subtotal + (subtotal * jQuery("#InvoiceItems_tax").val() / 100);
jQuery("#InvoiceItems_total").val(total);
});
});
</script>
Try this
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("#Items_unit_cost, #Items_quantity, #Items_discount").on('keyup',calculate_total);
function calculate_total(){
var subtotal = jQuery("#Items_quantity").val() * jQuery("#Items_unit_cost").val();
var total = subtotal + (subtotal * jQuery("#Items_discount").val() / 100);
jQuery("#Items_total").val(total);
}
calculate_total();
});
</script>