<a href="#" style="float:right;"><i class="fas fa-fw fa-trash"></i></a><a href="#" class="note-link" data-prospect-id="{{ data._id }}" data-route="companies" data-company-name="{{ data.name|e('html_attr') }}" data-user-id="{{ (data.owner is empty?'undefined':data.owner._id) }}" data-toggle="tooltip" title="Edit Activity" data-activity-type="note" data-activityId={{ activity._id }}" style="float:right;"><i class="fas fa-fw fa-pencil fa-pencil-alt"></i></a>
$(document).on('click', '.note-link', function () {
console.log("boom");
var id = (typeof $(this).attr('data-company-id') != 'undefined') ? $(this).attr('data-company-id') : $(this).attr('data-prospect-id');
//var cId = $(this).attr('data-company-id'),
var cId = 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.showActivityForm = function (companyId, proposalId, type) {
console.log(type);
[b]var model = objectModels[type],[/b]
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
[b] formIt.show(config);[/b]
};
note: {
singular: 'note/reminder',
plural: 'note/reminders',
fields: {
activityType: {
type: 'string',
required: true,
[b]options: {'call': 'Call Note', 'visit': 'Visit Note', 'reminder': 'Reminder'}[/b]
},
date: {
type: 'datetime',
required: true
},
notes: {
type: 'string',
required: true,
multiline: true
},
company: {
type: 'id',
required: true,
lookup: 'companies',
display: '{{ name }}',
class: 'select2'
}
}
},
'use strict';
function FormIt(options) {
// Create the defaults we will extend
this.defaults = {
fields: {},
title: 'New Form',
directionsText: 'Complete the form below.',
directionsClass: 'lead',
containerClass: 'mfp-hide white-popup white-popup-md',
submitButtonText: '<i class="fas fa-fw fa-check"></i> Save',
submitButtonClass: 'btn btn-success',
cancelButtonText: 'Cancel',
cancelButtonClass: 'btn btn-link',
loadDataFromUrl: '',
onShow: function(self){},
onDataReceived: function(data, self){ return data; },
onDataLoaded: function(data, self){},
onValid: function(data, self){},
onSubmit: function(data, self){}
};
// create a new form uniq id
this.formId = this._uniqid();
// establish the opts that will be used
this.opts = {};
this.$el;
}
FormIt.prototype.init = function() {
// create the base container to use
var html = '<div id="formit-' + this.formId + '" class="' + this.opts.containerClass + '">' +
'<h3>' + this.opts.title + '</h3>' +
'<hr />' +
'<p class="' + this.opts.directionsClass + '">' + this.opts.directionsText + '</p>' +
'<div class="formit-errors"></div>' +
'<div class="loading">' +
'<h3 class="text-center"><i class="fas fa-fw fa-cog fa-spin"></i> Loading...</h3>' +
'</div>' +
'<form class="needs-validation d-none" novalidate>' +
'<div class="field-list"></div>' +
'<hr />' +
'<div class="buttons-footer">' +
'<button type="submit" class="btn-formit-submit ' + this.opts.submitButtonClass + '">' + this.opts.submitButtonText + '</button>' +
'<button type="button" class="btn-formit-cancel ' + this.opts.cancelButtonClass + '">' + this.opts.cancelButtonText + '</button>' +
'</div>' +
'</form>' +
'</div>';
if ($('#formit-' + this.formId).length === 0) {
$('body').append(html);
} else {
$('#formit-' + this.formId).replaceWith(html);
}
this.$el = $('#formit-' + this.formId);
// add in the events
this._addEvents();
};
FormIt.prototype.show = function(opts) {
// create the instance specific options
this.opts = $.extend({}, this.defaults, opts);
// ensure there are fields for the form
if ( this._getObjectKeys(this.opts.fields).length === 0 ) {
throw 'Invalid fields option provided.';
}
// delete any existing form
$('div[id^="formit-"]').remove();
// create the base form
this.init();
// build the html form
this._buildForm();
// open the form
$.magnificPopup.open({
alignTop: true,
items: {
type: 'inline',
src: this.$el
}
});
// hide the loading screen if we do not need to load any external data
if (this.opts.loadDataFromUrl === '') {
this.hideLoading();
this.opts.onDataLoaded({}, this);
} else {
this.loadData();
}
// call the callback
if (typeof this.opts.onShow == 'function') {
this.opts.onShow(this);
}
};
FormIt.prototype.close = function() {
$.magnificPopup.close();
};
FormIt.prototype.getData = function() {
var data = {},
fields = this.$el.find('form').serializeArray();
for (var i in fields) {
data[ fields[i].name ] = fields[i].value;
}
return data;
};
FormIt.prototype.loadData = function() {
// set a local reference to the object for inside the ajax callback
var self = this;
// show the loading screen
this.showLoading();
// look up the data
$.get(this.opts.loadDataFromUrl, {}, function(resp){
if (resp.error) {
self.close();
return CAMS.alert('Oh no!', resp.msg, 'error');
}
// set a reference
var data = (typeof resp.data.rows != 'undefined') ? resp.data.rows[0] : resp.data;
// call a lifecycle method
data = self.opts.onDataReceived(data, this);
// stop on false
if (!data) {
return self.close();
}
// load the form
self._loadDataIntoForm(data);
// show the form
self.hideLoading();
}, 'json').fail(function(){
self.close();
CAMS.alert('Oh no!', 'An unexpected error was encountered while trying to load your data. Please try again.', 'error');
});
};
FormIt.prototype.reset = function(options) {
};
FormIt.prototype.addMsg = function(msg, type) {
type = type || 'danger';
this.clearMsg();
this.$el.find('.formit-errors').append('<p class="alert alert-'+type+'">'+msg+'</p>');
};
FormIt.prototype.clearMsg = function() {
this.$el.find('.formit-errors').empty();
};
FormIt.prototype.hideLoading = function() {
this.$el.find('.loading').addClass('d-none');
this.$el.find('form').removeClass('d-none');
};
FormIt.prototype.showLoading = function() {
this.$el.find('form').addClass('d-none');
this.$el.find('.loading').removeClass('d-none');
};
FormIt.prototype._addEvents = function() {
var self = this;
// add in the submission form
this.$el.on('submit', 'form', function(e){
var $f = $(this);
e.preventDefault();
e.stopPropagation();
$f.addClass('was-validated');
if ($f[0].checkValidity() === false) {
self.addMsg('Please check the highlighted fields.');
return false;
}
self.clearMsg();
var data = self.getData(),
resp;
if (typeof self.opts.onValid == 'function') {
resp = self.opts.onValid(data, self);
if (resp === false) {
return false;
}
}
if (typeof self.opts.onSubmit == 'function') {
resp = self.opts.onSubmit(data, self);
if (resp === false) {
return false;
}
}
if (typeof self.opts.ajax == 'undefined') {
self.close();
}
self._ajax();
});
this.$el.on('click', 'button.btn-formit-cancel', function(){
self.close();
});
};
FormIt.prototype._ajax = function() {
if (typeof this.opts.ajax.path == 'undefined' || this.opts.ajax.path === '') {
throw 'Invalid or missing ajax.path value.';
}
var self = this,
$btn = this.$el.find('button[type="submit"]'),
btnText = $btn.html(),
params = (typeof this.opts.ajax.params != 'undefined') ? '&' + this._serialize(this.opts.ajax.params) : '',
data = this.$el.find('form').serialize() + params;
$btn.html('<i class="fas fa-fw fa-spinner-third fa-spin"></i> Processing...');
$.post(this.opts.ajax.path, data, function(resp){
if (typeof self.opts.ajax.onComplete == 'function') {
var check = self.opts.ajax.onComplete(resp, self);
if (check === false) {
return false;
}
}
self.close();
}, 'json').fail(function(){
if (typeof self.opts.ajax.onError == 'function') {
self.opts.ajax.onError(self);
}
}).always(function(){
$btn.html(btnText)
});
};
FormIt.prototype._buildForm = function() {
var fields = [];
for (var fid in this.opts.fields) {
fields.push( this._createField(fid, this.opts.fields[fid]) );
}
this.$el.find('form .field-list').empty().append( fields.join('') );
};
FormIt.prototype._getObjectKeys = function(obj) {
var keys = [];
for (var k in obj) {
keys.push(k);
}
return keys;
}
FormIt.prototype._loadDataIntoForm = function(data) {
var $field, model;
for (var fid in data) {
// load the field
$field = $('#formit-' + fid);
if ($field.length === 0) {
continue;
}
// look for the field model
model = this.opts.fields[fid];
// load the value based on the type of field
switch (true) {
// look for a select2
case (typeof model.lookup != 'undefined'):
if (typeof data[fid] == 'object' && typeof data[fid]._id != 'undefined') {
$field.empty().append('<option value="'+data[fid]._id+'">'+data[fid].text+'</option>');
}
break;
default:
$field.val( data[fid] );
break;
}
}
// call the loaded lifecycle method
this.opts.onDataLoaded(data, this);
};
FormIt.prototype._createField = function(fid, field) {
var name = field.name || fid,
label = field.label || this._fieldLabelFromId(fid),
placeholder = field.placeholder || label,
classes = field.class || '',
help = field.help || '',
input = '';
switch (true) {
// static text
case (field.type == 'static'):
var htmlType = field.htmlType || 'p';
return '<' + htmlType + ' class="' + classes + '">' + label + '</' + htmlType + '>';
break;
// check for a select2
case (typeof field.lookup != 'undefined'):
input = '<select id="formit-' + fid + '" name="' + name + '" class="form-control ' + classes + '"' + ((field.required) ? ' required' : '') + '></select>';
break;
// multiline string = textarea
case (field.type == 'string' && typeof field.multiline != 'undefined' && field.multiline):
input = '<textarea id="formit-' + fid + '" name="' + name + '" placeholder="' + placeholder + '" class="form-control ' + classes + '"' + ((field.required) ? ' required' : '') + '></textarea>';
break;
// string with contacts is a select2 calling the contacts of the associated company
case (field.type == 'string' && typeof field.contacts != 'undefined' && field.contacts):
var opts = ''; // this is a placeholder for when I implement loading data into the form
input = '<select id="formit-' + fid + '" name="' + name + '" class="form-control contacts select2 ' + classes + '"' + ((field.required) ? ' required' : '') + ' data-route="/companies/contacts">' + opts + '</select>';
break;
// string with options = select
case (field.type == 'string' && typeof field.options != 'undefined'):
var opts = '',
isArr = Array.isArray(field.options),
val = '';
for (var k in field.options) {
val = (isArr) ? field.options[k] : k;
opts += '<option value="' + val + '">' + field.options[k] + '</option>';
}
input = '<select id="formit-' + fid + '" name="' + name + '" class="form-control ' + classes + '"' + ((field.required) ? ' required' : '') + '>' + opts + '</select>';
break;
// string, double, integer, email, datetime
default:
let inputType = 'text';
let attr = ' ';
if (field.type == 'double' || field.type == 'integer') {
inputType = 'number';
attr = (field.type == 'double') ? ' step="0.01"' : ' ';
} else if (field.type == 'email') {
inputType = 'email';
}
if (field.type == 'datetime') {
classes += ' field-datetime';
}
input = '<input type="' + inputType + '" id="formit-' + fid + '" name="' + name + '" placeholder="' + placeholder + '" class="form-control ' + classes + '"' + ((field.required) ? ' required' : '') + attr + '>';
break;
}
return '<div class="form-group">' +
'<label for="formit-' + fid + '" class="control-label">' + label + ((field.required) ? '<strong>*</strong>' : '') + '</label>' +
input +
((help !== '') ? '<small class="text-muted"><i class="fas fa-fw fa-question-circle"></i> ' + help + '</small>' : '') +
'</div>';
};
FormIt.prototype._fieldLabelFromId = function(fid) {
return (fid + '')
.replace(/^(.)|\s+(.)/g, function ($1) {
return $1.toUpperCase()
});
};
FormIt.prototype._serialize = function(obj, prefix) {
var str = [],
p;
for (p in obj) {
if (obj.hasOwnProperty(p)) {
var k = prefix ? prefix + "[" + p + "]" : p,
v = obj[p];
str.push((v !== null && typeof v === "object") ?
serialize(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
}
return str.join("&");
};
FormIt.prototype._uniqid = function(prefix, moreEntropy) {
// discuss at: http://locutus.io/php/uniqid/
// original by: Kevin van Zonneveld (http://kvz.io)
// revised by: Kankrelune (http://www.webfaktory.info/)
// note 1: Uses an internal counter (in locutus global) to avoid collision
// example 1: var $id = uniqid()
// example 1: var $result = $id.length === 13
// returns 1: true
// example 2: var $id = uniqid('foo')
// example 2: var $result = $id.length === (13 + 'foo'.length)
// returns 2: true
// example 3: var $id = uniqid('bar', true)
// example 3: var $result = $id.length === (23 + 'bar'.length)
// returns 3: true
if (typeof prefix === 'undefined') {
prefix = ''
}
var retId
var _formatSeed = function (seed, reqWidth) {
seed = parseInt(seed, 10).toString(16) // to hex str
if (reqWidth < seed.length) {
// so long we split
return seed.slice(seed.length - reqWidth)
}
if (reqWidth > seed.length) {
// so short we pad
return Array(1 + (reqWidth - seed.length)).join('0') + seed
}
return seed
}
var $global = (typeof window !== 'undefined' ? window : global)
$global.$locutus = $global.$locutus || {}
var $locutus = $global.$locutus
$locutus.php = $locutus.php || {}
if (!$locutus.php.uniqidSeed) {
// init seed with big random int
$locutus.php.uniqidSeed = Math.floor(Math.random() * 0x75bcd15)
}
$locutus.php.uniqidSeed++
// start with prefix, add current milliseconds hex string
retId = prefix
retId += _formatSeed(parseInt(new Date().getTime() / 1000, 10), 8)
// add seed hex string
retId += _formatSeed($locutus.php.uniqidSeed, 5)
if (moreEntropy) {
// for more entropy we add a float lower to 10
retId += (Math.random() * 10).toFixed(8).toString()
}
return retId
};
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
:Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.
”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.
Our community of experts have been thoroughly vetted for their expertise and industry experience.
The Fellow title is reserved for select members who demonstrate sustained contributions, industry leadership, and outstanding performance. We will announce the experts being inducted into the Experts Exchange Fellowship during the annual Expert Awards, but unlike other awards, Fellow is a lifelong status. This title may not be given every year if there are no obvious candidates.
The Most Valuable Expert award recognizes technology experts who passionately share their knowledge with the community, demonstrate the core values of this platform, and go the extra mile in all aspects of their contributions. This award is based off of nominations by EE users and experts. Multiple MVEs may be awarded each year.