CyberStore Ecommerce 2023 Documentation
WarehouseShipFrom_Display Widget

A warehouse selection widget. Introduced in v2.21. 

 Remarks

The WarehouseShipFrom_Display widget is used as part of the CatalogItemDetailControl in conjunction with the CatalogPricingControl and presents the shopper with information about the warehouse that the item will ship from when purchased.

When warehouse selection is enabled on the shopper's Customer Class, the widget also provides a means for presenting the shopper with the available warehouses from which the item may ship. Furthermore, if warehouse selection item surcharges are confgured for the Item or Category, then an additional fee can be applied to the order if the warehouse selected is not the default warehouse to use of the Item.

 Example

See an example of how to load and configure this widget in SitePages.config.

<Control src="LoadWidgetControl.ascx" 
    FileLocation="WarehouseShipFrom_Display.html" 
/>
 Widget Source

The following is the source code for this widget.

Developer's Note:

To create a custom version of the widget, copy all of the code below into a file of the same name and place it into your Site's widgets folder (e.g., ../YourSiteFolder/Widgets). The CyberStore page engine will then override the default source with your customized version.

<div class="warehouseBox">
</div>
<div id="topDiv">
</div>
<div id="popupContainerView">
</div>
<style media="screen" type="text/css">
    .outer > * {
        display: inline-block;
        vertical-align: middle;
        height: 30px;
    }

    .data {
        font-weight: bold;
        padding-right: 5px;
        padding-left: 5px;
    }

    .listLine {
        display: inline-block;
        padding: 5px 0px;
    }

    .dx-popup-wrapper > .dx-overlay-content {
        padding: 15px;
    }

    .outer {
        margin-bottom: 20px;
    }

    .popUpTitle {
        font-weight: bold;
        padding-right: 10px;
        padding-left: 10px;
        font-size: 1.3em;
    }

    div#simpleList {
        font-size: 1.2em;
    }

    #simpleList .dx-list-item-selected {
        font-weight: 700;
    }

    .dx-item.dx-list-item {
        border: 1px solid #e1e1e1;
        margin-bottom: 9px;
    }

        .dx-item.dx-list-item:nth-child(even) {
            background: #f6f6f6;
        }

    .dx-item.dx-list-item {
        border: 1px solid #e1e1e1;
        margin-bottom: 9px;
    }

        .dx-item.dx-list-item:nth-child(even) {
            background: #f6f6f6;
        }

    .warehouseList {
        display: grid;
        /* justify-content: start; */
        grid-template-columns: 1fr 3fr 1fr 1fr;
        justify-items: start;
    }

    .warehouseBox {
        margin-top: 15px;
        display: inline-block;
    }

        .warehouseBox .data-row.outer {
            margin-right: -15px;
        }

    .row-warehouse-SeviceFee.data {
        margin-left: auto;
    }

    .warehouseFee.listLine {
        margin-left: auto;
        text-align: right;
        /* flex: 0 1 0;*/
        padding: 5px 0px
    }

    div#whLink {
        display: block;
        font-weight: 700;
    }

    .btnholder {
        float: right;
    }

        .btnholder button {
            background-color: #ff6607;
            color: #fff;
            padding: 8px;
            border-radius: 7px;
            border-width: 0;
            margin-inline: 5px;
        }

    .warehouseBox .dx-popup-content {
        min-height: 200px;
    }

    /* PopupTitle */
    #thewarehousePopUpToolbar {
        background-color: #ffffff;
        border-bottom: 0px;
    }

    .warehouseTitleBtnClass {
        background-color: #ff6607;
    }

    .warehouseTitleText {
        color: black
    }
</style>
<script type="text/javascript">
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' Base Widget:  WarehouseShipFrom_Display.html
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' (c) 2022 by Dovetail Internet Technologies, LLC
    // '              www.dovetailinternet.com
    // '              info@dovetailinternet.com
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' All rights reserved. Not to be used without permission.
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' Development Date: Oct 2021
    // ' Release Version:  2.21.0
    // ' Devex:  v 2.21
    // ' Modified: 01/04/2022
    // ' Modified: 08/17/2022  U#15323
    // ' Modified: 11/02/2022  T#16213
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' The widget displays the designated warehouse for an item. It provides a
    // ' link to a popup that allows the user to change the source warehouse for an item if desired.
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

    //Global Variables
    'use strict';
    var WarehouseData = {
        "ListSelectedIndex": 0, //No Preference
        "TotalWarehouses": 0
    };

    $(function () {
        var $wrapperDiv
        var el_Id = 'topDiv';

        createWidget(PAGE_ITEM, el_Id);

        /**========================================================================
         **                           createWidget
         *?  create unique element for widget?
         *@param stockCode str
         *@param ElementId str (Element id)
         *@return html element
         *========================================================================**/
        function createWidget(stockCode, ElementId) {
            var divId = stockCode + '_' + Math.floor(Math.random() * 1000001);
            $wrapperDiv = $('<div>')
                .attr('id', divId)
                .appendTo(ElementId);
            getWarehouseData(stockCode);
        }

        /**========================================================================
         **                           getWarehouseData
         *? get Warehouse data?
         *@param ItemId int
         *@return DATA  stringified json
         *========================================================================**/
        function getWarehouseData(ItemId) {
            MakeAJAXCall(
                'Inventory.GetItemInventoryQuantities',
                {
                    Item_ID: ItemId,
                    UOM: 0,
                },
                processWarhouseData
            );
        }

        /**========================================================================
         **                           processWarhouseData
         *?  Consumes and Organizes the Data from Inventory.GetItemInventoryQuantities ?
         *@param DATA stringified json
         *@return WarehouseData obj
         //NOTE select warehouse order   1.preferredWarehouse 2.defaultWarehouse 3.No Preference
         //then displays the warehouse data on first load only.
         *========================================================================**/
        function processWarhouseData(DATA) {
            try {
                if (DATA != null) {
                    var data = JSON.parse(DATA);
                    if (data.Result.Success) {
                        console.dir(data);
                        WarehouseData.ItemData = data.Data;
                        WarehouseData.productId = PAGE_ITEM;
                        WarehouseData.TotalWarehouses = data.Data.Warehouses.length;
                        //add no preference obj to ItemData.Warehouses
                        if (WarehouseData.ItemData.Warehouses.length == WarehouseData.TotalWarehouses) {
                            WarehouseData.ItemData.Warehouses.unshift({ Warehouse: '', Description: ` No Preference`, InventoryQty: 0, SurchargeFee: '', SurchargeFeeAmount: 0 });
                        }
                        //NOTE 1.preferredWarehouse
                        if (WarehouseData.ItemData.PreferredWarehouse != null && WarehouseData.ItemData.PreferredWarehouse != '') {
                            WarehouseData.ItemData.Warehouses.forEach((element, i) => {
                                if (element.Warehouse == WarehouseData.ItemData.PreferredWarehouse) {
                                    WarehouseData.ListSelectedIndex = i;
                                    WarehouseData.ResetListSelectedIndex = i;
                                }
                            });
                            displayWarehouseInfo(WarehouseData);
                            return;
                        }
                        //NOTE 2.defaultWarehouse
                        if (WarehouseData.ItemData.DefaultWarehouse != null && WarehouseData.ItemData.DefaultWarehouse != '') {
                            WarehouseData.ItemData.Warehouses.forEach((element, i) => {
                                if (element.Warehouse == WarehouseData.ItemData.DefaultWarehouse) {
                                    WarehouseData.ListSelectedIndex = i;
                                    WarehouseData.ResetListSelectedIndex = i;
                                }
                            });
                            displayWarehouseInfo(WarehouseData);
                            return;
                        }
                        //NOTE 3. preferredWarehouse == '' && defaultWarehouse == ''
                        if ((WarehouseData.ItemData.DefaultWarehouse == null || WarehouseData.ItemData.DefaultWarehouse == '')
                            && (WarehouseData.ItemData.PreferredWarehouse == null || WarehouseData.ItemData.PreferredWarehouse == '')) {
                            WarehouseData.ListSelectedIndex = 0;
                            WarehouseData.ResetListSelectedIndex = 0;
                            displayWarehouseInfo(WarehouseData);
                            return;
                        }
                    }
                }
            } catch (error) {
                console.log(error)
            }
        }


        /**========================================================================
         **                           displayWarehouseInfo
         *?  Updates the display on the page with the selected WH data?
         *@param WarehouseData obj
         *@return HTML
         *========================================================================**/
        function displayWarehouseInfo(WarehouseData) {
            try {
                var $warehousecontainer = $('.warehouseBox');
                $warehousecontainer.empty();

                var selectedWarehouse = WarehouseData.ItemData.Warehouses[WarehouseData.ListSelectedIndex];
                document.getElementById("hfSelectedWarehouse").value = selectedWarehouse.Warehouse;

                var surChargeTxt = '';
                if (selectedWarehouse.SurchargeFee.length < 1) {
                    surChargeTxt = `${selectedWarehouse.SurchargeFee}`;
                }
                if (selectedWarehouse.SurchargeFee.length >= 1) {
                    surChargeTxt = `${selectedWarehouse.SurchargeFee} ${selectedWarehouse.SurchargeFeeDescription}`;
                }

                var warehouseRow = $('<div>').addClass('data-row outer');
                $('<div>')
                    .addClass('row-lable')
                    .text('Will Ship from warehouse:')
                    .appendTo(warehouseRow);
                $('<div>')
                    .addClass('row-warehous-Name data')
                    .text(selectedWarehouse.Warehouse + ' ' + selectedWarehouse.Description)
                    .appendTo(warehouseRow);
                $('<div>')
                    .addClass('row-warehouse-SeviceFee data')
                    .text(surChargeTxt)
                    .appendTo(warehouseRow);
                $('<div>')
                    .addClass('row-warehouse-SelectLink')
                    .attr('id', 'whLink')
                    .html('<a>Change Warehouse</a>')
                    .on('click', function () {
                        buildPopup(WarehouseData);
                    })
                    .appendTo(warehouseRow);
                warehouseRow.appendTo($warehousecontainer);
                $warehousecontainer.appendTo($wrapperDiv);
            } catch (error) {
                console.log(error);
            }
        }

        /**========================================================================
         **                           buildPopup
         *?  Builds the popup and the list that is displayed in the popup?
         *@param WarehouseData obj
         *@return dxpopup
         *========================================================================**/
        function buildPopup(WarehouseData) {
            var dataArr = WarehouseData.ItemData.Warehouses;

            /**================================================================================================
             *  Build select list for popup
             *================================================================================================**/
            var listWidget = $('<div id="simpleList">').dxList({
                height: 'auto',
                dataSource: dataArr,
                hoverStateEnabled: true,
                showSelectionControls: true,
                selectionMode: 'single',
                onSelectionChanged: selectionHasChanged,
                itemTemplate: function (dataArr, index) {
                    var result = $('<div>').addClass('warehouseList');
                    $('<div>')
                        .addClass('warehouseCode listLine')
                        .text(dataArr.Warehouse)
                        .appendTo(result);
                    $('<div>')
                        .addClass('warehouseDesc listLine')
                        .text(dataArr.Description)
                        .appendTo(result);
                    $('<div>')
                        .addClass('warehouseRank listLine')
                        .text(dataArr.Status)
                        .appendTo(result);
                    $('<div>')
                        .addClass('warehouseFee listLine')
                        .html(dataArr.SurchargeFee)
                        .appendTo(result);
                    return result;
                },
            });

            /**================================================================================================
             *  Popup
             *================================================================================================**/
            $('#popupContainerView').dxPopup({
                wrapperAttr: {
                    id: "warehousePopupWrapper",
                    class: "wareHousePopup"
                },
                showTitle: true,
                height: 'auto',
                width: '600px',
                closeOnOutsideClick: false,
                dragEnabled: true,
                onHiding: function (e) {
                    displayWarehouseInfo(WarehouseData);
                },
                toolbarItems: [
                    {
                        text: "Select a warehouse",
                        location: "before"
                    }, {
                        widget: "dxButton",
                        elementAttr: {
                            id: "popupResetBtn",
                            class: "popupResetBtn"
                        },
                        location: "after",
                        options: {
                            text: "Reset",
                            visible: false,
                            onClick: function () {
                                WarehouseData.ListSelectedIndex = WarehouseData.ResetListSelectedIndex
                                updatePopupList(WarehouseData.ItemData.Warehouses[WarehouseData.ListSelectedIndex]);
                            }
                        }
                    }],
                contentTemplate: function (contentElement) {
                    contentElement.append(listWidget);
                },
            });


            $('#popupContainerView').dxPopup('instance').show();


            /**================================================================================================
             *!                 WARNING Relitive selectors
             *!   Get and set ids and classes for items in the toolbar the selectors are Relitive udates to
             *!   the title bar could change functionality
             *================================================================================================**/
            $("#warehousePopupWrapper > div > div.dx-toolbar.dx-widget.dx-visibility-change-handler.dx-collection.dx-popup-title.dx-has-close-button").attr("id", "thewarehousePopUpToolbar").addClass('warehouseTitleClass');
            $("#thewarehousePopUpToolbar > div > div.dx-toolbar-after > div:nth-child(1)").attr("id", "ResetBtnDiv").addClass('warehouseTitleBtnBox');
            $("#ResetBtnDiv > div > div").attr("id", "PopUpResetBtn").addClass('warehouseTitleBtnClass');
            $("#thewarehousePopUpToolbar > div > div.dx-toolbar-after > div:nth-child(2)").attr("id", "CloseBtnDiv").addClass('warehouseTitleBtnBox');
            $("#CloseBtnDiv > div > div").attr("id", "PopUpCloseBtn").addClass('warehouseTitleBtnClass');

            $("#thewarehousePopUpToolbar > div > div.dx-toolbar-before > div").attr("id", "PopUpTitleDiv").addClass('warehouseTitleText');


            updatePopupList(WarehouseData.ItemData.Warehouses[WarehouseData.ListSelectedIndex]);
        }
        /**================================================================================================
         **                                      selectionHasChanged
         *?  handles the onSelectionChanged event for the list in the popup?
         *?  handles the onSelectionChanged event for the list in the popup?
         *@param e event
         *================================================================================================**/
        function selectionHasChanged(e) {
            if (!_.isEmpty(e.addedItems)) {
                WarehouseData.ListSelectedIndex = WarehouseData.ItemData.Warehouses.findIndex(x => x.Warehouse == e.addedItems[0].Warehouse);
                updatePopupList(WarehouseData.ItemData.Warehouses[WarehouseData.ListSelectedIndex]);
            }
            // moved to the close button onHiding() displayWarehouseInfo(WarehouseData);
        }

        /**========================================================================
         **                           updatePopupList
         *?  selects the item in the list bassed on the?
         *@param theWarehouse array
         *@param this may need to change type
         *========================================================================**/
        function updatePopupList(theWarehouse) {
            let selectedKeys = []
            selectedKeys.push(theWarehouse);
            const list = $('#simpleList').dxList('instance');
            list.option('selectedItemKeys', selectedKeys);
        }

    });
</script>