brotherton-erpnext/erpnext/templates/includes/product_page.js

216 lines
6.1 KiB
JavaScript
Raw Normal View History

// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ready(function() {
2015-10-05 10:57:52 +00:00
window.item_code = $('[itemscope] [itemprop="productID"]').text().trim();
var qty = 0;
frappe.call({
type: "POST",
Hub (#10934) * [WIP]Hub * [listing] Show items, users and item_groups * Show filters * [start] cart, api for rfq and opp * rfq working * [wip] keys * wip quotes * [hub] register/unregister * [hub] rename password to access_token, remove passed company field * [hub] publishing cases, api call wrapper * [hub] add and remove fields working * [hub] fix flags, update on client save working * [hub] new hub page, client item CUD at hub working * listing, standard rate, local site hack * item listing, item page, search, back to home * [hub] implement hub company * [hub] company filter * [hub] basic rfq-ing, item page cleanup * categories wip * [hub] use get_doc_before_save() * [hub] send opportunity message to hub, api to make locally * [hub] enqueueing in hub api request wrapper * cleanup * [hub] refactor shopping cart's product.py to reuse * sync dynamic item fields daily * Scheduler heartbeat check * [wip] hub categories * [hub] wip enqueued callbacks * [hub] outgoing messages, fixing callback loop * [hub] bug: callback save after primary save * [hub] pricing, stock, currency * [hub] replace send_hub_request with make_and_enqueue * add hub.less, refactor code * Remove template html files, add styling for hub item cards * fix paging * add breadcrumb * Add sidebar * [hub] add company page, change country * [hub] order_by filters * [hub] make hub category a tree * [hub] enqueue batched item enqueueing * [hub] requested products page * [minor] * update hub url * [fix] url * [fix] more reform * fix recursion * [hub] data migration plans as jsons * Hub register, create data connector, sync with run * [add] user registration by session user * Removed hub_message * Remove sync code from hub_settings * Remove hub methods from item.py * Update Hub Sync plan * Hub unregister * Update Hub connector on reregister * Dont delete Hub Connector on unregister * Enable hub on success response * Add new hub whitelisted methods * [hub] list working * Hub register from hub page * [hub] Add hub logo in desk icon, link to page * [hub] hide page head on empty state * [hub] make rfq * [hub] push opportunity doc, poll for opportunity docs * add fields to item mapping * update hub mappings * Make RFQ * [hub] item, home routing * Make rfq and send opportunity refactor * [hub][fix] remote lead data * images passed as base64 * set default company on register * Revert "images passed as base64" This reverts commit 0b033a5fb7072b2d39a1b87a47dc41e7af707bb4. * Add sync to hub page * Prompt for publish items to hub * add post process to hub document to lead * Rename Hub document to Hub message, create opportunity in post process
2017-10-05 05:47:30 +00:00
method: "erpnext.shopping_cart.product_info.get_product_info_for_website",
args: {
item_code: get_item_code()
},
callback: function(r) {
if(r.message) {
if(r.message.cart_settings.enabled) {
$(".item-cart, .item-price, .item-stock").toggleClass("hide", (!!!r.message.product_info.price || !!!r.message.product_info.in_stock));
}
if(r.message.cart_settings.show_price) {
$(".item-price").toggleClass("hide", false);
}
if(r.message.cart_settings.show_stock_availability) {
$(".item-stock").toggleClass("hide", false);
}
if(r.message.product_info.price) {
$(".item-price")
.html(r.message.product_info.price.formatted_price_sales_uom + "<div style='font-size: small'>\
(" + r.message.product_info.price.formatted_price + " / " + r.message.product_info.uom + ")</div>");
if(r.message.product_info.in_stock==0) {
$(".item-stock").html("<div style='color: red'> <i class='fa fa-close'></i> {{ _("Not in stock") }}</div>");
}
else if(r.message.product_info.in_stock==1) {
var qty_display = "{{ _("In stock") }}";
if (r.message.product_info.show_stock_qty) {
qty_display += " ("+r.message.product_info.stock_qty+")";
}
$(".item-stock").html("<div style='color: green'>\
<i class='fa fa-check'></i> "+qty_display+"</div>");
}
if(r.message.product_info.qty) {
qty = r.message.product_info.qty;
toggle_update_cart(r.message.product_info.qty);
} else {
toggle_update_cart(0);
}
}
}
}
})
$("#item-add-to-cart button").on("click", function() {
2017-05-30 07:24:42 +00:00
frappe.provide('erpnext.shopping_cart');
erpnext.shopping_cart.update_cart({
2015-10-05 10:57:52 +00:00
item_code: get_item_code(),
2018-01-19 17:31:25 +00:00
qty: $("#item-spinner .cart-qty").val(),
callback: function(r) {
if(!r.exc) {
toggle_update_cart(1);
qty = 1;
}
},
btn: this,
});
});
2018-01-19 17:31:25 +00:00
$("#item-spinner").on('click', '.number-spinner button', function () {
var btn = $(this),
input = btn.closest('.number-spinner').find('input'),
oldValue = input.val().trim(),
newVal = 0;
if (btn.attr('data-dir') == 'up') {
newVal = parseInt(oldValue) + 1;
} else if (btn.attr('data-dir') == 'dwn') {
if (parseInt(oldValue) > 1) {
newVal = parseInt(oldValue) - 1;
}
else {
newVal = parseInt(oldValue);
}
}
input.val(newVal);
});
$("[itemscope] .item-view-attribute .form-control").on("change", function() {
try {
var item_code = encodeURIComponent(get_item_code());
} catch(e) {
// unable to find variant
// then chose the closest available one
var attribute = $(this).attr("data-attribute");
var attribute_value = $(this).val();
var item_code = find_closest_match(attribute, attribute_value);
if (!item_code) {
2017-05-30 07:24:42 +00:00
frappe.msgprint(__("Cannot find a matching Item. Please select some other value for {0}.", [attribute]))
throw e;
}
}
2017-08-29 08:32:49 +00:00
if (window.location.search == ("?variant=" + item_code) || window.location.search.includes(item_code)) {
return;
}
2016-01-01 11:53:12 +00:00
window.location.href = window.location.pathname + "?variant=" + item_code;
});
// change the item image src when alternate images are hovered
$(document.body).on('mouseover', '.item-alternative-image', (e) => {
const $alternative_image = $(e.currentTarget);
const src = $alternative_image.find('img').prop('src');
$('.item-image img').prop('src', src);
});
});
var toggle_update_cart = function(qty) {
$("#item-add-to-cart").toggle(qty ? false : true);
$("#item-update-cart")
.toggle(qty ? true : false)
.find("input").val(qty);
2018-01-19 17:31:25 +00:00
$("#item-spinner").toggle(qty ? false : true);
}
2015-10-05 10:57:52 +00:00
function get_item_code() {
2017-05-30 07:24:42 +00:00
var variant_info = window.variant_info;
if(variant_info) {
var attributes = get_selected_attributes();
var no_of_attributes = Object.keys(attributes).length;
2015-10-05 10:57:52 +00:00
for(var i in variant_info) {
var variant = variant_info[i];
if (variant.attributes.length < no_of_attributes) {
// the case when variant has less attributes than template
continue;
}
2015-10-05 10:57:52 +00:00
var match = true;
for(var j in variant.attributes) {
if(attributes[variant.attributes[j].attribute]
2017-05-30 07:24:42 +00:00
!= variant.attributes[j].attribute_value
) {
match = false;
break;
2015-10-05 10:57:52 +00:00
}
}
if(match) {
return variant.name;
}
}
throw "Unable to match variant";
} else {
2017-05-30 07:24:42 +00:00
return window.item_code;
2015-10-05 10:57:52 +00:00
}
}
function find_closest_match(selected_attribute, selected_attribute_value) {
// find the closest match keeping the selected attribute in focus and get the item code
var attributes = get_selected_attributes();
var previous_match_score = 0;
var previous_no_of_attributes = 0;
var matched;
2017-05-30 07:24:42 +00:00
var variant_info = window.variant_info;
for(var i in variant_info) {
var variant = variant_info[i];
var match_score = 0;
var has_selected_attribute = false;
for(var j in variant.attributes) {
if(attributes[variant.attributes[j].attribute]===variant.attributes[j].attribute_value) {
match_score = match_score + 1;
if (variant.attributes[j].attribute==selected_attribute && variant.attributes[j].attribute_value==selected_attribute_value) {
has_selected_attribute = true;
}
}
}
if (has_selected_attribute
&& ((match_score > previous_match_score) || (match_score==previous_match_score && previous_no_of_attributes < variant.attributes.length))) {
previous_match_score = match_score;
matched = variant;
previous_no_of_attributes = variant.attributes.length;
}
}
if (matched) {
for (var j in matched.attributes) {
var attr = matched.attributes[j];
$('[itemscope]')
.find(repl('.item-view-attribute .form-control[data-attribute="%(attribute)s"]', attr))
.val(attr.attribute_value);
}
return matched.name;
}
}
function get_selected_attributes() {
var attributes = {};
$('[itemscope]').find(".item-view-attribute .form-control").each(function() {
attributes[$(this).attr('data-attribute')] = $(this).val();
});
return attributes;
}