From 71fc49252f9ec4f1421cad0eeecd1164805970c5 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Sat, 14 Jul 2018 14:43:57 +0200 Subject: [PATCH] Modularize product picker --- public/viewjs/components/productpicker.js | 155 ++++++++++++++++++++++ public/viewjs/consume.js | 38 ++---- public/viewjs/inventory.js | 129 +++--------------- public/viewjs/purchase.js | 128 ++---------------- public/viewjs/shoppinglistform.js | 41 ++---- views/components/productpicker.blade.php | 18 +++ views/consume.blade.php | 15 +-- views/inventory.blade.php | 15 +-- views/purchase.blade.php | 15 +-- views/shoppinglistform.blade.php | 13 +- 10 files changed, 239 insertions(+), 328 deletions(-) create mode 100644 public/viewjs/components/productpicker.js create mode 100644 views/components/productpicker.blade.php diff --git a/public/viewjs/components/productpicker.js b/public/viewjs/components/productpicker.js new file mode 100644 index 00000000..479b21ef --- /dev/null +++ b/public/viewjs/components/productpicker.js @@ -0,0 +1,155 @@ +Grocy.Components.ProductPicker = { }; + +Grocy.Components.ProductPicker.GetPicker = function () +{ + return $('#product_id'); +} + +Grocy.Components.ProductPicker.GetInputElement = function() +{ + return $('#product_id_text_input'); +} + +Grocy.Components.ProductPicker.GetValue = function() +{ + return $('#product_id').val(); +} + +Grocy.Components.ProductPicker.SetValue = function(value) +{ + Grocy.Components.ProductPicker.GetInputElement().val(value); + Grocy.Components.ProductPicker.GetInputElement().trigger('change'); +} + +Grocy.Components.ProductPicker.InProductAddWorkflow = function() +{ + return typeof GetUriParam('createdproduct') !== "undefined"; +} + +Grocy.Components.ProductPicker.InProductModifyWorkflow = function() +{ + return typeof GetUriParam('addbarcodetoselection') !== "undefined"; +} + +Grocy.Components.ProductPicker.ShowCustomError = function(text) +{ + var element = $("#custom-productpicker-error"); + element.text(text); + element.removeClass("d-none"); +} + +Grocy.Components.ProductPicker.HideCustomError = function() +{ + $("#custom-productpicker-error").addClass("d-none"); +} + +$('.combobox').combobox({ + appendId: '_text_input', + bsVersion: '4' +}); + +var prefillProduct = GetUriParam('createdproduct'); +if (typeof prefillProduct !== "undefined") +{ + var possibleOptionElement = $("#product_id option[data-additional-searchdata*='" + prefillProduct + "']").first(); + if (possibleOptionElement.length === 0) + { + possibleOptionElement = $("#product_id option:contains('" + prefillProduct + "')").first(); + } + + if (possibleOptionElement.length > 0) + { + $('#product_id').val(possibleOptionElement.val()); + $('#product_id').data('combobox').refresh(); + $('#product_id').trigger('change'); + + var nextInputElement = $(Grocy.Components.ProductPicker.GetPicker().parent().data('next-input-selector').toString()); + nextInputElement.focus(); + } +} + +var addBarcode = GetUriParam('addbarcodetoselection'); +if (addBarcode !== undefined) +{ + $('#addbarcodetoselection').text(addBarcode); + $('#flow-info-addbarcodetoselection').removeClass('d-none'); + $('#barcode-lookup-disabled-hint').removeClass('d-none'); +} + +$('#product_id_text_input').on('change', function(e) +{ + var input = $('#product_id_text_input').val().toString(); + var possibleOptionElement = $("#product_id option[data-additional-searchdata*='" + input + "']").first(); + + if (GetUriParam('addbarcodetoselection') === undefined && possibleOptionElement.length > 0) + { + $('#product_id').val(possibleOptionElement.val()); + $('#product_id').data('combobox').refresh(); + $('#product_id').trigger('change'); + } + else + { + var optionElement = $("#product_id option:contains('" + input + "')").first(); + if (input.length > 0 && optionElement.length === 0 && typeof GetUriParam('addbarcodetoselection') === "undefined") + { + var addProductWorkflowsAdditionalCssClasses = ""; + if (Grocy.Components.ProductPicker.GetPicker().parent().data('disallow-add-product-workflows').toString() === "true") + { + addProductWorkflowsAdditionalCssClasses = "d-none"; + } + + bootbox.dialog({ + message: L('"#1" could not be resolved to a product, how do you want to proceed?', input), + title: L('Create or assign product'), + onEscape: function() { }, + size: 'large', + backdrop: true, + buttons: { + cancel: { + label: 'Cancel', + className: 'btn-default responsive-button', + callback: function() { } + }, + addnewproduct: { + label: 'P ' + L('Add as new product'), + className: 'btn-success add-new-product-dialog-button responsive-button ' + addProductWorkflowsAdditionalCssClasses, + callback: function() + { + window.location.href = U('/product/new?prefillname=' + encodeURIComponent(input) + '&returnto=' + encodeURIComponent(window.location.pathname)); + } + }, + addbarcode: { + label: 'B ' + L('Add as barcode to existing product'), + className: 'btn-info add-new-barcode-dialog-button responsive-button', + callback: function() + { + window.location.href = U(window.location.pathname + '?addbarcodetoselection=' + encodeURIComponent(input)); + } + }, + addnewproductwithbarcode: { + label: 'A ' + L('Add as new product and prefill barcode'), + className: 'btn-warning add-new-product-with-barcode-dialog-button responsive-button ' + addProductWorkflowsAdditionalCssClasses, + callback: function() + { + window.location.href = U('/product/new?prefillbarcode=' + encodeURIComponent(input) + '&returnto=' + encodeURIComponent(window.location.pathname)); + } + } + } + }).on('keypress', function(e) + { + if (e.key === 'B' || e.key === 'b') + { + $('.add-new-barcode-dialog-button').not(".d-none").click(); + } + if (e.key === 'p' || e.key === 'P') + { + $('.add-new-product-dialog-button').not(".d-none").click(); + } + if (e.key === 'a' || e.key === 'A') + { + $('.add-new-product-with-barcode-dialog-button').not(".d-none").click(); + } + }); + } + } +}); diff --git a/public/viewjs/consume.js b/public/viewjs/consume.js index ac7f849d..0af74d1d 100644 --- a/public/viewjs/consume.js +++ b/public/viewjs/consume.js @@ -19,10 +19,8 @@ toastr.success(L('Removed #1 #2 of #3 from stock', jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.product.name)); $('#amount').val(1); - $('#product_id').val(''); - $('#product_id_text_input').focus(); - $('#product_id_text_input').val(''); - $('#product_id_text_input').trigger('change'); + Grocy.Components.ProductPicker.SetValue(''); + Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.FrontendHelpers.ValidateForm('consume-form'); }, function(xhr) @@ -38,7 +36,7 @@ ); }); -$('#product_id').on('change', function(e) +Grocy.Components.ProductPicker.GetPicker().on('change', function(e) { var productId = $(e.target).val(); @@ -54,14 +52,14 @@ $('#product_id').on('change', function(e) if ((productDetails.stock_amount || 0) === 0) { - $('#product_id').val(''); - $('#product_id_text_input').val(''); + Grocy.Components.ProductPicker.SetValue(''); Grocy.FrontendHelpers.ValidateForm('consume-form'); - $('#product-error').text(L('This product is not in stock')); - $('#product_id_text_input').focus(); + Grocy.Components.ProductPicker.ShowCustomError(L('This product is not in stock')); + Grocy.Components.ProductPicker.GetInputElement().focus(); } else { + Grocy.Components.ProductPicker.HideCustomError(); Grocy.FrontendHelpers.ValidateForm('consume-form'); $('#amount').focus(); } @@ -74,28 +72,8 @@ $('#product_id').on('change', function(e) } }); -$('.combobox').combobox({ - appendId: '_text_input' -}); - -$('#product_id_text_input').on('change', function(e) -{ - var input = $('#product_id_text_input').val().toString(); - var possibleOptionElement = $("#product_id option[data-additional-searchdata*='" + input + "']").first(); - - if (possibleOptionElement.length > 0) - { - $('#product_id').val(possibleOptionElement.val()); - $('#product_id').data('combobox').refresh(); - $('#product_id').trigger('change'); - } -}); - $('#amount').val(1); -$('#product_id').val(''); -$('#product_id_text_input').focus(); -$('#product_id_text_input').val(''); -$('#product_id_text_input').trigger('change'); +Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.FrontendHelpers.ValidateForm('consume-form'); $('#amount').on('focus', function(e) diff --git a/public/viewjs/inventory.js b/public/viewjs/inventory.js index 7c83f781..ee7652c4 100644 --- a/public/viewjs/inventory.js +++ b/public/viewjs/inventory.js @@ -43,10 +43,8 @@ $('#inventory-change-info').addClass('d-none'); $('#new_amount').val(''); Grocy.Components.DateTimePicker.SetValue(''); - $('#product_id').val(''); - $('#product_id_text_input').focus(); - $('#product_id_text_input').val(''); - $('#product_id_text_input').trigger('change'); + Grocy.Components.ProductPicker.SetValue(''); + Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.FrontendHelpers.ValidateForm('inventory-form'); } }, @@ -63,7 +61,7 @@ ); }); -$('#product_id').on('change', function(e) +Grocy.Components.ProductPicker.GetPicker().on('change', function(e) { var productId = $(e.target).val(); @@ -87,94 +85,23 @@ $('#product_id').on('change', function(e) } }); -$('.combobox').combobox({ - appendId: '_text_input' -}); - -$('#product_id_text_input').on('change', function(e) -{ - var input = $('#product_id_text_input').val().toString(); - var possibleOptionElement = $("#product_id option[data-additional-searchdata*='" + input + "']").first(); - - if (GetUriParam('addbarcodetoselection') === undefined && possibleOptionElement.length > 0) - { - $('#product_id').val(possibleOptionElement.val()); - $('#product_id').data('combobox').refresh(); - $('#product_id').trigger('change'); - } - else - { - var optionElement = $("#product_id option:contains('" + input + "')").first(); - if (input.length > 0 && optionElement.length === 0 && GetUriParam('addbarcodetoselection') === undefined ) - { - bootbox.dialog({ - message: L('#1 could not be resolved to a product, how do you want to proceed?', input), - title: L('Create or assign product'), - onEscape: function() { }, - size: 'large', - backdrop: true, - buttons: { - cancel: { - label: L('Cancel'), - className: 'btn-default', - callback: function() { } - }, - addnewproduct: { - label: 'P ' + L('Add as new product'), - className: 'btn-success add-new-product-dialog-button', - callback: function() - { - window.location.href = U('/product/new?prefillname=' + encodeURIComponent(input) + '&returnto=' + encodeURIComponent(window.location.pathname)); - } - }, - addbarcode: { - label: 'B ' + L('Add as barcode to existing product'), - className: 'btn-info add-new-barcode-dialog-button', - callback: function() - { - window.location.href = U('/inventory?addbarcodetoselection=' + encodeURIComponent(input)); - } - }, - addnewproductwithbarcode: { - label: 'A ' + L('Add as new product and prefill barcode'), - className: 'btn-warning add-new-product-with-barcode-dialog-button', - callback: function() - { - window.location.href = U('/product/new?prefillbarcode=' + encodeURIComponent(input) + '&returnto=' + encodeURIComponent(window.location.pathname)); - } - } - } - }).on('keypress', function(e) - { - if (e.key === 'B' || e.key === 'b') - { - $('.add-new-barcode-dialog-button').click(); - } - if (e.key === 'p' || e.key === 'P') - { - $('.add-new-product-dialog-button').click(); - } - if (e.key === 'a' || e.key === 'A') - { - $('.add-new-product-with-barcode-dialog-button').click(); - } - }); - } - } -}); - $('#new_amount').val(''); -$('#product_id').val(''); -$('#product_id_text_input').focus(); -$('#product_id_text_input').val(''); -$('#product_id_text_input').trigger('change'); Grocy.FrontendHelpers.ValidateForm('inventory-form'); +if (Grocy.Components.ProductPicker.InProductAddWorkflow() === false) +{ + Grocy.Components.ProductPicker.GetInputElement().focus(); +} +else +{ + Grocy.Components.ProductPicker.GetPicker().trigger('change'); +} + $('#new_amount').on('focus', function(e) { - if ($('#product_id_text_input').val().length === 0) + if (Grocy.Components.ProductPicker.GetValue().length === 0) { - $('#product_id_text_input').focus(); + Grocy.Components.ProductPicker.GetInputElement().focus(); } else { @@ -203,32 +130,6 @@ $('#inventory-form input').keydown(function(event) } }); -var prefillProduct = GetUriParam('createdproduct'); -if (prefillProduct !== undefined) -{ - var possibleOptionElement = $("#product_id option[data-additional-searchdata*='" + prefillProduct + "']").first(); - if (possibleOptionElement.length === 0) - { - possibleOptionElement = $("#product_id option:contains('" + prefillProduct + "')").first(); - } - - if (possibleOptionElement.length > 0) - { - $('#product_id').val(possibleOptionElement.val()); - $('#product_id').data('combobox').refresh(); - $('#product_id').trigger('change'); - $('#new_amount').focus(); - } -} - -var addBarcode = GetUriParam('addbarcodetoselection'); -if (addBarcode !== undefined) -{ - $('#addbarcodetoselection').text(addBarcode); - $('#flow-info-addbarcodetoselection').removeClass('d-none'); - $('#barcode-lookup-disabled-hint').removeClass('d-none'); -} - $('#new_amount').on('keypress', function(e) { $('#new_amount').trigger('change'); @@ -246,7 +147,7 @@ Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e) $('#new_amount').on('keyup', function(e) { - var productId = $('#product_id').val(); + var productId = Grocy.Components.ProductPicker.GetValue(); var newAmount = parseInt($('#new_amount').val()); if (productId) diff --git a/public/viewjs/purchase.js b/public/viewjs/purchase.js index 457583a2..e9fb9056 100644 --- a/public/viewjs/purchase.js +++ b/public/viewjs/purchase.js @@ -44,10 +44,8 @@ { $('#amount').val(0); Grocy.Components.DateTimePicker.SetValue(''); - $('#product_id').val(''); - $('#product_id_text_input').focus(); - $('#product_id_text_input').val(''); - $('#product_id_text_input').trigger('change'); + Grocy.Components.ProductPicker.SetValue(''); + Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.FrontendHelpers.ValidateForm('purchase-form'); } }, @@ -64,7 +62,7 @@ ); }); -$('#product_id').on('change', function(e) +Grocy.Components.ProductPicker.GetPicker().on('change', function(e) { var productId = $(e.target).val(); @@ -95,95 +93,23 @@ $('#product_id').on('change', function(e) } }); -$('.combobox').combobox({ - appendId: '_text_input', - bsVersion: '4' -}); - -$('#product_id_text_input').on('change', function(e) -{ - var input = $('#product_id_text_input').val().toString(); - var possibleOptionElement = $("#product_id option[data-additional-searchdata*='" + input + "']").first(); - - if (GetUriParam('addbarcodetoselection') === undefined && possibleOptionElement.length > 0) - { - $('#product_id').val(possibleOptionElement.val()); - $('#product_id').data('combobox').refresh(); - $('#product_id').trigger('change'); - } - else - { - var optionElement = $("#product_id option:contains('" + input + "')").first(); - if (input.length > 0 && optionElement.length === 0 && GetUriParam('addbarcodetoselection') === undefined ) - { - bootbox.dialog({ - message: L('"#1" could not be resolved to a product, how do you want to proceed?', input), - title: L('Create or assign product'), - onEscape: function() { }, - size: 'large', - backdrop: true, - buttons: { - cancel: { - label: 'Cancel', - className: 'btn-default', - callback: function() { } - }, - addnewproduct: { - label: 'P ' + L('Add as new product'), - className: 'btn-success add-new-product-dialog-button', - callback: function() - { - window.location.href = U('/product/new?prefillname=' + encodeURIComponent(input) + '&returnto=' + encodeURIComponent(window.location.pathname)); - } - }, - addbarcode: { - label: 'B ' + L('Add as barcode to existing product'), - className: 'btn-info add-new-barcode-dialog-button', - callback: function() - { - window.location.href = U('/purchase?addbarcodetoselection=' + encodeURIComponent(input)); - } - }, - addnewproductwithbarcode: { - label: 'A ' + L('Add as new product and prefill barcode'), - className: 'btn-warning add-new-product-with-barcode-dialog-button', - callback: function() - { - window.location.href = U('/product/new?prefillbarcode=' + encodeURIComponent(input) + '&returnto=' + encodeURIComponent(window.location.pathname)); - } - } - } - }).on('keypress', function(e) - { - if (e.key === 'B' || e.key === 'b') - { - $('.add-new-barcode-dialog-button').click(); - } - if (e.key === 'p' || e.key === 'P') - { - $('.add-new-product-dialog-button').click(); - } - if (e.key === 'a' || e.key === 'A') - { - $('.add-new-product-with-barcode-dialog-button').click(); - } - }); - } - } -}); - $('#amount').val(0); -$('#product_id').val(''); -$('#product_id_text_input').focus(); -$('#product_id_text_input').val(''); -$('#product_id_text_input').trigger('change'); Grocy.FrontendHelpers.ValidateForm('purchase-form'); +if (Grocy.Components.ProductPicker.InProductAddWorkflow() === false) +{ + Grocy.Components.ProductPicker.GetInputElement().focus(); +} +else +{ + Grocy.Components.ProductPicker.GetPicker().trigger('change'); +} + $('#amount').on('focus', function(e) { - if ($('#product_id_text_input').val().length === 0) + if (Grocy.Components.ProductPicker.GetValue().length === 0) { - $('#product_id_text_input').focus(); + Grocy.Components.ProductPicker.GetInputElement().focus(); } else { @@ -212,32 +138,6 @@ $('#purchase-form input').keydown(function(event) } }); -var prefillProduct = GetUriParam('createdproduct'); -if (prefillProduct !== undefined) -{ - var possibleOptionElement = $("#product_id option[data-additional-searchdata*='" + prefillProduct + "']").first(); - if (possibleOptionElement.length === 0) - { - possibleOptionElement = $("#product_id option:contains('" + prefillProduct + "')").first(); - } - - if (possibleOptionElement.length > 0) - { - $('#product_id').val(possibleOptionElement.val()); - $('#product_id').data('combobox').refresh(); - $('#product_id').trigger('change'); - Grocy.Components.DateTimePicker.GetInputElement().focus(); - } -} - -var addBarcode = GetUriParam('addbarcodetoselection'); -if (addBarcode !== undefined) -{ - $('#addbarcodetoselection').text(addBarcode); - $('#flow-info-addbarcodetoselection').removeClass('d-none'); - $('#barcode-lookup-disabled-hint').removeClass('d-none'); -} - Grocy.Components.DateTimePicker.GetInputElement().on('change', function(e) { Grocy.FrontendHelpers.ValidateForm('purchase-form'); diff --git a/public/viewjs/shoppinglistform.js b/public/viewjs/shoppinglistform.js index 519122eb..6b666034 100644 --- a/public/viewjs/shoppinglistform.js +++ b/public/viewjs/shoppinglistform.js @@ -30,7 +30,7 @@ } }); -$('#product_id').on('change', function(e) +Grocy.Components.ProductPicker.GetPicker().on('change', function(e) { var productId = $(e.target).val(); @@ -52,39 +52,22 @@ $('#product_id').on('change', function(e) } }); -$('.combobox').combobox({ - appendId: '_text_input' -}); - -$('#product_id_text_input').on('change', function(e) -{ - var input = $('#product_id_text_input').val().toString(); - var possibleOptionElement = $("#product_id option[data-additional-searchdata*='" + input + "']").first(); - - if (possibleOptionElement.length > 0 && possibleOptionElement.text().length > 0) - { - $('#product_id').val(possibleOptionElement.val()); - $('#product_id').data('combobox').refresh(); - $('#product_id').trigger('change'); - } -}); - -$('#product_id_text_input').focus(); -$('#product_id_text_input').trigger('change'); - -if (Grocy.EditMode === 'edit') -{ - $('#product_id').addClass('suppress-next-custom-validate-event'); - $('#product_id').trigger('change'); -} - Grocy.FrontendHelpers.ValidateForm('shoppinglist-form'); +if (Grocy.Components.ProductPicker.InProductAddWorkflow() === false) +{ + Grocy.Components.ProductPicker.GetInputElement().focus(); +} +else +{ + Grocy.Components.ProductPicker.GetPicker().trigger('change'); +} + $('#amount').on('focus', function(e) { - if ($('#product_id_text_input').val().length === 0) + if (Grocy.Components.ProductPicker.GetValue().length === 0) { - $('#product_id_text_input').focus(); + Grocy.Components.ProductPicker.GetInputElement().focus(); } else { diff --git a/views/components/productpicker.blade.php b/views/components/productpicker.blade.php new file mode 100644 index 00000000..1e008bb6 --- /dev/null +++ b/views/components/productpicker.blade.php @@ -0,0 +1,18 @@ +@push('componentScripts') + +@endpush + +@php if(empty($disallowAddProductWorkflows)) { $disallowAddProductWorkflows = false; } @endphp + +
+ + +
{{ $L('You have to select a product') }}
+
+
{{ $L('will be added to the list of barcodes for the selected product on submit') }}
+
diff --git a/views/consume.blade.php b/views/consume.blade.php index d4b5d96b..48c7acf8 100644 --- a/views/consume.blade.php +++ b/views/consume.blade.php @@ -11,16 +11,11 @@
-
- - -
{{ $L('You have to select a product') }}
-
+ @include('components.productpicker', array( + 'products' => $products, + 'nextInputSelector' => '#amount', + 'disallowAddProductWorkflows' => true + ))
diff --git a/views/inventory.blade.php b/views/inventory.blade.php index d1f2f24d..1f6a3702 100644 --- a/views/inventory.blade.php +++ b/views/inventory.blade.php @@ -11,17 +11,10 @@ -
- - -
{{ $L('You have to select a product') }}
-
{{ $L('will be added to the list of barcodes for the selected product on submit') }}
-
+ @include('components.productpicker', array( + 'products' => $products, + 'nextInputSelector' => '#new_amount' + ))
diff --git a/views/purchase.blade.php b/views/purchase.blade.php index e28dc401..ac547852 100644 --- a/views/purchase.blade.php +++ b/views/purchase.blade.php @@ -11,17 +11,10 @@ -
- - -
{{ $L('You have to select a product') }}
-
{{ $L('will be added to the list of barcodes for the selected product on submit') }}
-
+ @include('components.productpicker', array( + 'products' => $products, + 'nextInputSelector' => '#best_before_date .datetimepicker-input' + )) @include('components.datetimepicker', array( 'id' => 'best_before_date', diff --git a/views/shoppinglistform.blade.php b/views/shoppinglistform.blade.php index 714a15a2..1a6bb56b 100644 --- a/views/shoppinglistform.blade.php +++ b/views/shoppinglistform.blade.php @@ -21,15 +21,10 @@ -
- - -
+ @include('components.productpicker', array( + 'products' => $products, + 'nextInputSelector' => '#amount' + ))