Link to home
Start Free TrialLog in
Avatar of Bruce Gust
Bruce GustFlag for United States of America

asked on

What is CAMS in this code?

Here's the code that references CAMS. I've got all of it here, but you don't have to look any further than line #30:

$(document).ready(function () {

    /* ################################################################### */
    /* Global events for viewing a company's detailed overview in the */
    /* slide out screen from the right */
    /* ################################################################### */

    var $slider, recordId, route;

    // bind the load action to all links referencing a company id
    $(document).on('click', 'a.open-company-details[data-company-id], a.open-company-details[data-prospect-id]', function () {
        var $this = $(this),
            id = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id');
        route = (typeof $this.attr('data-route') != 'undefined') ? $this.attr('data-route') : 'companies';

        recordId = id;
       
        openCompanyDetails(id, route);        
    });
    // Datatable assign to (someone else)
    $(document).on('click', 'a.assign-to', function () {
        var $this = $(this),
            userId = $this.attr('data-user-id'),
            id = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id');
        route = (typeof $this.attr('data-route') != 'undefined') ? $this.attr('data-route') : 'companies';

        recordId = id;


        CAMS.startAssignTo(id, route, userId);
    });
    // Datatable assign to me
    $(document).on('click', 'a.assign-to-me', function () {
        var $this = $(this),
            userId = $this.attr('data-user-id');
        id = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id');
        route = (typeof $this.attr('data-route') != 'undefined') ? $this.attr('data-route') : 'companies';

        recordId = id;
        $.post((route ? route + '/assign' : '/companies/assign'), { user: userId, companies: [recordId] }, function (resp) {
            if (resp.error) {
                CAMS.alert('Error', resp.msg, 'error');
                return false;
            }
            CAMS.alert('Success', 'Company was successfully assigned to you.', 'success');
        }, 'json').fail(function () {
            CAMS.alert('Error', 'An unexpected error was encountered while trying to save your company assignments. Please refresh the page and try again.', 'error');
        });
    });


    $(window).on('open-company-details', function (e, id, route, tab) {
        if (typeof id != 'string') {
            return CAMS.alert('Error', 'The link you clicked is not properly formed. Please refresh the page and try again.', 'error');
        }

        route = (typeof route == 'undefined' || route === '') ? CAMS.getAJAXRoute() : route;
        tab = (typeof tab == 'undefined') ? 'details' : tab;

        openCompanyDetails(id, route, tab);
    });


    $(document).on('click', 'a.edit-company-details[data-company-id], a.edit-company-details[data-prospect-id]', function () {
        var $this = $(this),
            id = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id');
        //route = (typeof $this.attr('data-company-id') != 'undefined') ? 'companies' : 'market';
        route = (typeof $this.attr('data-route') != 'undefined') ? $this.attr('data-route') : 'companies';

        recordId = id;

        $(window).trigger('company-form-show', [id, route]);
    });

    $(document).on('click', '.company-add-activity[data-prospect-id]', function () {
        var $this = $(this),
            opts = {
                'data-company-id': ((typeof $this.attr('data-company-id')) != 'undefined' ? $this.attr('data-company-id') : $this.attr('data-prospect-id')),
                'data-company-name': $this.attr('data-company-name'),
                'data-proposal-id': $this.attr('data-proposal-id'),
                'data-route': $this.attr('data-route'),
                'data-user-id': $this.attr('data-user-id')
            };

        if (typeof opts['data-company-id'] == 'undefined') {
            CAMS.alert('Invalid Link', 'The selected link is not properly formatted. Please refresh the page or contact support.', 'error');
        }

        if (typeof $this.attr('data-proposal-pipeline') != 'undefined') {
            opts['data-proposal-pipeline'] = $this.attr('data-proposal-pipeline');
        }

        CAMS.addActivity(opts);
    });

    $(document).on('click', '.delete-company[data-prospect-id]', function () {
        var prospect_id = $(this).attr('data-prospect-id');
        CAMS.confirm('Are You Sure?', 'Are you sure you want to delete the selected companies?', function (result) {
            if (!result) {
                return false;
            }

            $.post('/market/delete', { companies: [prospect_id] }, function (resp) {
                if (resp.error) {
                    return CAMS.alert('Unexpected Error', resp.msg, 'error');
                }

                // trigger a refresh of datatables
                dtTables['main-dt'].draw();
            }, 'json').fail(function () {
                CAMS.alert('Unexpected Error', 'We encountered an unexpected error while trying to process your request.', 'error');
            });
        });
    });


    $('#modal-company').on('click', '#btn-close', function () {
        CAMS.closeCompanyDetails();
        $("#modal-company").css("display", "none");
    });

    $('#modal-company').on('click', '#btn-edit,.edit-company-details', function () {
        var $this = $(this),
            id = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id');
        route = (typeof $this.attr('data-route') != 'undefined') ? $this.attr('data-route') : 'companies';

        $(window).trigger('company-form-show', [id, route]);
    });

    $('#modal-company').on('click', '.assign-to', function () {
        var $this = $(this),
            userId = $this.attr('data-user-id'),
            id = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id');
        route = (typeof $this.attr('data-route') != 'undefined') ? $this.attr('data-route') : 'companies';
        recordId = id;
        CAMS.startAssignTo(id, route, userId);
    });

    $('#modal-company').on('click', '#company-files-list .delete-file', function () {
        var $this = $(this),
            $tr = $this.closest('tr'),
            key = $tr.attr('data-file-key'),
            route = (typeof $this.attr('data-proposal-id') != 'undefined')
                ? '/companies/proposals/' + $this.attr('data-proposal-id') + '/delete-file/' + key
                : '/companies/delete-file/' + recordId + '/' + key;

        CAMS.confirm('Delete File?', 'Are you sure you want to delete this file?', function (resp) {
            if (!resp) {
                return false;
            }

            $.post(route, {}, function (resp) {
                $tr.remove();
            }, 'json').fail(function () {
                CAMS.alert('Unknown Error', 'We encountered an unexptected error while trying to delete the selected file. Please try again.', 'error');
            });
        });
    });

    $(window).on('select-user-post-complete', function (e, user) {
        //$('<a href="#" class="open-company-details" data-company-id="'+recordId+'" />').trigger('click');
        if (typeof recordId != 'undefined') {
            openCompanyDetails(recordId, (typeof route != 'undefined' ? route : '/companies/'));
        }
    });


    function openCompanyDetails(id, route, tab) {
        CAMS.showCompanyDetails(id, {
            route: route,
            afterOpen: function () {
                // add the file uploader
                CAMS.createFileUploader($('#modal-company').find('#btn-add-file'), {
                    fieldName: '',
                    onUpload: function (data) {
                        // save the file to the company record
                        //$.post((typeof route != 'undefined' ? route +'save-file/' : '/companies/save-file/') + recordId, {file: data}, function(resp){
                        $.post(('/' + route + '/save-file/' + recordId), { file: data }, function (resp) {
                            // do nothing for now
                        }, 'json').fail(function () {
                            CAMS.alert('Error', 'There was an error while trying to add the file to the company record.');
                        });
                    }
                });

                // open the specified tab
                if (typeof tab != 'undefined') {
                    $('#modal-company #' + tab + '-tab').trigger('click');
                }                
            }
        });
    }



    /* ################################################################### */
    /* Add/edit a company */
    /* ################################################################### */

    $(window).on('company-form-show', function (e, companyId, route) {
        var model = {
            _source: {type:'static',htmlType:'h3',label:'Source: Companies',class:'data-_source text-right'},
            name: objectModels.company.name,            
            owner: objectModels.company.owner,
            h3: {
                type: 'static',
                htmlType: 'h3',
                label: 'Meta Data'
            },
            p: {
                type: 'static',
                label: 'Additional meta data associated with this company.'
            }           
        };

        // add in the meta data fields
        for (var f in objectModels.company.meta.fields) {
            objectModels.company.meta.fields[f].name = 'meta[' + f + ']';

            model[f] = objectModels.company.meta.fields[f];
        }        
        
        // build the form
        formIt.show({
            title: 'Company',
            directionsText: '',
            fields: model,
            loadDataFromUrl: (typeof companyId == 'undefined' || companyId == 'new') ? '' : '/' + route + '/' + companyId + '?json=1',
            onShow: function (self) {
                self.$el.find('input[name="phone"]').mask('999-999-9999');
            },
            onDataReceived: function (data, self) {
                // we need to format the data to fit the form before loading it
                var clean = {
                    _id: data._id,
                    name: data.name,
                    owner: data.owner ? {
                        _id: data.owner._id, //Earlier data.owner[0]._id
                        text: data.owner.firstName + ' ' + data.owner.lastName
                    } : false
                };

                for (var f in objectModels.company.meta.fields) {
                    clean[f] = typeof data.meta != 'undefined'? (typeof data.meta[f] != 'undefined') ? data.meta[f] : '':'';
                }
                if (typeof data.market != 'undefined') {
                    if (data.source != 'undefined') {
                        $(document).find('h3.data-_source').text('Source: ' + data.source);
                    } else {
                        $(document).find('h3.data-_source').text('Source: Market Analysis');
                    }
                    
                }
                return clean;
            },
            onDataLoaded: function (data, self) {
                CAMS.createUserSelector($('#formit-owner'), self.$el);
            },
            ajax: {
                path: '/' + route + '/save/' + companyId,
                params: {},
                onComplete: function (resp, self) {
                    if (resp.error) {
                        self.addMsg(resp.msg);
                        return false;
                    }
                    companyId = resp.data ? resp.data.id : companyId;
                    openCompanyDetails(companyId, route);
                }
            }
        });
    });

    /* ################################################################### */
    /* Add a broker to the company form */
    /* ################################################################### */

    $('#modal-company').on('click', '#btn-add-broker', function (e, opts) {
        route = $(this).attr('data-route');
        recordId = typeof recordId == 'undefined' ? ((typeof $(this).attr('data-company-id')) != 'undefined' ? $(this).attr('data-company-id') : $(this).attr('data-prospect-id')) : recordId;
        var opts = (typeof opts == 'undefined') ? {} : opts,
            id = (typeof opts._id == 'undefined') ? 'new' : opts._id,
            config = {
                title: 'Add a Broker',
                directionsText: 'Complete the form below to add a new broker to the selected company.',
                fields: objectModels.broker.fields,
                onShow: function (self) {
                    //self.$el.find('input[name="phone"]').mask('999-999-9999');
                },
                ajax: {
                    path: '/' + (route ? route : 'companies') + '/' + recordId + '/brokers/' + id,
                    params: {},
                    onComplete: function (resp, self) {
                        if (resp.error) {
                            self.addMsg(resp.msg);
                            return false;
                        }

                        openCompanyDetails(recordId, (route ? route : 'companies'), 'details');
                    }
                }
            };

        if (typeof opts == 'object') {
            config = $.extend({}, opts, config);
        }

        formIt.show(config);
    });

    $('#modal-company').on('click', '.edit-broker', function () {
        var $this = $(this),
            companyId = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id'),
            brokerId = $this.attr('data-broker-id');
        route = $this.attr('data-route');

        if (typeof companyId == 'undefined' || typeof brokerId  == 'undefined') {
            return CAMS.alert('Error', 'The link you clicked is invalid. Please refresh the page to try again.', 'error');
        }

        $('#modal-company #btn-add-broker').trigger('click', [{ _id: brokerId, loadDataFromUrl: '/' + (route ? route : 'companies') + '/' + companyId + '/brokers/' + brokerId  }]);
    });


    /* ################################################################### */
    /* Add a contact to the company form */
    /* ################################################################### */

    $('#modal-company').on('click', '#btn-add-contact', function (e, opts) {
        route = $(this).attr('data-route');
        recordId = typeof recordId == 'undefined' ? ((typeof $(this).attr('data-company-id')) != 'undefined' ? $(this).attr('data-company-id') : $(this).attr('data-prospect-id')) : recordId;
        var opts = (typeof opts == 'undefined') ? {} : opts,
            id = (typeof opts._id == 'undefined') ? 'new' : opts._id,
            config = {
                title: 'Add a Contact',
                directionsText: 'Complete the form below to add a new contact to the selected company.',
                fields: objectModels.contact.fields,
                onShow: function (self) {
                    self.$el.find('input[name="phone"]').mask('999-999-9999');
                },
                ajax: {
                    path: '/' + (route ? route : 'companies') + '/' + recordId + '/contacts/' + id,
                    params: {},
                    onComplete: function (resp, self) {
                        if (resp.error) {
                            self.addMsg(resp.msg);
                            return false;
                        }

                        openCompanyDetails(recordId, (route ? route : 'companies'), 'contacts');
                    }
                }
            };

        if (typeof opts == 'object') {
            config = $.extend({}, opts, config);
        }

        formIt.show(config);
    });

    $('#modal-company').on('click', '.edit-contact', function () {
        var $this = $(this),
            companyId = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id'),
            contactId = $this.attr('data-contact-id');
        route = $this.attr('data-route');

        if (typeof companyId == 'undefined' || typeof contactId == 'undefined') {
            return CAMS.alert('Error', 'The link you clicked is invalid. Please refresh the page to try again.', 'error');
        }

        $('#modal-company #btn-add-contact').trigger('click', [{_id: contactId,loadDataFromUrl: '/'+(route ? route : 'companies') + '/' + companyId + '/contacts/' + contactId}]);
    });

    /* ################################################################### */
    /* Add an address/location to the company */
    /* ################################################################### */

    $('#modal-company').on('click', '#btn-add-address', function (e, opts) {
        route = $(this).attr('data-route');
        recordId = typeof recordId == 'undefined' ? ((typeof $(this).attr('data-company-id')) != 'undefined' ? $(this).attr('data-company-id') : $(this).attr('data-prospect-id')) : recordId;
        var opts = (typeof opts == 'undefined') ? {} : opts,
            id = (typeof opts._id == 'undefined') ? 'new' : opts._id,
            config = {
                title: 'Add an Address',
                directionsText: 'Start typing the address of the location you want to add. When results show up, please select one from the list. Or, manually enter the address you\'re looking for.',
                fields: {
                    street: {
                        type: 'string',
                        required: true,
                        label: 'Street Address'
                    },
                    city: {
                        type: 'string',
                        required: true,
                        label: 'City'
                    },
                    state: {
                        type: 'string',
                        required: true,
                        label: 'State'
                    },
                    postal: {
                        type: 'string',
                        required: true,
                        label: 'Postal/Zip Code'
                    }
                },
                ajax: {
                    path: '/' + (route ? route : 'companies') + '/' + recordId + '/addresses/' + id,
                    params: {},
                    onComplete: function (resp, self) {
                        if (resp.error) {
                            self.addMsg(resp.msg);
                            return false;
                        }

                        openCompanyDetails(recordId, (route ? route : 'companies'), 'contacts');
                    }
                }
            };

        if (typeof opts == 'object') {
            config = $.extend({}, opts, config);
        }

        formIt.show(config);
        // Google places Autocomplete
        $(document).find("#formit-street").attr("autocomplete", "nope");
        var autocomplete = new google.maps.places.Autocomplete(
            document.getElementById('formit-street'), { types: ['geocode'] });
        autocomplete.addListener('place_changed', fillInAddress);
        var componentForm = {
            street_number: 'short_name',
            route: 'long_name',
            locality: 'long_name',
            administrative_area_level_1: 'short_name',
            country: 'long_name',
            postal_code: 'short_name'
        };
        function fillInAddress() {
            // Get the place details from the autocomplete object.
            var place = autocomplete.getPlace();
            var streetElement = document.getElementById('formit-street');
            var cityElement = document.getElementById('formit-city');
            var stateElement = document.getElementById('formit-state');
            var postalElement = document.getElementById('formit-postal');

            streetElement.value = '';
            streetElement.disabled = false;
            cityElement.value = '';
            cityElement.disabled = false;
            stateElement.value = '';
            stateElement.disabled = false;
            postalElement.value = '';
            postalElement.disabled = false;


            // Get each component of the address from the place details,
            // and then fill-in the corresponding field on the form.
            for (var i = 0; i < place.address_components.length; i++) {
                var addressType = place.address_components[i].types[0];
                if (componentForm[addressType]) {
                    var val = place.address_components[i][componentForm[addressType]];
                    var componentElement = addressType == 'route' ? streetElement : addressType == 'locality' ? cityElement : addressType == 'administrative_area_level_1' ? stateElement : addressType == 'postal_code' ? postalElement : '';
                    if (componentElement) {
                        componentElement.value = val;
                    }

                }
            }
        }
    });

    $('#modal-company').on('click', '.edit-address', function () {
        var $this = $(this),
            companyId = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id'),
            addressId = $this.attr('data-address-id');
        route = $this.attr('data-route');
        if (typeof companyId == 'undefined' || typeof addressId == 'undefined') {
            return CAMS.alert('Error', 'The link you clicked is invalid. Please refresh the page to try again.', 'error');
        }

        $('#modal-company #btn-add-address').trigger('click', [{
            _id: addressId,
            loadDataFromUrl: '/'+(route ? route : 'companies') + '/' + companyId + '/addresses/' + addressId
        }]);
    });

    $('#modal-company').on('click', '.delete-contact', function () {
        var $this = $(this),
            companyId = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id'),
            contactId = $this.attr('data-contact-id');
        route = $this.attr('data-route');
        CAMS.confirm('Delete contact?', 'Are you sure you want to delete this contact?', function (resp) {
            if (!resp) {
                return false;
            }

            $.get((route ? route : 'companies') + '/' + recordId + '/contacts/delete/' + contactId, {}, function (resp) {
                $this.closest('.card').remove();
            }, 'json').fail(function () {
                CAMS.alert('Error', 'An unexpected error was encountered. Please try again.', 'error');
            });
        });
    });

    $('#modal-company').on('click', '.delete-address', function () {
        var $this = $(this),
            companyId = (typeof $this.attr('data-company-id') != 'undefined') ? $this.attr('data-company-id') : $this.attr('data-prospect-id'),
            addressId = $this.attr('data-address-id');
        route = $this.attr('data-route');
        CAMS.confirm('Delete address?', 'Are you sure you want to delete this address?', function (resp) {
            if (!resp) {
                return false;
            }

            $.get((route ? route : 'companies') + '/' + recordId + '/addresses/delete/' + addressId, {}, function (resp) {
                $this.closest('.card').remove();
            }, 'json').fail(function () {
                CAMS.alert('Error', 'An unexpected error was encountered. Please try again.', 'error');
            });
        });
    });
     /* ################################################################### */
    /* Custom Fields */
    /* ################################################################### */
    $('#modal-company').on('click', '.edit-custom-fields,.add-custom-fields', function () {
        let cID = $(this).attr('data-id'), _route = $(this).attr('data-route');
        $.get('/'+_route + '/' + cID + '/get/custom/fields', {}, function (resp) {
            if (resp.error) { CAMS.alert('Error', resp.error.msg, 'error'); }
            let kvcontrols = '';
            if (resp.data.customFields) {
                Object.keys(resp.data.customFields).forEach((key, index) => {
                    kvcontrols = kvcontrols + '<div class="row cf-row-' + index + '">' +
                        '<div class="col-3"><input type="text" class="form-control" name="' + key + '" value="' + key + '" placeholder="Field Name"/></div>' +
                        '<div class="col"><input type="text" class="form-control" name="' + key + '" value="' + resp.data.customFields[key] + '" placeholder="Field Value"  /></div>' +
                        '<div class="col-2"><button type="button" class="btn btn-danger btn-sm cf-row-remove" data-row-id="cf-row-' + index + '"><i class="fa fa-times fa-lg"></i></button></div>' +
                        '</div>';
                });
            }            
            kvcontrols = '<div class="card wrap-cf animated zoomIn"> <div class="wrap-sub-cf">' +
                '<div class="card-header">Custom Fields<button class="cf-close btn btn-sm float-right text-right"><i class="fa fa-times"></i></button></div>' +                
                '<div class="card-body">' +
                '<div class="card-title">Custome Fields associated with this company.</div>' +
                '<form method="POST" class="cf-form">' +
                '<div class="row"><div class="col-3"><strong>Field Name</strong></div><div class="col"><strong>Field Value</strong></div><div class="col-2"><strong>Action</strong></div></div>'+
                kvcontrols +
                '<div class="wrap-new-cf"></div>'+
                '<div class="row"><button type="button" class="btn btn-sm col new-cf"><i class="fa fa-plus"></i></button></div>'+
                '<button type="button" class="btn btn-success cf-save"><i class="fa fa-save"></i> Save</button>' +
                '</form>' +
                '</div>' +                
                '</div>'+
                '</div> </div>';
            if ($('.wrap-cf').length > 0) {
                $('.wrap-cf').html(kvcontrols);
            } else {
                $(document).find('body').append(kvcontrols);
            }
            $(".cf-row-remove").on("click", function () {
                $(window).trigger('cf-remove', $(this).attr('data-row-id'));
            });
            $(".cf-close").on("click", function () {
                $(document).find('.wrap-cf').remove();
            });
            $(document).find("wrap-cf.cf-remove").on("click", function () {
                $(document).find('wrap-cf.wrap-cf').html('');
            });
            $('.cf-save').on("click", function () {
                $('.cf-form').submit();
            });
            $('.cf-form').on('submit', function (e) {
                e.preventDefault();
                let data = $(this).serialize();
                saveCustomFields(cID, data, _route);
            });
            $('.new-cf').on('click', function () {
                let newID = Math.floor((Math.random() * 1000) + 1);
                $('.wrap-new-cf').append('<div class="row cf-row-' + newID + '">' +
                    '<div class="col-3"><input type="text" class="form-control" name="new-' + newID + '" placeholder="Field Name"/></div>' +
                    '<div class="col"><input type="text" class="form-control" name="new-' + newID + '" placeholder="Field Value"  /></div>' +
                    '<div class="col-2"><button type="button" class="btn btn-danger btn-sm cf-row-remove" data-row-id="cf-row-' + newID + '"><i class="fa fa-times fa-lg"></i></button></div>' +
                    '</div>');
                $(".cf-row-remove").on("click", function () {
                    $(window).trigger('cf-remove', [$(this).attr('data-row-id')]);                    
                });
            });
        }, 'json').fail(function () {
            CAMS.alert('Error', 'An unexpected error was encountered. Please try again.', 'error');
        });
    });
    $(window).on('cf-remove', function (e, id) {
        CAMS.confirm('Confirm', 'Are you sure that you want to remove the field name & value permanently?', (confirm) => {
            if (confirm === true) {
                $('.' + id).remove();
            }
        });        
    });
    $('#modal-company').on('click', '.delete-custom-fields', function () {
        CAMS.confirm('Confirm', 'Are you sure that you want to remove custom fields permanently?', (confirm) => {
            if (confirm === true) {
                saveCustomFields($(this).attr('data-id'), {}, $(this).attr('data-route'));
            }
        });        
    });
    function saveCustomFields(companyId, data, _route ='companies') {
        $.post('/'+_route + '/' + companyId + '/save/custom/fields', data, function (res) {
            if (res.error) { CAMS.alert('Error', res.error.msg, 'error'); }
            $('.cf-close').trigger('click');
            openCompanyDetails(companyId, _route);
        }, 'json').fail(function () {
            CAMS.alert('Error', 'An unexpected error was encountered. Please try again.', 'error');
        });
    }
});

Open in new window


When I do a search for CAMS in the codebase, I get nothing but similar references apart from the "cams.js" page. There I see something different. It looks like this:

var CAMSObj = function () {
    var self = this,
        activeForms = {},
        $slider, recordId;

    /* public properties */

    this.assignCompanyList = [];
    this.route = 'companies';

    this.googleAddressIndex = {};

    /* ################################################################### */
    /* Global method for opening up the company details view  */
    /* ################################################################### */

    this.showCompanyDetails = function (companyId, opts) {
        route = (typeof opts.route != 'undefined') ? opts.route : 'companies';
        var sWidth = (window.innerWidth > 550) ? 550 : window.innerWidth - 30,
            afterOpen = opts.afterOpen || function () { };

        recordId = companyId;
        route = (route == 'market/' || route == '/market/') ? 'market' : ((route == 'companies/' || route == '/companies/') ? 'companies' : route);
        $.get('/' + route + '/' + companyId, { ajax: 1 }, function (resp) {
            // add the content to the modal
            $('#modal-company').find('.slide-panel-content').empty().append(resp);

            // add the content scrollbar
            SimpleScrollbar.initEl($('#modal-company').find('.slide-panel-content')[0]);

            // enable tooltips
            $('#modal-company [data-toggle="tooltip"]').tooltip({
                container: $('#modal-company')
            });

            // show the slide panel
            $slider = $('<a href="modal-company" />').bigSlide({
                menu: '#modal-company',
                menuWidth: sWidth + 'px',
                easyClose: false,
                side: 'right',
                beforeOpen: function () {$('#modal-company').draggable();},
                afterOpen: afterOpen
            }).trigger('click');
            $('#modal-company').css("display", "block");
            
        }).fail(function () {
            alert('An unexpected error was encountered while trying to load your company record. Please refresh the page and try again.');
        });
    };

    this.closeCompanyDetails = function () {
        $slider.trigger('click');
    };


    /* ################################################################### */
    /* Global methods for adding activities to a company  */
    /* ################################################################### */


    this.addActivity = function (opts, onComplete) {
        var $el = $('div.activity-wrapper a');

        // add the options to it
        for (var k in opts) {
            $el.attr(k, opts[k]);
        }

        $.magnificPopup.open({
            alignTop: true,
            items: {
                type: 'inline',
                src: $('div.activity-wrapper')
            }
        });
    };

    this.showActivityForm = function (companyId, proposalId, type) {
        var model = objectModels[type],
            fc = model.singular.substring(0, 1),
            config = {
                title: 'Add a' + ((fc == 'a' || fc == 'e' || fc == 'i' || fc == 'o' || fc == 'u') ? 'n' : '') + ' ' + ucwords(model.singular),
                directionsText: 'Complete the form below to add a new ' + model.singular + '.',
                fields: model.fields,
                onShow: function (self) {
                    // add in the additional events and plugins
                    // add in datetime support
                    self.$el.find('input.field-datetime').datepicker({
                        autoClose: true,
                        language: 'en',
                        timepicker: true,
                        dateFormat: 'mm/dd/yyyy',
                        timeFormat: 'h:ii AA',
                        showEvent: 'focus',
                        minutesStep: 5
                    });

                },
                ajax: {
                    path: '/companies/add-activity',
                    params: {
                        company: companyId,
                        proposal: proposalId,
                        type: type,
                    },
                    onComplete: function (resp, self) {
                        if (resp.error) {
                            self.addMsg(resp.msg);
                            return false;
                        }
                        companyId = (companyId == 'bulk' ? resp.data.id : companyId);
                        recordId = companyId;
                        $(window).trigger('open-company-details', [companyId, ((typeof route != 'undefined') ? route : '/companies/'), 'history']);
                    }
                }
            };

        // show the form
        formIt.show(config);
    };


    /* ################################################################### */
    /* Global methods for (un)assigning a company(s) to a user  */
    /* ################################################################### */

    this.startAssignTo = function (companiesIdList, route, userId) {
        self.assignCompanyList = companiesIdList;
        self.route = route;

        $(window).trigger('select-user-show', [{ userId: userId, route: route }]);
    };

    /* ################################################################### */
    /* Global methods for building a select2 user and company elements  */
    /* ################################################################### */

    this.createCompanySelector = function ($select, $parentModal, _route, multiselect = false) {
        let routeUrl = ((typeof route != 'undefined') ? '/' + route + '/select2' : (typeof _route != 'undefined' ? '/' + _route + '/select2' : '/companies/select2'));
        routeUrl = routeUrl.replace('//', '/');
        var config = {
            multiple: multiselect,
            placeholder: 'Search for a company',
            minimumInputLength: 1,
            theme: 'bootstrap4',
            ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
                url: routeUrl,
                dataType: 'json',
                quietMillis: 250,
                delay: 250,
                data: function (term, page) {
                    return {
                        q: term,
                        p: page
                    };
                },
                processResults: function (data, params) {
                    // since we are using custom formatting functions we do not need to alter the remote JSON data
                    return { results: data };
                },
                cache: false
            }
        };

        if (typeof $parentModal != 'undefined') {
            config.dropdownParent = $parentModal
        }

        $select.select2(config);
    };
    /*
     * Products and Services Select 2
     */

    //this.createServiceModelSelector = function ($select, $parentModal) {
    //    var config = {
    //        multiple: false,//multiselect,            
    //        placeholder: 'Search for a model',
    //        minimumInputLength: 1,
    //        theme: 'bootstrap4',
    //        ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
    //            url: '/products-and-services/service-model/select2',
    //            dataType: 'json',
    //            quietMillis: 250,
    //            delay: 250,
    //            data: function (term, page) {
    //                return {
    //                    q: term,
    //                    p: page
    //                };
    //            },
    //            processResults: function (data, params) {
    //                // since we are using custom formatting functions we do not need to alter the remote JSON data
    //                return { results: data };
    //            },
    //            cache: false
    //        }
    //    };

    //    if (typeof $parentModal != 'undefined') {
    //        config.dropdownParent = $parentModal;
    //    }

    //    $select.select2(config).on('select2:open', () => {
    //        $(".select2-results:not(:has(a))").append('<a href="#" style="padding: 6px;height: 20px;display: inline-table;">Create new item</a>').on('click', function (b) {
    //            a.trigger('close');

    //            // add your code
    //        });
    //    });
    //};

    this.createUserSelector = function ($select, $parentModal) {
        var config = {
            placeholder: 'Search for an user',
            minimumInputLength: 1,
            theme: 'bootstrap4',
            ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
                url: '/users/select2',
                dataType: 'json',
                quietMillis: 250,
                delay: 250,
                data: function (term, page) {
                    return {
                        q: term,
                        p: page
                    };
                },
                processResults: function (data, params) {
                    // since we are using custom formatting functions we do not need to alter the remote JSON data
                    return { results: data };
                },
                cache: false
            }
        };

        if (typeof $parentModal != 'undefined') {
            config.dropdownParent = $parentModal
        }
        // Avatar append
        config.templateResult = formatState;
        config.templateSelection = formatState;

        $select.select2(config);

        // Avatar append
        function formatState(opt) {
            if (!opt.id) {
                return opt.text;
            }
            if (typeof opt.avatar != 'undefined') {
                if (opt.avatar.length > 0) {
                    return $('<span><img src="' + opt.avatar + '" width="23px" /> ' + opt.text + '</span>');
                } else {
                    if (!opt.image) {
                        return opt.text;
                    } else {
                        return $('<span><img src="' + opt.image + '" width="23px" /> ' + opt.text + '</span>');
                    }
                }                
            } else {
                if (!opt.image) {
                    return opt.text;
                } else {
                    return $('<span><img src="' + opt.image + '" width="23px" /> ' + opt.text + '</span>');
                }
            }
        }
    };

    this.serviceSelectorData = [];

    this.createServiceSelector = function ($select, $parentModal, multiselect = false) {
        var config = {
            multiple: multiselect,
            placeholder: 'Search for a service',
            // minimumInputLength: 1,
            minimumResultsForSearch: Infinity,
            theme: 'bootstrap4',
            ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
                url: '/settings/services/select2',
                dataType: 'json',
                quietMillis: 250,
                delay: 250,
                data: function (term, page) {
                    return {
                        q: term,
                        p: page
                    };
                },
                processResults: function (data, params) {
                    // set a cache of the results
                    self.serviceSelectorData = data;

                    // wrap it up for use
                    return { results: data };
                },
                cache: false
            }
        };

        if (typeof $parentModal != 'undefined') {
            config.dropdownParent = $parentModal
        }

        $select.select2(config);

        $select.on('change', function (e) {
            if (this.value === '') {
                return true;
            } else if (self.serviceSelectorData.length === 0) {
                return true;
            }

            for (var i in self.serviceSelectorData) {
                if (self.serviceSelectorData[i]._id == this.value) {
                    $(window).trigger('service-selector-changed', [this, self.serviceSelectorData[i]]);
                }
            }
        });
    };

    /* ################################################################### */
    /* General file upload methods */
    /* ################################################################### */

    this.createFileUploader = function ($el, opts) {
        var id = $el.attr('id') + '-file',
            $wrapper = $('#' + $el.attr('data-list-wrapper')),
            fieldName = opts.fieldName || '',
            onUpload = opts.onUpload || function (data) { };

        // add the enctype to the form
        $el.closest('form').attr('enctype', 'multipart/form-data');

        // create the file upload element
        $el.before('<input type="file" id="' + id + '" name="qqfile" value="" style="display:none;" />');

        $('#' + id).fileupload({
            url: '/upload',
            dataType: 'json',
            formData: {},
            maxFileSize: 10000000,
            submit: function (e, data) {
                var fid = md5(data.files[0].name),
                    html = '<tr data-file="' + fid + '">' +
                        '<td colspan="3"><span class="file-title">' + data.files[0].name + '</span><span class="file-progress">0%</span></td>' +
                        '</tr>';

                $wrapper.find('table tbody').append(html);
                $wrapper.show();
            },
            progress: function (e, data) {
                var fid = md5(data.files[0].name);

                $wrapper.find('table tbody tr[data-file="' + fid + '"] .file-progress').html(data.progressInterval.toFixed(0) + '%');
            },
            done: function (e, data) {
                var fid = md5(data.files[0].name),
                    file = data.result,
                    $tr = $wrapper.find('table tbody tr[data-file="' + fid + '"]'),
                    fields = '';

                file.date = moment().millisecond(file.date).format('MM/DD/YYYY hh:mm A');

                if (fieldName !== '') {
                    fields = '<input type="hidden" name="' + fieldName + '[' + file.key + '][key]" value="' + file.key + '">' +
                        '<input type="hidden" name="' + fieldName + '[' + file.key + '][url]" value="' + file.url + '">' +
                        '<input type="hidden" name="' + fieldName + '[' + file.key + '][name]" value="' + file.name + '">' +
                        '<input type="hidden" name="' + fieldName + '[' + file.key + '][date]" value="' + file.date + '">';
                }

                var html = '<td>' +
                    fields +
                    '<a href="' + file.url + '" target="_blank">' + file.name + '</a>' +
                    '</td>' +
                    '<td>' + file.date + '</td>' +
                    '<td class="text-right">' +
                    '<button type="button" class="btn btn-danger btn-sm delete-file"><i class="fas fa-fw fa-trash"></i></button>' +
                    '</td>';

                $tr.empty().append(html);

                onUpload(file);
            },
            fail: function (e, data) {
                var fid = md5(data.files[0].name);

                $wrapper.find('table tbody tr[data-file="' + fid + '"] .file-progress').html('Upload Failed');
                $wrapper.find('table tbody tr[data-file="' + fid + '"]').addClass('text-danger');
            }
        });

        $el.on('click', function () {
            $('#' + id).trigger('click');
        });

    };


    /* ################################################################### */
    /* General utility methods */
    /* ################################################################### */

    this.makeAddressSearch = function ($el, $parentModal) {
        var sessToken = '';

        var config = {
            placeholder: 'Search for an address or building',
            minimumInputLength: 1,
            theme: 'bootstrap4',
            ajax: {
                url: '/vendors/google/addresses',
                dataType: 'json',
                quietMillis: 250,
                delay: 250,
                data: function (q, page) {
                    return {
                        q: q.term,
                        sessionToken: sessToken,
                        p: page
                    };
                },
                processResults: function (data, params) {
                    self.googleAddressIndex = data.index;

                    return { results: data.results };
                },
                cache: false
            }
        };

        if (typeof $parentModal != 'undefined') {
            config.dropdownParent = $parentModal
        }

        $el.select2(config);
    };


    /* ################################################################### */
    /* General utility methods */
    /* ################################################################### */

    this.getAJAXRoute = function () {
        switch (true) {
            case (/^\/companies(?:\/.*)?/.test(window.location.pathname)):
                return '/companies';
                break;

            case (/^\/market(?:\/.*)?/.test(window.location.pathname)):
                return '/market';
                break;

            default:
                return false;
                break;
        }
    };


    /* ################################################################### */
    /* SweetAlert2 methods */
    /* ################################################################### */


    this.alert = function (title, msg, type, callback) {
        swal({
            title: title,
            text: msg,
            html:msg,
            type: type || 'info'
        }).then(function () {
            if (typeof callback == 'function') {
                callback(true);
            }
        }, function (dismiss) {
            if (typeof callback == 'function') {
                callback(false);
            }
        });
    };

    this.confirm = function (title, msg, callback) {
        swal({
            title: title,
            text: msg,
            html: msg,
            type: 'warning',
            showCancelButton: true,
            confirmButtonColor: '#DD6B55',
            confirmButtonText: 'Confirm'
        }).then(function (resp) {
            if (typeof callback == 'function') {
                if (resp.value) {
                    callback(true);
                } else {
                    callback(false);
                }
            }
        }, function (dismiss) {
            if (typeof callback == 'function') {
                callback(false);
            }
        });
    };

    this.prompt = function (title, msg, callback, opts) {
        var config = $.extend({}, {
            title: title,
            text: msg,
            html: msg,
            //type: 'info',
            input: 'text',
            showCancelButton: true,
            animation: 'slide-from-top',
            inputPlaceholder: '',
            allowOutsideClick: false,
            allowEscapeKey: false,
            inputValidator: function (val) {
                return new Promise(function (resolve, reject) {
                    if (typeof val != 'string' || val === '') {
                        reject('Please enter a valid value.');
                    } else {
                        resolve();
                    }
                });
            }
        }, opts);

        swal(config).then(function (input) {
            if (typeof callback == 'function') {
                if (typeof input.dismiss == 'undefined') {
                    callback(input);
                }
            }
        }, function (dismiss) {
            if (typeof callback == 'function') {
                callback(false);
            }
        });
    };

};

var CAMS, formIt, heatMap;

$(document).ready(function () {

    CAMS = new CAMSObj();
    formIt = new FormIt();
    if (typeof heatMapObj != 'undefined') {
        heatMap = new heatMapObj();
    }
    

    $(document).on('change', 'input[type="checkbox"].table-all', function () {
        var $t = $(this).closest('table'),
            checked = $(this).prop('checked');

        $t.find('input[type="checkbox"]').prop('checked', checked);
    });

    $(document).on('click', '.activity-wrapper a.assign-to', function () {
        var id = $(this).attr('data-id'),
            userId = $(this).attr('data-user-id');
        if (typeof id == 'undefined') {
            id = $(this).attr('data-company-id');
        }
        route = $(this).attr('data-route');

        CAMS.startAssignTo([id], route, userId);
    });

    $(document).on('click', '.add-proposal, .open-proposal-details', function () {
        var $this = $(this),
            id = (typeof $this.attr('data-proposal-id') != 'undefined') ? $this.attr('data-proposal-id') : 'new',
            opts = {};
        route = (typeof $this.attr('data-route') != 'undefined') ? $this.attr('data-route') + "/" : 'companies/';

        // if the add proposal link was clicked, we do not want it to load an
        // existing proposal record
        if ($this.hasClass('add-proposal')) {
            id = 'new';
        }

        if (typeof $this.attr('data-company-id') != 'undefined') {
            opts.company = {
                id: $this.attr('data-company-id'),
                name: $this.attr('data-company-name'),
                clientMessage: $this.attr('data-company-clientMessage')                
            };
            opts.company.meta = {};
            opts.company.meta.ftes = $this.attr('data-company-meta-ftes');
        }

        // if a status is provided with the link, then we want to pre-select the status
        if (typeof $this.attr('data-proposal-pipeline') != 'undefined') {
            opts.pipeline = $this.attr('data-proposal-pipeline');
        }

        $(window).trigger('proposal-form-show', [id, opts]);
    });

    $(document).on('click', '.delete-proposal', function () {
        var $this = $(this),
            id = (typeof $this.attr('data-proposal-id') != 'undefined') ? $this.attr('data-proposal-id') : '';
        CAMS.confirm('Are You Sure?', 'Are you sure you want to delete the selected proposal? This will remove all associated activity, files and services', function (result) {
            if (!result) {
                return false;
            }
            $.post('/companies/proposal/delete/' + id, function (resp) {
                if (resp.error) {
                    CAMS.alert('Error', resp.msg, 'error');
                    return false;
                }
                CAMS.alert('Success', 'Your proposal has been deleted successfully');
                $this.parents('.card').remove();
            }, 'json').fail(function () {
                CAMS.alert('Unexpected Error', 'We encountered an unexpected error while trying to process your request.', 'error');
            });
        });
    });
    $(document).on('click', '#btn-delete', function () {
        let data = { companies: [$(this).attr('data-prospect-id')] };
        CAMS.confirm('Are You Sure?', 'You want to delete the selected company from your account? This will remove all associated proposals, activities, files', function (result) {
            if (!result) {
                return false;
            }
            $.post('/companies/delete',data, function (resp) {
                if (resp.error) {
                    CAMS.alert('Error', resp.msg, 'error');
                    return false;
                }
                CAMS.alert('Success', 'Company has been deleted from your account successfully. Please refersh the page to update the view.');                
            }, 'json').fail(function () {
                CAMS.alert('Unexpected Error', 'We encountered an unexpected error while trying to process your request.', 'error');
            });
        });
    });

    $(document).on('click', '.company-add-activity[data-company-id]', function () {
        var $this = $(this),
            opts = {
                'data-company-id': ((typeof $this.attr('data-company-id')) != 'undefined' ? $this.attr('data-company-id') : $this.attr('data-prospect-id')),
                'data-company-name': $this.attr('data-company-name'),
                'data-proposal-id': $this.attr('data-proposal-id'),
                'data-route': $this.attr('data-route')
            };

        if (typeof opts['data-company-id'] == 'undefined') {
            CAMS.alert('Invalid Link', 'The selected link is not properly formatted. Please refresh the page or contact support.', 'error');
        }

        if (typeof $this.attr('data-proposal-pipeline') != 'undefined') {
            opts['data-proposal-pipeline'] = $this.attr('data-proposal-pipeline');
        }

        CAMS.addActivity(opts);
    });
    $(document).on('click', '.add-activity-bulk', function () {
        var $this = $(this),
            opts = {
                'data-company-id': 'bulk',
                'data-company-name': 'bulk',
                'data-proposal-id': 'bulk',
                'data-route': $this.attr('data-route')
            };

        CAMS.addActivity(opts);
    });

    $(document).on('click', '.activity-wrapper a.activity-link', function () {
        var cId = $(this).attr('data-company-id'),
            pId = $(this).attr('data-proposal-id'),
            type = $(this).attr('data-activity-type');
        route = ((typeof $(this).attr('data-route') == 'undefined') ? route : $(this).attr('data-route'));


        if (typeof cId == 'undefined' || typeof type == 'undefined') {
            CAMS.alert('Invalid Link', 'The selected link is not properly formatted. Please refresh the page or contact support.', 'error');
        }

        CAMS.showActivityForm(cId, pId, type);
        // Engage / Add Activity for filtered or bulk dataset
        $companySelect = $(document).find('select[name="company"].select2');
        if (typeof $companySelect != 'undefined') {
            if ($companySelect.length > 0) {
                if (cId == 'bulk') {
                    // add the select2 elements
                    CAMS.createCompanySelector($companySelect);
                    // check for a company id in the opts
                    var _company = pickedList_s();
                    if (typeof _company != 'undefined') {
                        if (Array.isArray(_company)) {
                            _company.forEach((item) => {
                                $companySelect.append('<option value="' + item.id + '" selected="selected">' + item.name + '</option>').trigger('change');
                            });
                        }
                    }
                } else {
                    $companySelect.closest('.form-group').remove();
                }
            }
        }
    });
    /*
     This method for multi select2 company dropdown.
     */
    function pickedList_s() {
        let _list = [];
        $(document).find('.table-cb:checked').each(function (i) {
            _list.push({ id: this.value, name: $(this).attr('data-text') });
        });
        return (_list);
    }
    $(window).on('select-user-complete', function (e, user) {
        $.post((route ? (route == 'market' ? '/market' : (route == 'companies' ? '/companies' : route)) + '/assign' : '/companies/assign'), { user: user._id, companies: CAMS.assignCompanyList }, function (resp) {
            if (resp.error) {
                CAMS.alert('Error', resp.msg, 'error');
                return false;
            }

            var msg = CAMS.assignCompanyList.length == 1 ? 'company was' : 'companies were';

            CAMS.alert('Success', 'Your ' + msg + ' successfully assigned to ' + user.firstName + '.', 'success');

            $(window).trigger('select-user-post-complete', [user]);
        }, 'json').fail(function () {
            CAMS.alert('Error', 'An unexpected error was encountered while trying to save your company assignments. Please refresh the page and try again.', 'error');
        });
    });

    $(document).on('click', '.user-info[data-user-id]', function () {
        var userId = $(this).attr('data-user-id');

        if (!userId) {
            return false;
        }

        $(window).trigger('user-info-show', [userId]);
    });


    $(document).on('change', '.service-model', function () {
        let $this = $(this),
            service_model_before = $this.data('pre');
        if ($this.find(':selected').val() == 'new') {
            $this.hide();

            let serviceModelForm = $('<div class="animated zoomIn service-model-wrapper" >' +
                '<div class="input-group">' +
                '<input type="text" name="service-model-new" id="service-model-new" placeholder="Enter new model name" class="form-control border-right-0" />' +
                '<div class="input-group-btn border bg-white border-left-0">' +
                '<button class="btn btn-sm btn-success service-model-form" type="button"><i class="fa fa-check fa-lg"></i></button>' +
                '<button class="btn btn-sm btn-danger service-model-cancel" type="button" title="Cancel"><i class="fa fa-times fa-lg"></i></button>' +
                '</div>' +
                '</div>' +
                '</div>');
            $this.after(serviceModelForm);
            $('.service-model-form').on('click', function (e) {
                e.preventDefault();
                let _name = $('#service-model-new').val();
                if (typeof _name != 'undefined') {
                    let formData = { name: toCamelCase(_name.trim()), key: toCamelCase(_name.trim()).replace(/ /g, '') };
                    $.post('/products-and-services/service-model', { data: formData }, function (resp) {
                        if (resp.error) {
                            CAMS.alert('Error', resp.msg, 'error');
                            return false;
                        }
                        let _newOption = '<option value="' + formData.key + '">' + formData.name + '</option>';
                        $('.service-model').each(function () {
                            $(this).append(_newOption);
                        });
                        $this.val(formData.key);
                        $this.show();
                        $(serviceModelForm).remove();
                        CAMS.alert('Success', 'New service model (Bill As) successfully added.', 'success');
                    }, 'json').fail(function () {
                        CAMS.alert('Error', 'An unexpected error was encountered while trying to save your service model (Bill As). Please refresh the page and try again.', 'error');
                    });
                } else {
                    CAMS.alert('Error', 'Please enter a text and try again.', 'error');
                }
            });
            $this.next().find('input').focus();
            $('.service-model-cancel').on('click', function () {
                $('.service-model-wrapper').remove();
                $this.val(service_model_before);
                $this.show();
            });
        }
    });


});


/* ################################################################### */
/* Global UTILITY functions/methods */
/* ################################################################### */

// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
if (!Array.isArray) {
    Array.isArray = function (arg) {
        return Object.prototype.toString.call(arg) === '[object Array]';
    };
}

// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
    Object.keys = (function () {
        'use strict';
        var hasOwnProperty = Object.prototype.hasOwnProperty,
            hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
            dontEnums = [
                'toString',
                'toLocaleString',
                'valueOf',
                'hasOwnProperty',
                'isPrototypeOf',
                'propertyIsEnumerable',
                'constructor'
            ],
            dontEnumsLength = dontEnums.length;

        return function (obj) {
            if (typeof obj !== 'function' && (typeof obj !== 'object' || obj === null)) {
                throw new TypeError('Object.keys called on non-object');
            }

            var result = [], prop, i;

            for (prop in obj) {
                if (hasOwnProperty.call(obj, prop)) {
                    result.push(prop);
                }
            }

            if (hasDontEnumBug) {
                for (i = 0; i < dontEnumsLength; i++) {
                    if (hasOwnProperty.call(obj, dontEnums[i])) {
                        result.push(dontEnums[i]);
                    }
                }
            }
            return result;
        };
    }());
}

function escapeHtml(unsafe) {
    if (typeof unsafe != 'undefined') {
        return unsafe
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }
}

function toCamelCase(str) {
    return str.replace(/(?:^|\s)\w/g, function (match) {
        return match.toUpperCase();
    });
}

function ucwords(str) {
    //  discuss at: http://locutus.io/php/ucwords/
    // original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // improved by: Waldo Malqui Silva (http://waldo.malqui.info)
    // improved by: Robin
    // improved by: Kevin van Zonneveld (http://kvz.io)
    // bugfixed by: Onno Marsman (https://twitter.com/onnomarsman)
    // bugfixed by: Cetvertacov Alexandr (https://github.com/cetver)
    //    input by: James (http://www.james-bell.co.uk/)
    //   example 1: ucwords('kevin van  zonneveld')
    //   returns 1: 'Kevin Van  Zonneveld'
    //   example 2: ucwords('HELLO WORLD')
    //   returns 2: 'HELLO WORLD'
    //   example 3: ucwords('у мэри был маленький ягненок и она его очень любила')
    //   returns 3: 'У Мэри Был Маленький Ягненок И Она Его Очень Любила'
    //   example 4: ucwords('τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός')
    //   returns 4: 'Τάχιστη Αλώπηξ Βαφής Ψημένη Γη, Δρασκελίζει Υπέρ Νωθρού Κυνός'

    return (str + '')
        .replace(/^(.)|\s+(.)/g, function ($1) {
            return $1.toUpperCase()
        })
}

function number_format(number, decimals, decPoint, thousandsSep) { // eslint-disable-line camelcase
    //  discuss at: http://locutus.io/php/number_format/
    // original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // improved by: Kevin van Zonneveld (http://kvz.io)
    // improved by: davook
    // improved by: Brett Zamir (http://brett-zamir.me)
    // improved by: Brett Zamir (http://brett-zamir.me)
    // improved by: Theriault (https://github.com/Theriault)
    // improved by: Kevin van Zonneveld (http://kvz.io)
    // bugfixed by: Michael White (http://getsprink.com)
    // bugfixed by: Benjamin Lupton
    // bugfixed by: Allan Jensen (http://www.winternet.no)
    // bugfixed by: Howard Yeend
    // bugfixed by: Diogo Resende
    // bugfixed by: Rival
    // bugfixed by: Brett Zamir (http://brett-zamir.me)
    //  revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    //  revised by: Luke Smith (http://lucassmith.name)
    //    input by: Kheang Hok Chin (http://www.distantia.ca/)
    //    input by: Jay Klehr
    //    input by: Amir Habibi (http://www.residence-mixte.com/)
    //    input by: Amirouche
    //   example 1: number_format(1234.56)
    //   returns 1: '1,235'
    //   example 2: number_format(1234.56, 2, ',', ' ')
    //   returns 2: '1 234,56'
    //   example 3: number_format(1234.5678, 2, '.', '')
    //   returns 3: '1234.57'
    //   example 4: number_format(67, 2, ',', '.')
    //   returns 4: '67,00'
    //   example 5: number_format(1000)
    //   returns 5: '1,000'
    //   example 6: number_format(67.311, 2)
    //   returns 6: '67.31'
    //   example 7: number_format(1000.55, 1)
    //   returns 7: '1,000.6'
    //   example 8: number_format(67000, 5, ',', '.')
    //   returns 8: '67.000,00000'
    //   example 9: number_format(0.9, 0)
    //   returns 9: '1'
    //  example 10: number_format('1.20', 2)
    //  returns 10: '1.20'
    //  example 11: number_format('1.20', 4)
    //  returns 11: '1.2000'
    //  example 12: number_format('1.2000', 3)
    //  returns 12: '1.200'
    //  example 13: number_format('1 000,50', 2, '.', ' ')
    //  returns 13: '100 050.00'
    //  example 14: number_format(1e-8, 8, '.', '')
    //  returns 14: '0.00000001'

    number = (number + '').replace(/[^0-9+\-Ee.]/g, '')
    var n = !isFinite(+number) ? 0 : +number
    var prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
    var sep = (typeof thousandsSep === 'undefined') ? ',' : thousandsSep
    var dec = (typeof decPoint === 'undefined') ? '.' : decPoint
    var s = ''

    var toFixedFix = function (n, prec) {
        var k = Math.pow(10, prec)
        return '' + (Math.round(n * k) / k)
            .toFixed(prec)
    }

    // @todo: for IE parseFloat(0.55).toFixed(0) = 0;
    s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.')
    if (s[0].length > 3) {
        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep)
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || ''
        s[1] += new Array(prec - s[1].length + 1).join('0')
    }

    return s.join(dec)
}

// md5
!function (n) { "use strict"; function t(n, t) { var r = (65535 & n) + (65535 & t); return (n >> 16) + (t >> 16) + (r >> 16) << 16 | 65535 & r } function r(n, t) { return n << t | n >>> 32 - t } function e(n, e, o, u, c, f) { return t(r(t(t(e, n), t(u, f)), c), o) } function o(n, t, r, o, u, c, f) { return e(t & r | ~t & o, n, t, u, c, f) } function u(n, t, r, o, u, c, f) { return e(t & o | r & ~o, n, t, u, c, f) } function c(n, t, r, o, u, c, f) { return e(t ^ r ^ o, n, t, u, c, f) } function f(n, t, r, o, u, c, f) { return e(r ^ (t | ~o), n, t, u, c, f) } function i(n, r) { n[r >> 5] |= 128 << r % 32, n[14 + (r + 64 >>> 9 << 4)] = r; var e, i, a, d, h, l = 1732584193, g = -271733879, v = -1732584194, m = 271733878; for (e = 0; e < n.length; e += 16)i = l, a = g, d = v, h = m, g = f(g = f(g = f(g = f(g = c(g = c(g = c(g = c(g = u(g = u(g = u(g = u(g = o(g = o(g = o(g = o(g, v = o(v, m = o(m, l = o(l, g, v, m, n[e], 7, -680876936), g, v, n[e + 1], 12, -389564586), l, g, n[e + 2], 17, 606105819), m, l, n[e + 3], 22, -1044525330), v = o(v, m = o(m, l = o(l, g, v, m, n[e + 4], 7, -176418897), g, v, n[e + 5], 12, 1200080426), l, g, n[e + 6], 17, -1473231341), m, l, n[e + 7], 22, -45705983), v = o(v, m = o(m, l = o(l, g, v, m, n[e + 8], 7, 1770035416), g, v, n[e + 9], 12, -1958414417), l, g, n[e + 10], 17, -42063), m, l, n[e + 11], 22, -1990404162), v = o(v, m = o(m, l = o(l, g, v, m, n[e + 12], 7, 1804603682), g, v, n[e + 13], 12, -40341101), l, g, n[e + 14], 17, -1502002290), m, l, n[e + 15], 22, 1236535329), v = u(v, m = u(m, l = u(l, g, v, m, n[e + 1], 5, -165796510), g, v, n[e + 6], 9, -1069501632), l, g, n[e + 11], 14, 643717713), m, l, n[e], 20, -373897302), v = u(v, m = u(m, l = u(l, g, v, m, n[e + 5], 5, -701558691), g, v, n[e + 10], 9, 38016083), l, g, n[e + 15], 14, -660478335), m, l, n[e + 4], 20, -405537848), v = u(v, m = u(m, l = u(l, g, v, m, n[e + 9], 5, 568446438), g, v, n[e + 14], 9, -1019803690), l, g, n[e + 3], 14, -187363961), m, l, n[e + 8], 20, 1163531501), v = u(v, m = u(m, l = u(l, g, v, m, n[e + 13], 5, -1444681467), g, v, n[e + 2], 9, -51403784), l, g, n[e + 7], 14, 1735328473), m, l, n[e + 12], 20, -1926607734), v = c(v, m = c(m, l = c(l, g, v, m, n[e + 5], 4, -378558), g, v, n[e + 8], 11, -2022574463), l, g, n[e + 11], 16, 1839030562), m, l, n[e + 14], 23, -35309556), v = c(v, m = c(m, l = c(l, g, v, m, n[e + 1], 4, -1530992060), g, v, n[e + 4], 11, 1272893353), l, g, n[e + 7], 16, -155497632), m, l, n[e + 10], 23, -1094730640), v = c(v, m = c(m, l = c(l, g, v, m, n[e + 13], 4, 681279174), g, v, n[e], 11, -358537222), l, g, n[e + 3], 16, -722521979), m, l, n[e + 6], 23, 76029189), v = c(v, m = c(m, l = c(l, g, v, m, n[e + 9], 4, -640364487), g, v, n[e + 12], 11, -421815835), l, g, n[e + 15], 16, 530742520), m, l, n[e + 2], 23, -995338651), v = f(v, m = f(m, l = f(l, g, v, m, n[e], 6, -198630844), g, v, n[e + 7], 10, 1126891415), l, g, n[e + 14], 15, -1416354905), m, l, n[e + 5], 21, -57434055), v = f(v, m = f(m, l = f(l, g, v, m, n[e + 12], 6, 1700485571), g, v, n[e + 3], 10, -1894986606), l, g, n[e + 10], 15, -1051523), m, l, n[e + 1], 21, -2054922799), v = f(v, m = f(m, l = f(l, g, v, m, n[e + 8], 6, 1873313359), g, v, n[e + 15], 10, -30611744), l, g, n[e + 6], 15, -1560198380), m, l, n[e + 13], 21, 1309151649), v = f(v, m = f(m, l = f(l, g, v, m, n[e + 4], 6, -145523070), g, v, n[e + 11], 10, -1120210379), l, g, n[e + 2], 15, 718787259), m, l, n[e + 9], 21, -343485551), l = t(l, i), g = t(g, a), v = t(v, d), m = t(m, h); return [l, g, v, m] } function a(n) { var t, r = "", e = 32 * n.length; for (t = 0; t < e; t += 8)r += String.fromCharCode(n[t >> 5] >>> t % 32 & 255); return r } function d(n) { var t, r = []; for (r[(n.length >> 2) - 1] = void 0, t = 0; t < r.length; t += 1)r[t] = 0; var e = 8 * n.length; for (t = 0; t < e; t += 8)r[t >> 5] |= (255 & n.charCodeAt(t / 8)) << t % 32; return r } function h(n) { return a(i(d(n), 8 * n.length)) } function l(n, t) { var r, e, o = d(n), u = [], c = []; for (u[15] = c[15] = void 0, o.length > 16 && (o = i(o, 8 * n.length)), r = 0; r < 16; r += 1)u[r] = 909522486 ^ o[r], c[r] = 1549556828 ^ o[r]; return e = i(u.concat(d(t)), 512 + 8 * t.length), a(i(c.concat(e), 640)) } function g(n) { var t, r, e = ""; for (r = 0; r < n.length; r += 1)t = n.charCodeAt(r), e += "0123456789abcdef".charAt(t >>> 4 & 15) + "0123456789abcdef".charAt(15 & t); return e } function v(n) { return unescape(encodeURIComponent(n)) } function m(n) { return h(v(n)) } function p(n) { return g(m(n)) } function s(n, t) { return l(v(n), v(t)) } function C(n, t) { return g(s(n, t)) } function A(n, t, r) { return t ? r ? s(t, n) : C(t, n) : r ? m(n) : p(n) } "function" == typeof define && define.amd ? define(function () { return A }) : "object" == typeof module && module.exports ? module.exports = A : n.md5 = A }(this);


$(document).ready(function () {
    // Custom function which toggles between sticky class (is-sticky)
    var stickyToggle = function (sticky, stickyWrapper, scrollElement) {
        var stickyHeight = sticky.outerHeight();
        var stickyTop = stickyWrapper.offset().top;
        if (scrollElement.scrollTop() >= stickyTop) {
            stickyWrapper.height(stickyHeight);
            sticky.addClass("is-sticky");
        }
        else {
            sticky.removeClass("is-sticky");
            stickyWrapper.height('auto');
        }
    };

    // Find all data-toggle="sticky-onscroll" elements
    $('[data-toggle="sticky-onscroll"]').each(function () {
        var sticky = $(this);
        var stickyWrapper = $('<div>').addClass('sticky-wrapper'); // insert hidden element to maintain actual top offset on page
        sticky.before(stickyWrapper);
        sticky.addClass('sticky');

        // Scroll & resize events
        $(window).on('scroll.sticky-onscroll resize.sticky-onscroll', function () {
            stickyToggle(sticky, stickyWrapper, $(this));
        });

        // On page load
        stickyToggle(sticky, stickyWrapper, $(window));
    });
});

$(document).on('click.bs.dropdown.data-api', '.dropdown.keep-inside-clicks-open', function (e) {
    e.stopPropagation();
  });

Open in new window


My question is: What is CAMS? Is it a global variable? I'm expecting something like CAMS= as opposed to var CAMSObj = function () {

What am I missing? What is CAMS?
SOLUTION
Avatar of Albert Van Halen
Albert Van Halen
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Bruce Gust

ASKER

I should've known to look further. I saw, "CAMSObj" and assumed that was the bottom line.

Thanks!