+ function copyAttributes($source, $target, attributes) {
+ _.each(attributes, function(name) {
+ if ($source.attr(name)) {
+ $target.attr(name, $source.attr(name));
+ }
+ });
+ }
+
+ $.fn.crmDatepicker = function(options) {
+ return $(this).each(function() {
+ if ($(this).is('.crm-form-date-wrapper .crm-hidden-date')) {
+ // Already initialized
+ return;
+ }
+ var
+ $dataField = $(this).wrap('<span class="crm-form-date-wrapper" />'),
+ settings = $.extend({}, $dataField.data('datepicker') || {}, options || {}),
+ $dateField = $(),
+ $timeField = $(),
+ $clearLink = $();
+
+ if (settings.allowClear !== undefined ? settings.allowClear : !$dataField.hasClass('required')) {
+ $clearLink = $('<a class="crm-hover-button crm-clear-link" title="'+ ts('Clear') +'"><span class="icon ui-icon-close"></span></a>')
+ .insertAfter($dataField);
+ }
+ if (settings.time !== false) {
+ $timeField = $('<input>').insertAfter($dataField);
+ copyAttributes($dataField, $timeField, ['class', 'disabled']);
+ $timeField
+ .addClass('crm-form-text crm-form-time')
+ .attr('placeholder', $dataField.attr('time-placeholder') === undefined ? ts('Time') : $dataField.attr('time-placeholder'))
+ .change(updateDataField)
+ .timeEntry({
+ spinnerImage: '',
+ show24Hours: settings.time === true || settings.time === undefined ? CRM.config.timeIs24Hr : settings.time == '24'
+ });
+ }
+ if (settings.date !== false) {
+ $dateField = $('<input>').insertAfter($dataField);
+ copyAttributes($dataField, $dateField, ['placeholder', 'style', 'class', 'disabled']);
+ $dateField.addClass('crm-form-text crm-form-date');
+ settings.dateFormat = settings.dateFormat || CRM.config.dateInputFormat;
+ settings.changeMonth = _.includes('m', settings.dateFormat);
+ settings.changeYear = _.includes('y', settings.dateFormat);
+ $dateField.datepicker(settings).change(updateDataField);
+ }
+ // Rudimentary validation. TODO: Roll into use of jQUery validate and ui.datepicker.validation
+ function isValidDate() {
+ try {
+ $.datepicker.parseDate(settings.dateFormat, $dateField.val());
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+ function updateInputFields(e, context) {
+ var val = $dataField.val(),
+ time = null;
+ if (context !== 'userInput' && context !== 'crmClear') {
+ if ($dateField.length) {
+ $dateField.datepicker('setDate', _.includes(val, '-') ? $.datepicker.parseDate('yy-mm-dd', val) : null);
+ }
+ if ($timeField.length) {
+ if (val.length === 8) {
+ time = val;
+ } else if (val.length === 19) {
+ time = val.split(' ')[1];
+ }
+ $timeField.timeEntry('setTime', time);
+ }
+ }
+ $clearLink.css('visibility', val ? 'visible' : 'hidden');
+ }
+ function updateDataField(e, context) {
+ // The crmClear event wipes all the field values anyway, so no need to respond
+ if (context !== 'crmClear') {
+ var val = '';
+ if ($dateField.val()) {
+ if (isValidDate()) {
+ val = $.datepicker.formatDate('yy-mm-dd', $dateField.datepicker('getDate'));
+ $dateField.removeClass('crm-error');
+ } else {
+ $dateField.addClass('crm-error');
+ }
+ }
+ if ($timeField.val()) {
+ val += (val ? ' ' : '') + $timeField.timeEntry('getTime').toTimeString().substr(0, 8);
+ }
+ $dataField.val(val).trigger('change', ['userInput']);
+ }
+ }
+ $dataField.hide().addClass('crm-hidden-date').on('change', updateInputFields);
+ updateInputFields();
+ });
+ };
+
+ $.fn.crmAjaxTable = function() {
+ return $(this).each(function() {
+ //Declare the defaults for DataTables
+ var defaults = {
+ "processing": true,
+ "serverSide": true,
+ "dom": '<"crm-datatable-pager-top"lfp>rt<"crm-datatable-pager-bottom"ip>',
+ "pageLength": 25,
+ "drawCallback": function(settings) {
+ //Add data attributes to cells
+ $('thead th', settings.nTable).each( function( index ) {
+ $.each(this.attributes, function() {
+ if(this.name.match("^cell-")) {
+ var cellAttr = this.name.substring(5);
+ var cellValue = this.value
+ $('tbody tr', settings.nTable).each( function() {
+ $('td:eq('+ index +')', this).attr( cellAttr, cellValue );
+ });
+ }
+ });
+ });
+ //Reload table after draw
+ $(settings.nTable).trigger('crmLoad');
+ }
+ };
+ //Include any table specific data
+ var settings = $.extend(true, defaults, $(this).data('table'));
+ //Make the DataTables call
+ $(this).DataTable(settings);
+ });
+ };
+