admin管理员组文章数量:1122832
I use the following code which immediately displays the pre-defined product attributes for a Dokan Auction Product with drop-down menus (instead of having the user manually click "Add Attribute"). I have also added two custom attribute sections, "Reference number" and "Watch year", where the user types in the values themselves.
// Enqueue Choices.js and its CSS
function enqueue_choices_js() {
wp_enqueue_style('choices-css', '.js/public/assets/styles/choices.min.css', array(), '1.0.0');
wp_enqueue_script('choices-js', '.js/public/assets/scripts/choices.min.js', array('jquery'), '1.0.0', true);
}
add_action('wp_enqueue_scripts', 'enqueue_choices_js');
// Main Function to Handle Dropdown with Choices.js, Ownership Verification, Reference Number, and Watch Year
function dokan_predefined_attributes_with_choices_and_custom_fields_js() {
global $post;
$product_id = isset($post) ? $post->ID : 0;
// Fetch the existing values for Reference Number and Watch Year (if they exist)
$existing_reference_number = $product_id ? get_post_meta($product_id, '_reference_number', true) : '';
$existing_watch_year = $product_id ? get_post_meta($product_id, '_watch_year', true) : '';
?>
<style>
.dokan-attribute-obligatory {
font-weight: bold;
color: #d9534f;
}
.product-edit-new-container .dokan-attribute-variation-options .dokan-product-attribute-wrapper ul li.product-attribute-list .dokan-product-attribute-item {
padding: 10px;
}
.choices[data-type*=select-one] .choices__button {
margin-top: -20px;
margin-right: 30px;
}
.dokan-attribute-missing {
border: 1px solid #d9534f;
padding: 10px;
border-radius: 5px;
}
.ui-sortable-handle {
touch-action: auto;
}
.dokan-btn-disabled {
opacity: 0.5;
pointer-events: none;
}
.ownership-confirmation {
margin-bottom: 20px;
padding: 10px;
border: 2px solid #0a3d62;
background-color: #f9f9f9;
border-radius: 5px;
}
.ownership-confirmation h3 {
margin-bottom: 10px;
font-weight: bold;
color: #0a3d62;
}
.choices__item--choice.is-highlighted {
background-color: #0a3d62 !important;
color: white !important;
}
/* Add margin between attributes */
.dokan-dashboard .dokan-dashboard-content ul li {
margin-top: 15px;
margin-bottom: 15px;
}
/* Red asterisk for required fields */
.required-asterisk {
color: #d9534f !important;
font-weight: 700 !important;
}
</style>
<script type="text/javascript">
jQuery(document).ready(function($) {
// Track ownership verification status and product image status
let ownershipPhotoUploaded = !!$('#ownership_photo_upload').val();
let productImageUploaded = !!$('input.dokan-feat-image-id').val();
// Predefined attributes list
var predefined_attributes = [
{ slug: 'pa_brand', name: 'Brand' },
{ slug: 'pa_condition', name: 'Condition' },
{ slug: 'pa_box', name: 'Original box' },
{ slug: 'pa_papers', name: 'Original papers' },
{ slug: 'pa_case-size', name: 'Case size' },
{ slug: 'pa_material', name: 'Material' },
{ slug: 'pa_dial-color', name: 'Dial color' }
];
// Function to load saved attribute terms
function getSavedAttributeValue(slug) {
return $('[name="attribute_values_' + slug + '"]').val() || '';
}
function getAttributeTerms(attributeSlug, callback, selectedValue = '') {
$.ajax({
url: '<?php echo admin_url('admin-ajax.php'); ?>',
method: 'POST',
dataType: 'json',
data: {
action: 'get_wc_attribute_terms',
attribute_slug: attributeSlug
},
success: function(response) {
callback(response, selectedValue);
},
error: function() {
callback([], selectedValue);
}
});
}
function addPredefinedAttributesToList() {
var $attributeList = $("ul.dokan-attribute-option-list");
$attributeList.empty();
$.each(predefined_attributes, function(index, attribute) {
var savedValue = getSavedAttributeValue(attribute.slug);
var attributeHtml = `
<li class="product-attribute-list taxonomy ${attribute.slug}" data-taxonomy="${attribute.slug}">
<div class="dokan-product-attribute-heading">
<span><i class="fas fa-bars" aria-hidden="true"></i> <strong>${attribute.name}</strong><span class="required-asterisk"> *</span></span>
</div>
<div class="dokan-product-attribute-item dokan-clearfix">
<div class="content-half-part">
<label class="form-label" for="">Name</label>
<strong>${attribute.name}</strong>
<input type="hidden" name="attribute_names[]" value="${attribute.slug}">
<input type="hidden" name="attribute_position[]" class="attribute_position" value="0">
<input type="hidden" name="attribute_is_taxonomy[]" value="1">
<label class="checkbox-item form-label">
<input type="checkbox" checked="checked" name="attribute_visibility[]" value="1"> Visible on the product page
</label>
</div>
<div class="content-half-part dokan-attribute-values">
<label for="" class="form-label">Value(s)</label>
<select style="width:100%;" class="dokan_attribute_values choices__input" name="attribute_values[${index}][]">
<option value="">Loading...</option>
</select>
</div>
</div>
</li>
`;
$attributeList.append(attributeHtml);
getAttributeTerms(attribute.slug, function(values, selectedValue) {
var optionsHtml = '<option value="">Select value</option>';
$.each(values, function(i, value) {
var selected = (value === selectedValue) ? 'selected' : '';
optionsHtml += '<option value="' + value + '" ' + selected + '>' + value + '</option>';
});
var $select = $(`select[name="attribute_values[${index}][]"]`);
$select.html(optionsHtml);
new Choices($select[0], {
searchEnabled: true,
removeItemButton: true,
itemSelectText: '',
});
}, savedValue);
});
}
function addCustomFields() {
// Reference Number and Watch Year moved to the top and outlined if missing
var referenceNumberField = `
<li class="product-attribute-list taxonomy reference-number" data-taxonomy="reference-number">
<div class="dokan-product-attribute-heading">
<span><i class="fas fa-bars" aria-hidden="true"></i> <strong>Reference Number</strong><span class="required-asterisk"> *</span></span>
</div>
<div class="dokan-product-attribute-item dokan-clearfix">
<div class="content-half-part">
<label class="form-label" for="reference_number">Reference Number</label>
<input type="text" id="reference_number" name="reference_number" class="dokan-form-control" placeholder="Enter reference number" value="<?php echo esc_attr($existing_reference_number); ?>" required>
</div>
</div>
</li>
`;
var watchYearField = `
<li class="product-attribute-list taxonomy watch-year" data-taxonomy="watch-year">
<div class="dokan-product-attribute-heading">
<span><i class="fas fa-bars" aria-hidden="true"></i> <strong>Watch Year</strong><span class="required-asterisk"> *</span></span>
</div>
<div class="dokan-product-attribute-item dokan-clearfix">
<div class="content-half-part">
<label class="form-label" for="watch_year">Watch Year</label>
<input type="text" id="watch_year" name="watch_year" class="dokan-form-control" placeholder="Enter watch year" value="<?php echo esc_attr($existing_watch_year); ?>" required>
</div>
</div>
</li>
`;
// Prepend custom fields (Reference Number and Watch Year) to the top of the attribute list
$("ul.dokan-attribute-option-list").prepend(watchYearField);
$("ul.dokan-attribute-option-list").prepend(referenceNumberField);
// Conditionally add Ownership Verification based on product status
if ($(".dokan-product-status-label:contains('Pending Review'), .dokan-product-status-label:contains('Online'), .dokan-product-status-label:contains('Draft')").length === 0) {
var ownershipField = `
<div class="ownership-confirmation">
<h3>Ownership Verification <span class="required-asterisk">*</span></h3>
<p>To confirm ownership, please upload a photo of your watch displaying the time <strong id="generated-time"></strong>.</p>
<div class="dokan-form-group">
<label class="dokan-control-label" for="ownership_photo_upload">Upload Photo</label>
<input type="file" name="ownership_photo_upload" id="ownership_photo_upload" accept="image/*" required>
</div>
</div>
`;
$('.dokan-attribute-variation-options').prepend('<div class="dokan-custom-fields">' + ownershipField + '</div>');
function generateRandomTime() {
var hours = Math.floor(Math.random() * 24);
var minutes = Math.floor(Math.random() * 60);
return ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2);
}
var randomTime = generateRandomTime();
$('#generated-time').text(randomTime);
}
}
addPredefinedAttributesToList();
addCustomFields();
function checkRequiredFields() {
var attributesFilled = checkAttributes();
var imageUploaded = checkFeaturedImage();
var customFieldsValid = checkCustomFields();
var $submitButton = $('input[name="update_auction_product"]');
if (attributesFilled && imageUploaded && customFieldsValid) {
$submitButton.prop('disabled', false).removeClass('dokan-btn-disabled');
} else {
$submitButton.prop('disabled', true).addClass('dokan-btn-disabled');
}
}
function checkAttributes() {
var missingValue = false;
$('ul.dokan-attribute-option-list select.dokan_attribute_values').each(function() {
if ($(this).val() === "" || $(this).val().length === 0) {
$(this).closest('.product-attribute-list').addClass('dokan-attribute-missing');
missingValue = true;
} else {
$(this).closest('.product-attribute-list').removeClass('dokan-attribute-missing');
}
});
// Check if Reference Number or Watch Year is missing
if ($('#reference_number').val() === "") {
$('#reference_number').closest('.product-attribute-list').addClass('dokan-attribute-missing');
missingValue = true;
} else {
$('#reference_number').closest('.product-attribute-list').removeClass('dokan-attribute-missing');
}
if ($('#watch_year').val() === "") {
$('#watch_year').closest('.product-attribute-list').addClass('dokan-attribute-missing');
missingValue = true;
} else {
$('#watch_year').closest('.product-attribute-list').removeClass('dokan-attribute-missing');
}
return !missingValue;
}
function checkFeaturedImage() {
return !!$('input.dokan-feat-image-id').val() && $('input.dokan-feat-image-id').val() !== "0";
}
function checkCustomFields() {
var referenceNumber = $('#reference_number').val();
var watchYear = $('#watch_year').val();
// Only check ownership verification if it's visible
var ownershipValid = $(".ownership-confirmation").length === 0 || !!$('#ownership_photo_upload').val();
return referenceNumber && watchYear && ownershipValid;
}
$(document).on('change', 'input.dokan-feat-image-id', function() {
productImageUploaded = !!$('input.dokan-feat-image-id').val();
checkRequiredFields();
});
$(document).on('click', '.dokan-remove-feat-image', function() {
setTimeout(function() {
productImageUploaded = false;
$('input.dokan-feat-image-id').val("0");
checkRequiredFields();
}, 100);
});
$(document).on('change', 'select.dokan_attribute_values, #ownership_photo_upload', function() {
checkRequiredFields();
});
checkRequiredFields();
});
</script>
<?php
}
add_action('wp_footer', 'dokan_predefined_attributes_with_choices_and_custom_fields_js');
// AJAX handler to get WooCommerce terms for an attribute
function get_wc_attribute_terms() {
$attribute_slug = isset($_POST['attribute_slug']) ? sanitize_text_field($_POST['attribute_slug']) : '';
$taxonomy = $attribute_slug;
$terms = get_terms(array(
'taxonomy' => $taxonomy,
'hide_empty' => false,
));
$term_names = array();
if (!is_wp_error($terms)) {
foreach ($terms as $term) {
$term_names[] = $term->name;
}
}
wp_send_json($term_names);
}
add_action('wp_ajax_get_wc_attribute_terms', 'get_wc_attribute_terms');
add_action('wp_ajax_nopriv_get_wc_attribute_terms', 'get_wc_attribute_terms');
// Hook to save custom fields (Reference Number and Watch Year) as WooCommerce product attributes
function save_reference_and_year_attributes($product_id) {
if (isset($_POST['reference_number'])) {
$reference_number = sanitize_text_field($_POST['reference_number']);
wp_set_object_terms($product_id, $reference_number, 'pa_reference-number');
}
if (isset($_POST['watch_year'])) {
$watch_year = sanitize_text_field($_POST['watch_year']);
wp_set_object_terms($product_id, $watch_year, 'pa_watch-year');
}
}
add_action('dokan_process_product_meta', 'save_reference_and_year_attributes', 10, 2);
I have two problems:
When the user clicks "Save Product", all attribute values are successfully saved for the product except for the Reference number and Watch year which is typed in with text.
The attribute values do not load when I edit an uploaded product (with status "Pending Review", "Draft" or "Online"). Instead, the user would have to re-select all values if they wish to make an edit and re-save the product.
Could someone please help me?
Kind regards,
Martin
本文标签: Custom Auction Product Attribute Section Dokan amp Woocommerce
版权声明:本文标题:Custom Auction Product Attribute Section [Dokan & Woocommerce] 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736286811a1927748.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论