CyberStore Ecommerce 2023 Documentation
ItemReturnForm Widget

An Item return request form widget. Introduced in 2023.1.

 Remarks

The item Return Form widget provides a customizable interface that allows the customer to return items. The interface allows for the return of a single item or multiples different items. The interface allows the customer to upload images or documents with the return.

 

By default the widget can be seen by navigating to /ecommerce/ReturnItem.aspx as a logged in Shopper.

The interface is organized into two sections. The top section is used to enter or lookup the product codes of the items the user would like to return. The user can enter an order number into the online order lookup field. this will add all of the items in that order into the items to be returned section. The user can enter a single item by entering a Product number. The top section also allows the user to add a quick note and upload any files or documents. The second section shows the items that are being returned. The user can easily add or remove items. Increase or decrease the number of items returned. The user can select the reason for the return of the item by selecting a customized Problem Code, each return line also has a note area.

After the return has been submitted the user will receive confirmation and the return can be accessed on the return history page.

 Widget Option Usage

Widget options provide a way to customize widgets in various ways. Widget options are sent to the widget when loaded with the LoadWidgetControl.

allowedExtensionsForUpload - Sets the types of files that can be uploaded. Default: '.jpg, .jpeg, .png, .pdf'

maxFileSize - Set the maximum size for uploaded files. Default: 4500000 (4.5 MB)

displayRules - Display the file size and file type allowed to the user. Default: true

selectButtonText - Set the text displayed in the file uploader. Default: 'Click or Drop File here'

fileUploadPrefix - Add a prefix to the name of the uploaded file. Default: ''

fileUploadSuffix - Add a suffix to the name of the uploaded file. Default: ''

AddReturnNumberToFileName - Add the Return Number to the uploaded file name Default: true

strObscureFilename - Change the name of the uploaded file to a randomly generated number. Default: false

allowMultipleFiles- Allow the user to upload more than one file. Default: false

popupText - Customize the text on the confirmation popup. Default: 'Thank You, We have received your return.'

popupHeader - Customize the text in the popup tile Default: 'The return has been entered.'

popupButtonText - Customize the text in the popup button. Default: 'Continue to Returns Section

submitButtonText - Customize the text in the Submit button. Default: 'Submit Return'

salesOrderPlaceholder - Customize the placeholder text in the sales order number input. Default: 'Enter Order Number'

 Example

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

<Control src="LoadWidgetControl.ascx" FileLocation="ItemReturnForm.html" RequireLogin="true" 
    Options="
        popupText: 'A member of our team will review your submission and you should expect to receive an email within 2-3
            busines days with an approval and shipping instructions or a follow-up requesting additional information
            about your return.',
        popupHeader: 'Thank you for submitting your return.',
        popupButtonText: 'Continue to Returns Section',
        submitButtonText: 'Submit Return',
        salesOrderPlaceholder: 'Enter Order Number',
        allowMultipleFiles: false,
        maxFileSize: 5000000,
        allowedExtensionsForUpload: '.Pdf',
        strObscureFilename: false,
        AddReturnNumberToFileName: true,
        fileUploadPrefix: 'pre_',
        fileUploadSuffix: '_Suf',
        displayRules: true,
        selectButtonText: 'Drop file here',"
/>
 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.

<style type='text/css'>
    /*   * {
        font-family: 'Open Sans', Arial, sans-serif;
    }*/

    #Main_Title {
        font-size: 20px;
        font-weight: 300;
        /*     border-bottom: 1px solid #cac9c9;*/
        height: 45px;
        color: #333;
        max-width: 190px;
    }

    .input-container {
        display: flex;
        flex-wrap: wrap;
        margin: 5px 0 25px;
        box-sizing: border-box;
    }

    .dx-field {
        flex-direction: column;
        display: flex;
        width: 50;
    }

        .dx-field.one .dx-field-value {
            display: flex;
            width !important;
        }

    .dx-field-label {
        float: left;
        width: 100;
        font-weight: 700;
    }

    div#salesOrderNumberLookup {
        width;
    }

    .btn {
        border-width: 2px;
        font-weight: 400;
        letter-spacing: 1.7px;
        -webkit-transition: all 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.1s ease-in-out;
        transition: all 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.1s ease-in-out;
        outline-color: #f60 !important;
        padding: 7px 12px 6px;
    }

    .dx-button-mode-text.dx-button-default {
        background-color: #cac7c7;
        color: #000000;
    }

        .dx-button-mode-text.dx-button-default.dx-state-hover {
            background-color: #000;
            color: #fff;
        }

    .btn-primary,
    .dx-toolbar-button .dx-button-mode-contained {
        color: #fff;
        background-color: #f60;
        border-color: #f60;
    }

    .btn-import.dx-button-mode-contained {
        color: #ee3a43;
        background-color: #e9ece7;
        border-radius: 0;
        margin-left: -10px !important;
    }

    button.btn.btn-primary {
        font-size: 1.0em;
        min-width: 115px;
    }

    .dx-button-mode-contained.dx-button-default {
        background: #f60;
        color: #fff;
    }

        .dx-button-mode-contained.dx-button-default.dx-state-hover,
        .default_btn_class.dx-button-mode-contained.dx-button-default.dx-state-focused {
            background: #000;
            color: #fff;
        }

    .dx-item.dx-list-item.dx-state-focused {
        background-color: #fff !important;
        color: #000 !important;
    }



    .dx-list-static-delete-button .dx-button-content,
    .dx-list-switchable-delete-button .dx-button-content {
        padding: 4px;
    }

    i.dx-icon.fa.fa-trash {
        font-size: 16px;
        color: #808080 !important;
    }

    .dx-widget.dx-numberbox-spin-button.dx-numberbox-spin-up.dx-state-hover,
    .dx-widget.dx-numberbox-spin-button.dx-numberbox-spin-down.dx-state-hover {
        background: #fff !important;
    }

        .dx-widget.dx-numberbox-spin-button.dx-numberbox-spin-up.dx-state-hover .dx-numberbox-spin-up-icon,
        .dx-widget.dx-numberbox-spin-button.dx-numberbox-spin-down.dx-state-hover .dx-numberbox-spin-down-icon {
            color: red;
            background: #fff !important;
        }

    .dx-item.dx-list-item.dx-state-active {
        background-color: rgba(00, 0, 0, 0.04) !important;
    }

    .dx-button-mode-contained {
        color: #fff;
        background-color: #f60;
        border-color: #f60;
        border-width: 0;
    }

        .dx-button-mode-contained.dx-state-hover {
            color: #fff;
            background-color: #000;
            border-width: 0;
        }

    i.dx-icon.fa.fa-long-arrow-right {
        float: right;
        margin-left: 20px;
        color: #fff;
    }

    /* used to mark questions for client*/
    .ClientQs {
        color: blue;
        font-size: 12px;
        font-weight: bold;
    }

    /*  RMA FORM STYLES   */
    .rmaHeaderRow {
        display: flex;
        justify-content: space-between;
    }

        .rmaHeaderRow div {
            font-weight: 700;
            /*color: #808080;*/
        }

        .rmaHeaderRow .inputWrapper {
            display: flex;
            justify-content: space-between;
            flex-basis: 50;
        }

    .productHeader {
        flex-basis;
    }

    .qtyHeader {
        flex-basis: 47;
    }

    .reasonHeader {
        flex-basis;
    }

    .rmaRow {
        display: flex;
        flex-direction: row;
        /*     flex-wrap: nowrap;
      padding: 15px;
     gap: 20px;*/
    }

        .rmaRow .image {
            padding: 0 10px;
        }

            .rmaRow .image img {
                width: 80px;
            }

    .dataRows {
        display: flex;
        flex-direction: column;
        justify-content: space-evenly;
        flex-grow: 1;
        flex-wrap: wrap;
        /*    width: 100;*/
    }

    .dataRowOne,
    .dataRowTwo {
        display: flex;
        flex-wrap: wrap;
        margin-bottom: 20px;
        margin-right: 20px;
    }

    .dataRowOne {
        justify-content: space-between;
        /*padding-right: 5px;*/
        margin-right: 20px;
        margin-bottom: 0px;
    }

    .details {
        /* flex-grow: 2; */
        /* max-width: 350px; */
        flex-basis;
    }

        .details .name {
            font-weight: 500;
            padding-left: 10px;
        }

        .details .stockcode {
            font-size: 12px;
            padding-left: 10px;
        }

    .selectWrapper {
        display: flex;
        flex-basis: 55;
        justify-content: space-around;
        padding: 0px;
    }

        .selectWrapper > div {
            flex-basis;
        }

    .dataRowOne .qty {
        max-width: 85px;
        margin: 0 8px 0 0;
    }

        .dataRowOne .qty input {
            text-align: center;
        }

    .dataRowOne .reason {
        flex-basis: 25;
    }

    .dataRowTwo {
        justify-content: space-between;
        max-width: 510px;
    }

        .dataRowTwo .condition,
        .dataRowTwo .rmaType {
            width;
        }

    .dx-numberbox-spin-down,
    .dx-numberbox-spin-up {
        position: relative;
        width: 100 !important;
        height !important;
        cursor: pointer !important;
        display: block !important;
    }

    .dx-field-value-static,
    .dx-field-value:not(.dx-switch):not(.dx-checkbox):not(.dx-button) {
        width: fit-content;
    }

    div#skuNumber {
        width: 50;
    }

    div#rmaHeaderNote {
        width;
    }

    #ReturnFileUploaderContainer {
        width: 50;
    }

    .dx-fileuploader-button.dx-button-mode-contained {
        color: #333;
        background-color: #ffffff;
        border-color: #fff;
        border-width: 1px;
    }

        .dx-fileuploader-button.dx-button-mode-contained.dx-state-hover {
            color: #333;
            background-color: #ffffff;
            border-color: #ddd;
            border-width: 1px;
        }

    @media (min-width: 320px) {
        .rmaRow {
            flex-wrap: wrap;
        }

        .dataRows {
            display: block;
            flex-wrap: wrap;
        }

        .dataRowOne,
        .dataRowTwo {
            flex-direction: column;
            margin-bottom: 0px;
        }

        .details {
            flex-basis;
            margin-bottom: 20px;
        }

        .selectWrapper {
            flex-basis: 100;
            justify-content: space-between;
            display: block;
            padding: 10px;
        }

            .selectWrapper > div {
                flex-basis;
                margin-bottom: 20px;
            }

        .dataRowTwo > div {
            flex-basis: 38;
            margin-bottom: 20px;
        }

        .dx-numberbox-spin-touch-friendly .dx-numberbox-spin-container {
            width: 34px !important;
        }

        .dx-list-item-after-bag,
        .dx-list-item-before-bag {
            vertical-align: top;
            padding-top: 10px;
        }

        .dx-list-static-delete-button,
        .dx-list-switchable-delete-button {
            padding: 5px;
            top: -140px;
            right: 10px;
        }

        .dx-icon-remove::before {
            color: #fff;
        }
    }

    @media (min-width: 768px) {

        .dataRowOne,
        .dataRowTwo {
            flex-direction: row;
            margin-bottom: 0px;
        }

        .productHeader {
            flex-basis;
        }

        .rmaHeaderRow .inputWrapper {
            flex-basis: 57;
        }

        .selectWrapper > div {
            flex-basis;
            margin-bottom: 20px;
        }

        .dataRowTwo > div {
            flex-basis: 38;
        }

        .dx-list-item-after-bag,
        .dx-list-item-before-bag {
            vertical-align: middle;
            padding-top: 0px;
        }

        .dx-list-static-delete-button,
        .dx-list-switchable-delete-button {
            padding: 5px;
            top: -100px;
            right: 0px;
            position: relative;
            border-width: 0px;
            /* background-color: #fff !important;*/
        }

        .dx-icon-remove::before {
            color: #fff;
        }
    }

    @media (min-width: 926px) {
        .dataRows {
            flex-wrap: nowrap;
        }

        .dataRowOne,
        .dataRowTwo {
            flex-direction: row;
            margin-bottom: 10px;
            justify-content: space-between;
        }

        .productHeader {
            flex-basis;
        }

        .rmaHeaderRow .inputWrapper {
            flex-basis: 57;
        }

        .details {
            flex-basis;
            margin-bottom: 0;
        }

        .selectWrapper {
            display: flex;
            flex-basis: 55;
            justify-content: space-between;
        }

            .selectWrapper > div {
                flex-basis;
                margin-bottom: 0px;
            }

        .dataRowTwo > div {
            flex-basis: 46;
        }

        .dx-list-static-delete-button,
        .dx-list-switchable-delete-button {
            padding: 5px;
            top: -10px;
            right: 0px;
            position: relative;
            border-width: 0px;
            /* background-color: #fff !important;*/
        }

        .dx-button-mode-contained .dx-icon {
            /*color: #000;*/
        }
    }

    @media (min-width: 1200px) {
        .productHeader {
            flex-basis;
        }

        .rmaRow {
            flex-wrap: nowrap;
        }
    }

    /* NOTE  */
    .fileUploadArea {
        border: 1px solid rgb(211, 208, 208);
    }

    .dx-fileuploader-upload-button {
        display: none;
        color: #000;
    }

    .note {
        display: flex;
        font-size: 10pt;
        color: #484848;
        margin-left: 9px;
        font-weight: 700
    }

        .note > span {
            font-weight: 500
        }

        .note > div {
            font-weight: 500;
            max-width: 161px;
            white-space: normal;
            padding: 0 5px;
        }

    .noteData {
        display: inline;
    }

    .dx-fileuploader-upload-button {
    }
</style>

<div class='returnBodyWrapper'>
    <div id='Main_Title'>
        <h1>Returns</h1>

    </div>
    <div id='returnHistoryBtn'></div>
    <!-- import SO Number -->
    <div class='input-container'>
        <div class='dx-field one'>
            <div class='dx-field-label'>
                Online Order Lookup
            </div>
            <div class='dx-field-value'>
                <div id='salesOrderNumberLookup'>
                </div>
            </div>
        </div>
        <div class='dx-field one'>
            <div class='dx-field-label'>
                Add Item To Return
            </div>
            <div class='dx-field-value'>
                <div id='skuNumber'>
                </div>
            </div>
        </div><br />
        <div class='dx-field one'>
            <div class='dx-field-label'>
                Notes:
            </div>
            <div class='dx-field-value'>
                <div id='rmaHeaderNote'>
                </div>
            </div>
        </div>

        <div class='dx-field one'>
            <div class='dx-field-label'>
                Upload File (Optional)
            </div>
            <div class='dx-field-value'>
                <div id='ReturnFileUploaderContainer' class='fileUploadArea'>
                </div>
            </div>
            <div>
                <div class='note_widgetOptions note'>
                    Allowed file extensions:
                    <div class='fileTypeDisplay_widgetOptions noteData'></div>
                </div>
                <div class='note_widgetOptions note'>
                    Maximum file size:
                    <div class='maxFileSizeDisplay_widgetOptions noteData'> </div>
                </div>
            </div>
        </div>
    </div>
    <!-- add SKU may not be in system StockCode-->
    <div class='input-container'>

    </div>
    <!-- display Sale Order section Header -->
    <div class='rmaHeaderRow hidden-xs hidden-sm'>
        <div class='productHeader'>Product Details</div>
        <div class='inputWrapper'>
            <div class='qtyHeader'>Qty to Return</div>
            <div class='reasonHeader'>Reason for Return</div>
            <div class='reasonHeader'>Note</div>
        </div>
    </div>
    <div>
        <hr>
    </div>

    <!-- Display order items in DX list control -->
    <div id='returnListWidgetDiv'></div>

    <!-- submit button -->
    <div class='dx-field-value col-sm-12 col-md-4 import'>
        <div class='btn btn-primary btn-lgd' id='icon-submit'>
        </div>
    </div>

</div>
<div id="popReturn"></div>

<script>
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' Base Widget:  ItemReturnForm.html
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' Custom Widget Filename: ItemReturnForm.html
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' (c) 2021 by Dovetail Internet Technologies, LLC
    // '              www.dovetailinternet.com
    // '              info@dovetailinternet.com
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' All rights reserved. Not to be used without permission.
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' Development Date: July 2021
    // ' Revision: 1.0
    // ' Modified: 11/01/2022 - PR
    // '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    // ' Create an RMA for Gentec so that Items can be returned. TP # 13515
    // ''

    // Global Variables
    var ReturnData_widgetID = [];
    var ReturnListWidget_widgetID;
    //var RmaNumber = '';
    let AllProblemCodes = [];
    var DefaultProblemCode = '';
    var PendingReturn = {};
    var UOMTypes = [0, 'P', 'PRE', 'PREFERRED', 1, 'S', 'STK', 'STOCKING', 2, 'A', 'ALT', 'ALTERNATE', 3, 'O', 'OTH', 'OTHER'];


    /**================================================================================================
     **                                      GetReturnLineID
     *?  Get the ID for the return line from an ID string?
     *@param eid  The element id string
     *@return The return line identifier as an integer
     *================================================================================================**/
    function GetReturnLineID(eid) {
        return parseInt(eid.substring(eid.indexOf('_') + 1));
    }

    ///-------------------------------------------------------------------------------------------------
    /// <summary>
    ///     Loads data into the return list.
    /// </summary>
    ///
    /// <param name="data">
    ///     The data.
    /// </param>
    ///
    /// <returns>
    ///     The return list.
    /// </returns>
    //NOTE
    ///-------------------------------------------------------------------------------------------------
    function LoadReturnList_widgetID(data) {
        ReturnData_widgetID = data;
        for (var i = 0; i < data.length; i++) {
            var d = data[i];
            // handle Custom Data nulls
            if (_.isUndefined(d.CustomData) == false && d.CustomData != '') {
                if (_.isUndefined(d.Options)) {
                    d.Options = {};
                }
                if (_.isObject(d.CustomData)) {
                    d.Options.CustomData = d.CustomData;
                } else if (_.isString(d.CustomData)) {
                    d.Options.CustomData = JSON.parse(d.CustomData);
                }
            }
            // handle purchase date nulls
            // NOTE move to a function if we need to do more of this in the future
            if (!_.isUndefined(d.PurchaseDate)) {
                if (d.PurchaseDate === null) {
                    d.PurchaseDate = '';
                }
            } else {
                d.PurchaseDate = '';
            }
        }
        ReturnData_widgetID = data;

        // $('#icon-submit').dxButton('option', 'disabled', _.isEmpty(ReturnData_widgetID))
        enableSubmitBtn(_.isEmpty(ReturnData_widgetID));
        ReturnListWidget_widgetID.option("dataSource", ReturnData_widgetID);
    }

    /**================================================================================================
     **                                   UpdateReturnLine_widgetID
     *?  Updates the detail line on a return?
     *@param objIndex int
     *@param name type
     *@return type
     // NOTE {ID,  StockCode,  Qty,  UOM,  PurchaseDate,  SerialNumber,  ReturnType,  ProblemCode,  ProblemNotes,  Options{}}
     *================================================================================================**/
    function UpdateReturnLine_widgetID(objIndex) {

        var l = ReturnData_widgetID[objIndex];
        //console.log(l);
        var uom = (_.isUndefined(l.UOM))
            ? 0
            : (_.contains(UOMTypes, l.UOM))
                ? l.UOM
                : (!isNaN(l.UOM))
                    ? '@' + l.UOM
                    : 0;
        MakeAJAXCall("Return.UpdateReturnLine", {
            ID: l.ID,
            StockCode: l.StockCode,
            Qty: l.Quantity,
            UOM: uom,
            PurchaseDate: l.PurchaseDate,
            SerialNumber: l.SerialNumber,
            ReturnType: (l.ReturnType.length > 0 ? l.ReturnType : 'G'),
            ProblemCode: l.ProblemCode,
            ProblemNotes: l.ProblemNotes,
            Options: l.Options
        }, function (DATA) {
            if (ValidAJAXResponse(DATA)) {
                var d = JSON.parse(DATA);
                if (d.Result.Success) {
                    LoadReturnList_widgetID(d.Data.Details);
                } else {
                    ToastAlert(d.Result.Message, false);
                }
            }
        });
    }



    ///-------------------------------------------------------------------------------------------------
    /// <summary>
    ///     Searches for the index of the first object in an array that has a specific attribute value.
    /// </summary>
    ///
    /// <param name="array">
    ///     The array.
    /// </param>
    /// <param name="attr">
    ///     The attribute.
    /// </param>
    /// <param name="value">
    ///     The value.
    /// </param>
    ///
    /// <returns>
    ///     The zero-based index of the found array by attribute value, or -1 if no match was found.
    /// </returns>
    ///-------------------------------------------------------------------------------------------------
    function IndexOfByAttrValue(array, attr, value) {
        for (var i = 0; i < array.length; i++) {
            if (array[i][attr] === value) {
                return i;
            }
        }
        return -1;
    }

    /**================================================================================================
     **                                      setWidgetOptionDefaults
     *?  set - check default values for widget options in one place?
     *@return type
    //TODO Need better default ==> deconstruction would work
    //NOTE if widgetOption == '' that is valid
     *================================================================================================**/
    function setWidgetOptionDefaults(widgetOptions = {}) {
        if (!_.isString(widgetOptions.allowedExtensionsForUpload) || widgetOptions.allowedExtensionsForUpload == '') {
            widgetOptions.allowedExtensionsForUpload = '.jpg, .jpeg, .png, .pdf';
        }
        (!_.isString(widgetOptions.selectButtonText)) ? widgetOptions.selectButtonText = 'Click or Drop File here' : widgetOptions.selectButtonText = widgetOptions.selectButtonText;
        (!_.isString(widgetOptions.fileUploadPrefix)) ? widgetOptions.fileUploadPrefix = '' : widgetOptions.fileUploadPrefix = widgetOptions.fileUploadPrefix;
        (!_.isString(widgetOptions.fileUploadSuffix)) ? widgetOptions.fileUploadSuffix = '' : widgetOptions.fileUploadSuffix = widgetOptions.fileUploadSuffix;
        (!_.isString(widgetOptions.popupText)) ? widgetOptions.popupText = 'Thank You, We have received your return.' : widgetOptions.popupText = widgetOptions.popupText;
        (!_.isString(widgetOptions.popupHeader)) ? widgetOptions.popupHeader = 'The return has been entered' : widgetOptions.popupHeader = widgetOptions.popupHeader;
        (!_.isString(widgetOptions.popupButtonText)) ? widgetOptions.popupButtonText = 'Continue to Returns Section' : widgetOptions.popupButtonText = widgetOptions.popupButtonText;
        (!_.isString(widgetOptions.submitButtonText)) ? widgetOptions.submitButtonText = 'Submit Return' : widgetOptions.submitButtonText = widgetOptions.submitButtonText;
        (!_.isString(widgetOptions.salesOrderPlaceholder)) ? widgetOptions.salesOrderPlaceholder = 'Enter Order Number' : widgetOptions.salesOrderPlaceholder = widgetOptions.salesOrderPlaceholder;
        widgetOptions.allowMultipleFiles === true ? widgetOptions.allowMultipleFiles = widgetOptions.allowMultipleFiles : widgetOptions.allowMultipleFiles = false;
        widgetOptions.strObscureFilename === true ? widgetOptions.strObscureFilename = widgetOptions.strObscureFilename : widgetOptions.strObscureFilename = false;
        widgetOptions.AddReturnNumberToFileName === true ? widgetOptions.AddReturnNumberToFileName = widgetOptions.AddReturnNumberToFileName : widgetOptions.AddReturnNumberToFileName = false;
        (_.isNaN(widgetOptions.maxFileSize)) ? widgetOptions.maxFileSize = 4500000 : widgetOptions.maxFileSize = widgetOptions.maxFileSize;
        widgetOptions.displayRules === false ? widgetOptions.displayRules = widgetOptions.displayRules : widgetOptions.displayRules = true;
    }

    /**================================================================================================
     **                                      enableSubmitBtn
     *?  disable the submit button if the form can not validate or if there is no items?
     *@param isTrue bool
     *================================================================================================**/
    function enableSubmitBtn(isTrue) {
        $('#icon-submit').dxButton('option', 'disabled', isTrue)
    }

    /**================================================================================================
     **                                         Onload
     *================================================================================================**/
    $(function () {

        //page level vars
        let isNewNote = false;
        var salesOrderNumber = '';
        let saveNoteTracker = 0;

        //NOTE Template get underscore
        DevExpress.setTemplateEngine('underscore');
        _.templateSettings.variable = 'item';

        setWidgetOptionDefaults(widgetOptions);

        $('#returnHistoryBtn').dxButton({
            text: 'Return History',
            type: "default",
            stylingMode: "contained",
            elementAttr: {
                class: "default_btn_class DT-Button"
            },
            onClick: function (e) { document.location = SITE_PATHS.application + '/ReturnHistory.aspx'; }
        });



        /**================================================================================================
         **       Sales order input
         *================================================================================================**/
        var txtImportOrder = $('#salesOrderNumberLookup').dxTextBox({
            placeholder: widgetOptions.salesOrderPlaceholder,
            onValueChanged: function (e) {
                salesOrderNumber = e.value;
            },
            onEnterKey: function (e) {
                var textBox = e.component;
                textBox.blur();
                getOrderDetails(salesOrderNumber);
                textBox.focus();
            },
            buttons: [{
                name: 'import',
                location: 'after',
                options: {
                    text: 'Import',
                    type: 'default',
                    stylingMode: 'text',
                    elementAttr: { id: 'btnImportOrder', class: 'DT-Button' },
                    onClick: function () {
                        getOrderDetails(salesOrderNumber);
                        txtImportOrder.focus();
                    }
                }
            }]
        });

        /**================================================================================================
         * Stock code input
         *================================================================================================**/
        $('#skuNumber').dxAutocomplete({
            dataSource: new DevExpress.data.CustomStore({
                loadMode: "raw",
                load: function () {
                    return $.getJSON("/ecommerce/exports/stockcodes.json");
                }
            }),
            placeholder: 'Enter Product Number',
            valueExpr: 'stockcode',
            searchExpr: ['stockcode', 'name'],
            itemTemplate: function (data, index) {
                return data.stockcode + ' - ' + data.name;
            },
            showClearButton: true,
            onEnterKey: function (e) {
                e.component.blur();
                StockCodeLookup(e.component.option('value'));
            },
            onValueChanged: function (data) { },
            buttons: [{
                name: 'add',
                location: 'after',
                options: {
                    text: 'Add',
                    type: 'default',
                    stylingMode: 'text',
                    elementAttr: { id: 'btnAddSku', class: 'DT-Button' },
                    onClick: function (e) {
                        StockCodeLookup($('#skuNumber').dxAutocomplete('option', 'value'));
                    }
                }
            }],

        });


        /**================================================================================================
         **   Note field (syspro Special instructions)
         *================================================================================================**/
        $('#rmaHeaderNote').dxTextArea({
            value: '',
            placeholder: 'Max length is 30 characters',
            height: 34,
            maxLength: 30,
            onValueChanged(e) {
                if (e.Value != e.previousValue) {
                    isNewNote = true;
                }
            },
            onFocusOut(e) {
                if (e.event.target.value.length >= 0 && isNewNote) {
                    PendingReturn.SpecialInstrs = e.event.target.value;
                    SaveReturnOptions(PendingReturn);
                }

            }
        });
        // .dxValidator({
        //     name: 'note',
        //     validationRules: [{
        //         type: 'required'
        //     }]
        // });


        /**================================================================================================
         **                                      SaveReturnOptions
         *?  save note input to SpecialInstrs field?
         *@param  PendingReturn returnObj
        //NOTE {Branch, Fax, UserField1, SpecialInstructions, OrderType, AlternateKey, ServiceTicket}
         *================================================================================================**/
        function SaveReturnOptions({ Branch: B = '', Fax: F = '', UserField1: UF = '', SpecialInstrs: SI = '', OrderType: OT = '', AlternateKey: AK = '', ServiceTicket: ST = '' }) {
            try {
                MakeAJAXCall("Return.SaveReturnOptions", {
                    Branch: B,
                    Fax: F,
                    UserField1: UF,
                    SpecialInstructions: SI,
                    OrderType: OT,
                    AlternateKey: AK,
                    ServiceTicket: ST
                }, function (DATA) {
                    if (ValidAJAXResponse(DATA)) {
                        var data = JSON.parse(DATA);
                        if (data.Result.Success) {
                        }
                        if (!data.Result.Success) {
                            if (saveNoteTracker < 3) {
                                saveNoteTracker++;
                                SaveReturnOptions(PendingReturn);
                            }
                            if (saveNoteTracker >= 3) {
                                ToastAlert(data.Result.Message, 'The note was not saved.', 3000);
                            }
                        }
                    }
                })
            } catch (error) {
                console.log("Error: " + error);
            }
        }

        /**================================================================================================
         *   functions for the file loader
         *================================================================================================**/
        var allowedExtensionsForUploadArray = []
        allowedExtensionsForUploadArray = widgetOptions.allowedExtensionsForUpload.split(',');
        var allowedExtensions = buildFileTypesArray(allowedExtensionsForUploadArray);

        // update widget displays with widget info
        $('.maxFileSizeDisplay_widgetOptions').html((widgetOptions.maxFileSize / 1000000) + ' MB');
        $('.fileTypeDisplay_widgetOptions').html(buildDisplayString(allowedExtensions));
        (widgetOptions.displayRules) ? $('note_widgetOptions').show() : $('.note_widgetOptions').hide();

        /**================================================================================================
         **                                      buildDisplayString
         *?  display accepted file types?
         *@param someArray array
         *@return display of file types
         *================================================================================================**/
        function buildDisplayString(someArray) {
            var html = '';
            someArray.forEach(function (item, i, someArray) {
                // if (i % 5 == 0) {
                //     if (i !== 0) { html += '</br>'; }
                // }
                html += item + '  ';
            });
            return html;
        }

        function buildFileTypesArray(anArray) {
            var returnArray = [];
            // if (anArray.length <= 0) {
            //     returnArray = ['.jpg', '.jpeg', '.gif', '.png', '.pdf']; // default file types
            // }
            if (anArray.length > 0) {
                returnArray = anArray.map(item => item.replace(/\s/g, ''));
                returnArray = returnArray.map(function (item) {
                    if (item.startsWith('.')) {
                        return item;
                    }
                    if (!item.startsWith('.')) {
                        var newItem = '.' + item;
                        return newItem;
                    }
                })
            }
            return returnArray;
        }

        /**================================================================================================
         * *  Build file upoader
         * widgetOptions.strObscureFilename
         * widgetOptions.filePrefix
         * widgetOptions.fileSuffix
         * widgetOptions.maxFileSize
         * widgetOptions.displayRules
         * widgetOptions.selectButtonText: 'Click or Drop File here',
         *
         *================================================================================================**/
        var returnFormFileUplpader = $('#ReturnFileUploaderContainer').dxFileUploader({
            uploadMode: 'useButtons',
            maxFileSize: widgetOptions.maxFileSize,
            selectButtonText: widgetOptions.selectButtonText,
            invalidFileExtensionMessage: 'File type is not allowed',
            invalidMaxFileSizeMessage: 'File is too large',
            allowedFileExtensions: allowedExtensions,
            showFileList: true,
            uploadButtonText: '',
            labelText: '',
            multiple: widgetOptions.allowMultipleFiles
        }).dxFileUploader('instance');


        /**================================================================================================
         *      Submit Return button
         *================================================================================================**/
        $('#icon-submit').dxButton({
            text: widgetOptions.submitButtonText,
            elementAttr: {
                class: "default_btn_class DT-Button"
            },
            onClick: function (e) {
                var result = e.validationGroup.validate();
                DevExpress.validationEngine.validateGroup();
                if (result.isValid) {
                    enableSubmitBtn(result.isValid);
                    //NOTE confirm the note has been saved
                    MakeAJAXCall("Return.PostReturn", {
                        Options: {}
                    }, function (DATA) {
                        if (ValidAJAXResponse(DATA)) {
                            let data = JSON.parse(DATA);
                            if (data.Result.Success) {
                                let fileNamePrefix = '';
                                if (widgetOptions.AddReturnNumberToFileName) {
                                    fileNamePrefix = `${widgetOptions.fileUploadPrefix}${data.Data.RMANumber}_`;
                                }
                                if (!widgetOptions.AddReturnNumberToFileName) {
                                    fileNamePrefix = `${widgetOptions.fileUploadPrefix}`;
                                }
                                //NOTE save file if uploaded
                                $('#ReturnFileUploaderContainer').dxFileUploader("instance").option('uploadUrl', FileUploadUtil(widgetOptions.strObscureFilename, fileNamePrefix, widgetOptions.fileUploadSuffix));
                                $('#ReturnFileUploaderContainer').dxFileUploader("instance").upload();
                                $('#ReturnFileUploaderContainer').dxFileUploader("instance").reset();
                                $("#rmaHeaderNote").dxTextArea("instance").reset();

                                createPopup(data.Data.RMANumber);
                                LoadReturnList_widgetID([]);
                                ScrollTop();
                            }
                            else {
                                // we had an error submitting the form
                                ToastAlert(data.Result.Message, data.Result.Success, 5000);
                            }
                        }
                    });
                }
                if (!result.isValid) {
                    //enableSubmitBtn(result.isValid);
                    // $('#icon-submit').dxButton('option', 'disabled', )
                    var msg = 'A required field is missing a value.'
                    if (result.brokenRules.length > 1) {
                        msg = result.brokenRules.length + ' required fields are missing values.'
                    }
                    ToastAlert(msg, result.isValid, 3000);
                }
            }
        });



        /**================================================================================================
         **   Build and fill return line detail list
         *================================================================================================**/
        ReturnListWidget_widgetID = $('#returnListWidgetDiv').dxList({
            height: 'auto',
            itemTemplate: $('#itemTemplate'),
            noDataText: '',
            allowItemDeleting: true,
            noDataText: 'Start your return request by entering an Order or Product number above.',
            onInitialized: function (e) {
                // load the currently pending return detail lines into the widget
                MakeAJAXCall("Return.GetPendingReturn", {}, function (DATA) {
                    if (ValidAJAXResponse(DATA)) {
                        var data = JSON.parse(DATA);
                        AllProblemCodes = data.LookupData.ProblemCodes;
                        DefaultProblemCode = data.LookupData.DefaultProblemCode;
                        PendingReturn = data.Data;
                        LoadReturnList_widgetID(data.Data.Details);
                    }
                })
            },
            onItemDeleted: function (e) {
                // delete the line from the pending return
                MakeAJAXCall('Return.DeleteReturnLine', { ID: e.itemData.ID }, function (DATA) {
                    if (ValidAJAXResponse(DATA)) {
                        var data = JSON.parse(DATA);
                        LoadReturnList_widgetID(data.Data.Details);
                    }
                });
            }
        }).dxList('instance');


        // }
        ///-------------------------------------------------------------------------------------------------
        /// <summary>
        ///     Gets order details.
        /// </summary>
        ///
        /// <param name="salesOrderNumber">
        ///     The sales order number.
        /// </param>
        ///
        /// <returns>
        ///     .
        /// </returns>
        ///-------------------------------------------------------------------------------------------------
        function getOrderDetails(salesOrderNumber) {
            MakeAJAXCall('Order.GetOrder', { OrderNumber: salesOrderNumber }, function (DATA) {
                if (ValidAJAXResponse(DATA)) {
                    var d = JSON.parse(DATA);
                    if (_.isEmpty(d.Data)) {
                        ToastAlert(d.Result.Message, false);
                    }
                    AddOrderToReturn(d.Data.Details);
                }
            });
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary>
        ///     Adds an order to the return
        /// </summary>
        ///
        /// <param name="dataSource">
        ///     The data source.stoc
        /// </param>
        /// <returns>
        ///     .
        /// </returns>
        ///-------------------------------------------------------------------------------------------------
        function AddOrderToReturn(dataSource) {
            var items = [];
            dataSource.forEach(function (detail) {
                items.push({
                    StockCode: detail.StockCode,
                    Qty: detail.Quantity,
                    UOM: String.Format('@{0}', detail.UOM),
                    PurchaseDate: '',
                    SerialNumber: '',
                    Options: {}
                })
            });
            MakeAJAXCall("Return.AddItemsToReturn", { Items: items }, function (DATA) {
                if (ValidAJAXResponse(DATA)) {
                    var data = JSON.parse(DATA);
                    LoadReturnList_widgetID(data.Data.Details);
                }
            });
            $('#salesOrderNumberLookup').dxTextBox('option', 'value', '');
        }


        ///-------------------------------------------------------------------------------------------------
        /// <summary>
        ///     Perform the stock code lookup, and add the item to the return list
        /// </summary>
        ///
        /// <param name="stockCode">
        ///     The stock code.
        /// </param>
        ///
        /// <returns>
        ///     confirms that the item number is not null
        /// </returns>
        ///-------------------------------------------------------------------------------------------------
        function StockCodeLookup(stockCode) {

            if (stockCode === null || stockCode === undefined || (stockCode.trim()).length <= 0) {
                $('#skuNumber').dxAutocomplete('option', 'isValid', false);
                setTimeout(function () {
                    $('#skuNumber').dxAutocomplete('option', 'isValid', true);
                }, 7000);
                ToastAlert('A product number is required.', false, 5000, 5000);
                return;
            }
            stockCode = stockCode.replace(/[\f\n\r\t\v]+/g, '');
            $('#skuNumber').dxAutocomplete('option', 'isValid', true)

            //NOTE the input exists good or bad look up the stockCode and get response
            MakeAJAXCall('Inventory.GetItemByStockCode', {
                StockCode: stockCode
            }, function (DATA) {
                let returnedItem = { StockCode: '', NonStockedItem: false }
                if (DATA) {
                    var data = JSON.parse(DATA);
                    if (data.Results.Success) {
                        returnedItem.StockCode = data.StockCode,
                            returnedItem.NonStockedItem = false;
                    }
                    if (!data.Results.Success) {
                        returnedItem.StockCode = stockCode,
                            returnedItem.NonStockedItem = true;
                    }
                    addItemToReturnList(returnedItem)
                }
            })
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary>
        ///     Adds an item to return list.
        /// </summary>
        ///
        /// <param name="returnedItem">
        ///     { StockCode: string, NonStockedItem: bool }
        /// </param>
        ///-------------------------------------------------------------------------------------------------
        function addItemToReturnList(returnedItem) {
            MakeAJAXCall("Return.AddItemToReturnByStockCode",
                {
                    StockCode: returnedItem.StockCode,
                    Qty: 1,
                    UOM: 0,
                    PurchaseDate: '',
                    SerialNumber: '',
                    Options: {
                        NonStockItem: returnedItem.NonStockedItem,
                    }
                }, function (DATA) {
                    if (ValidAJAXResponse(DATA)) {
                        var d = JSON.parse(DATA);
                        if (d.Result.Success) {
                            $('#skuNumber').dxAutocomplete('option', 'value', '');
                            LoadReturnList_widgetID(d.Data.Details);
                        } else {
                            ToastAlert(d.Result.Message, false);
                        }
                    }
                    $('#skuNumber').dxAutocomplete('instance').focus();
                });
        }

        /**================================================================================================
         **                                              createPopup
         *?  create and display RMA popup?
         *@param rmaNumber string
         *@return dxPopup
         *================================================================================================**/
        function createPopup(rmaNumber) {
            var popReturn = $('#popReturn').dxPopup({
                contentTemplate: function (contentElement) {
                    contentElement.append(
                        $('<h2 />').text(`${widgetOptions.popupHeader}`),
                        $('<h4 />').text(`RMA Number: ${rmaNumber}`),
                        $('<p />').text(`${widgetOptions.popupText}`)
                    )
                },
                animation: {
                    show: {
                        delay: 125,
                        type: 'pop',
                        duration: 400
                    }
                },
                height: 'auto',
                width: '600px',
                visible: false,
                showTitle: false,
                closeOnOutsideClick: true,
                resizeEnabled: true,
                dragEnabled: true,
                elementAttr: {
                    class: 'thankYouPopup'
                },
                toolbarItems: [{
                    widget: 'dxButton',
                    toolbar: 'bottom',
                    location: 'after',
                    options: {
                        text: widgetOptions.popupButtonText,
                        type: 'success',
                        stylingMode: 'contained',
                        onClick: function (e) {
                            popReturn.hide();
                        },
                        elementAttr: {
                            class: 'btn-primary DT-Button'
                        },
                    }
                }]
            }).dxPopup('instance');
            popReturn.show();
        }


    });

    ///-------------------------------------------------------------------------------------------------
    /// <summary>
    ///     Check options and custom data objects exist in a ReturnData member.
    /// </summary>
    ///
    /// <param name="index">
    ///     Zero-based index of the.
    /// </param>
    ///
    /// <returns>
    ///     .
    /// </returns>
    //NOTE this function is not used in the base version but could be used if custome data in utilized
    ///-------------------------------------------------------------------------------------------------
    function CheckOptions(index) {
        if (_.isUndefined(ReturnData_widgetID[index].Options)) {
            ReturnData_widgetID[index].Options = {};

        }
        if (_.isUndefined(ReturnData_widgetID[index].Options.CustomData)) {
            ReturnData
            ReturnData_widgetID[index].Options.CustomData = {};
        }
    }

    /**================================================================================================
     **                                      BuildRowWidgets
     *?  Builds and fills the line detail widgets?
     *@param item array - return line detail
     *@return type
     *================================================================================================**/
    function BuildRowWidgets(item) {
        /**------------------------------------------------------------------------------------------------
         * QTY input
         *------------------------------------------------------------------------------------------------**/
        $('#qty_' + item.ID).dxNumberBox({
            mode: 'number',
            min: 1,
            value: item.Quantity,
            showSpinButtons: true,
            onValueChanged: function (e) {
                var r = IndexOfByAttrValue(ReturnData_widgetID, 'ID', item.ID);
                ReturnData_widgetID[r].Quantity = e.value;
                UpdateReturnLine_widgetID(r);
            }
        }).dxValidator({
            name: 'Quantity',
            validationRules: [{
                type: 'required'
            }]
        });


        /**------------------------------------------------------------------------------------------------
         * New Return reason with Problem codes
         *------------------------------------------------------------------------------------------------**/
        $('#reason_' + item.ID).dxSelectBox({
            dataSource: AllProblemCodes,
            displayExpr: 'DisplayText',
            valueExpr: 'Code',
            placeholder: 'Select One',
            onInitialized: function (e) {
                if (item.ProblemCode === '' && DefaultProblemCode !== '') {
                    e.component.option('value', DefaultProblemCode);
                    item.ProblemCode = DefaultProblemCode;
                }
                if (item.ProblemCode !== '') {
                    e.component.option('value', item.ProblemCode);
                }
            },
            onValueChanged: function (e) {
                var r = IndexOfByAttrValue(ReturnData_widgetID, 'ID', item.ID);
                ReturnData_widgetID[r].ProblemCode = e.value;
                UpdateReturnLine_widgetID(r);
            }
        }).dxValidator({
            name: 'Reason',
            validationRules: [{
                type: 'required'
            }]
        });

        /**================================================================================================
         *      Line item notes
         *================================================================================================**/
        $('#note_' + item.ID).dxTextArea({
            placeholder: "Add a note",
            height: 45,
            onInitialized: function (e) {
                if (!_.isUndefined(item.ProblemNotes)) {
                    e.component.option('value', item.ProblemNotes);
                }
            },
            maxLength: 250,
            onValueChanged(e) {
                var r = IndexOfByAttrValue(ReturnData_widgetID, 'ID', item.ID);
                //CheckOptions(r);
                ReturnData_widgetID[r].ProblemNotes = e.component.option('value')
                UpdateReturnLine_widgetID(r);

            }
        }).dxValidator({
            name: 'Line Note',
            validationRules: [{
                type: 'required'
            }]
        });;

        /**================================================================================================
         *      RMA type hidden
         *================================================================================================**/
        $('#rmaType_' + item.ID).dxTextBox({
            value: 'General Return',
            readOnly: true,
            visible: false,
            onValueChanged: function (e) {
            }
        });
    }
</script>



<!------------------------------------------ Line detail template template ------------------------------------------>
<!--NOTE use underscore template to build display  -->
<script type='text/html' id='itemTemplate'>
    <div class='row rmaRow'>
        <div class='image'>
            <img src='<%= item.Photo1 %>' />
        </div>
        <div class='dataRows'>
            <div class='dataRowOne'>
                <div class='details'>
                    <div class='name'> <%= item.Description %></div>
                    <div class='stockcode'><%= item.StockCode %></div>
                </div>
                <div class="selectWrapper">
                    <div class='rowQty' id='qty_<%= item.ID %>'></div>
                    <div class='rowSelect' id='reason_<%= item.ID %>'></div>
                    <div class='rowTextArea' id='note_<%= item.ID %>'></div>
                    <div id='rmaType_<%= item.ID %>'></div>
                </div>
            </div>
            <!-- <div class='dataRowTwo'>
                 <div id='condition_<%= item.ID %>'></div>
                <div id='rmaType_<%= item.ID %>'></div>
            </div> -->
        </div>
    </div>
    <% $(function () { BuildRowWidgets(item); }); %>
</script>