Browse Source

Merge pull request #18648 from abpframework/issue-18335

Improve AbpDatePicker
pull/18654/head
maliming 2 years ago
committed by GitHub
parent
commit
ea7200f77f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md
  2. 13
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelper.cs
  3. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs
  4. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerOptions.cs
  5. 20
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDateRangePickerTagHelperService.cs
  6. 13
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/IAbpDatePickerOptions.cs
  7. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs
  8. 562
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js
  9. 711
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js

6
docs/en/UI/AspNetCore/Tag-Helpers/Form-elements.md

@ -364,7 +364,8 @@ You can set some of the attributes on your c# property, or directly on HTML tag.
* `single-open-and-clear-button`: Shows the open and clear buttons in a single button when it's `True`. The default value is `True`.
* `is-utc`: Converts the date to UTC when its `True`. The default value is `False`.
* `is-iso`: Converts the date to ISO format when its `True`. The default value is `False`.
* `date-format`: Sets the date format of the input. The default format is the user's culture date format. You need to provide a JavaScript date format convention. Eg: `YYYY-MM-DDTHH:MM:SSZ`.
* `visible-date-format`: Sets the date format of the input. The default format is the user's culture date format. You need to provide a JavaScript date format convention. Eg: `YYYY-MM-DDTHH:MM:SSZ`.
* `input-date-format`: Sets the date format of the hidden input for backend compatibility. The default format is `YYYY-MM-DD`. You need to provide a JavaScript date format convention. Eg: `YYYY-MM-DDTHH:MM:SSZ`.
* `date-separator`: Sets a character to separate start and end dates. The default value is `-`
* Other non-mapped attributes will be automatically added to the input element as is. See the available [datepicker options](https://www.daterangepicker.com/#options). Eg: `data-start-date="2020-01-01"`
@ -425,7 +426,8 @@ newPicker.insertAfter($('body'));
* `singleOpenAndClearButton`: Shows the open and clear buttons in a single button when it's `True`. The default value is `True`.
* `isUtc`: Converts the date to UTC when its `True`. The default value is `False`.
* `isIso`: Converts the date to ISO format when its `True`. The default value is `False`.
* `dateFormat`: Sets the date format of the input. The default format is the user's culture date format. You need to provide a JavaScript date format convention. Eg: `YYYY-MM-DDTHH:MM:SSZ`.
* `visibleDateFormat`: Sets the date format of the input. The default format is the user's culture date format. You need to provide a JavaScript date format convention. Eg: `YYYY-MM-DDTHH:MM:SSZ`.
* `inputDateFormat`: Sets the date format of the hidden input for backend compatibility. The default format is `YYYY-MM-DD`. You need to provide a JavaScript date format convention. Eg: `YYYY-MM-DDTHH:MM:SSZ`.
* `dateSeparator`: Sets a character to separate start and end dates. The default value is `-`.
* `startDateName`: Sets the name of the hidden start date input.
* `endDateName`: Sets the name of the hidden end date input.

13
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelper.cs

@ -185,17 +185,28 @@ public abstract class
set => _abpDatePickerOptionsImplementation.ParentEl = value;
}
[Obsolete("Use VisibleDateFormat instead.")]
public string? DateFormat {
get => _abpDatePickerOptionsImplementation.DateFormat;
set => _abpDatePickerOptionsImplementation.DateFormat = value;
}
public string? VisibleDateFormat {
get => _abpDatePickerOptionsImplementation.VisibleDateFormat;
set => _abpDatePickerOptionsImplementation.VisibleDateFormat = value;
}
public string? InputDateFormat {
get => _abpDatePickerOptionsImplementation.InputDateFormat;
set => _abpDatePickerOptionsImplementation.InputDateFormat = value;
}
public bool OpenButton {
get => _abpDatePickerOptionsImplementation.OpenButton;
set => _abpDatePickerOptionsImplementation.OpenButton = value;
}
public bool ClearButton {
public bool? ClearButton {
get => _abpDatePickerOptionsImplementation.ClearButton;
set => _abpDatePickerOptionsImplementation.ClearButton = value;
}

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs

@ -125,7 +125,7 @@ public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelp
var openButtonContent = TagHelper.OpenButton
? await ProcessButtonAndGetContentAsync(context, output, "calendar", "open")
: "";
var clearButtonContent = TagHelper.ClearButton
var clearButtonContent = TagHelper.ClearButton == true || (!TagHelper.ClearButton.HasValue && TagHelper.AutoUpdateInput != true)
? await ProcessButtonAndGetContentAsync(context, output, "times", "clear", visible:!TagHelper.SingleOpenAndClearButton)
: "";
@ -382,6 +382,16 @@ public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelp
{
attrList.Add("data-date-format", options.DateFormat);
}
if(!options.VisibleDateFormat.IsNullOrEmpty())
{
attrList.Add("data-visible-date-format", options.VisibleDateFormat);
}
if(!options.InputDateFormat.IsNullOrEmpty())
{
attrList.Add("data-input-date-format", options.InputDateFormat);
}
if(options.Ranges != null && options.Ranges.Any())
{

6
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerOptions.cs

@ -31,9 +31,13 @@ public class AbpDatePickerOptions : IAbpDatePickerOptions
public bool? LinkedCalendars { get; set; }
public bool? AutoUpdateInput { get; set; }
public string? ParentEl { get; set; }
[Obsolete("Use VisibleDateFormat instead.")]
public string? DateFormat { get; set; }
public string? VisibleDateFormat { get; set; }
public string? InputDateFormat { get; set; }
public bool OpenButton { get; set; } = true;
public bool ClearButton { get; set; } = true;
public bool? ClearButton { get; set; }
public bool SingleOpenAndClearButton { get; set; } = true;
public bool? IsUtc { get; set; }
public bool? IsIso { get; set; }

20
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDateRangePickerTagHelperService.cs

@ -84,18 +84,24 @@ public class AbpDateRangePickerTagHelperService : AbpDatePickerBaseTagHelperServ
protected override void AddBaseTagAttributes(TagHelperAttributeList attributes)
{
if (TagHelper.AspForStart != null &&
TagHelper.AspForStart.Model != null &&
if (TagHelper.AspForStart?.Model != null &&
SupportedInputTypes.TryGetValue(TagHelper.AspForStart.Metadata.ModelType, out var convertFuncStart))
{
attributes.Add("data-start-date", convertFuncStart(TagHelper.AspForStart.Model));
var convert = convertFuncStart(TagHelper.AspForStart.Model);
if(!convert.IsNullOrWhiteSpace())
{
attributes.Add("data-start-date", convert);
}
}
if (TagHelper.AspForEnd != null &&
TagHelper.AspForEnd.Model != null &&
if (TagHelper.AspForEnd?.Model != null &&
SupportedInputTypes.TryGetValue(TagHelper.AspForEnd.Metadata.ModelType, out var convertFuncEnd))
{
attributes.Add("data-end-date", convertFuncEnd(TagHelper.AspForEnd.Model));
var convert = convertFuncEnd(TagHelper.AspForEnd.Model);
if(!convert.IsNullOrWhiteSpace())
{
attributes.Add("data-end-date", convert);
}
}
}

13
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/IAbpDatePickerOptions.cs

@ -134,11 +134,22 @@ public interface IAbpDatePickerOptions
/// </summary>
string? ParentEl { get; set; }
[Obsolete("Use VisibleDateFormat instead.")]
string? DateFormat { get; set; }
/// <summary>
/// The date format string that will appear in the input element. For user input.
/// </summary>
string? VisibleDateFormat { get; set; }
/// <summary>
/// The date format string that will appear in the hidden input element. For backend compatibility.
/// </summary>
string? InputDateFormat { get; set; }
bool OpenButton { get; set; }
bool ClearButton { get; set; }
bool? ClearButton { get; set; }
bool SingleOpenAndClearButton { get; set; }

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs

@ -48,7 +48,8 @@ public class SharedThemeGlobalScriptContributor : BundleContributor
"/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js",
"/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js",
"/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js",
"/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js"
"/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js",
"/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js"
});
}
}

562
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js

@ -197,565 +197,7 @@
});
}
abp.libs.bootstrapDateRangePicker = {
packageName: "bootstrap-daterangepicker",
createDateRangePicker: function (options) {
options = options || {};
options.singleDatePicker = false;
return this.createDatePicker(options);
},
createSinglePicker: function (options) {
options = options || {};
options.singleDatePicker = true;
return this.createDatePicker(options);
},
createDatePicker: function (options) {
var $container = $('<div class="mb-3"></div>')
var label = $('<label class="form-label"></label>')
if (options.label) {
label.text(options.label)
}
$container.append(label)
var $datePicker = options.singleDatePicker ? $('<abp-date-picker></abp-date-picker>') : $('<abp-date-range-picker></abp-date-range-picker>');
$container.append($datePicker)
var $inputGroup = $('<div class="input-group"></div>');
var $dateInput = $('<input type="text" autocomplete="off" class="form-control" />');
if (options.placeholder) {
$dateInput.attr('placeholder', options.placeholder)
}
if (options.value) {
$dateInput.val(options.value)
}
if (options.name) {
$dateInput.attr('name', options.name)
}
if (options.id) {
$dateInput.attr('id', options.id)
}
if (options.required) {
$dateInput.attr('required', true)
}
if (options.disabled) {
$dateInput.attr('disabled', true)
}
if (options.readonly) {
$dateInput.attr('readonly', true)
}
if(options.placeholder) {
$dateInput.attr('placeholder', options.placeholder)
}
if (options.size) {
switch (options.size) {
case 'Small':
$dateInput.addClass('form-control-sm')
break;
case 'Medium':
$dateInput.addClass('form-control-md')
break;
case 'Large':
$dateInput.addClass('form-control-lg')
break;
default:
break;
}
}
$inputGroup.append($dateInput);
if (options.openButton !== false) {
var $openButton = $('<button type="button" class="btn btn-outline-secondary" tabindex="-1" data-type="open"><i class="fa fa-calendar"></i></button>');
$inputGroup.append($openButton);
if(options.disabled) {
$openButton.attr('disabled', 'disabled')
}
}
if (options.clearButton !== false) {
var $clearButton = $('<button type="button" class="btn btn-outline-secondary" tabindex="-1" data-type="clear"><i class="fa fa-times"></i></button>');
$inputGroup.append($clearButton);
if(options.disabled) {
$clearButton.attr('disabled', 'disabled')
}
}
$datePicker.append($inputGroup);
if (options.startDateName) {
var $hiddenStartDateElement = $('<input type="hidden" data-start-date="true" name="' + options.startDateName + '" />');
$datePicker.append($hiddenStartDateElement);
}
if (options.endDateName) {
var $hiddenEndDateElement = $('<input type="hidden" data-end-date="true" name="' + options.endDateName + '" />');
$datePicker.append($hiddenEndDateElement);
}
if (options.dateName) {
var $hiddenDateElement = $('<input type="hidden" data-date="true" name="' + options.dateName + '" />');
$datePicker.append($hiddenDateElement);
}
$datePicker.data('options', options);
abp.dom.initializers.initializeDateRangePickers($datePicker);
$container[0].datePicker = $datePicker[0];
return $container;
}
};
abp.dom.initializers.initializeDateRangePickers = function ($rootElement) {
function setOptions (options, $datePickerElement, singleDatePicker) {
options.singleDatePicker = singleDatePicker;
var defaultOptions = {
showDropdowns: true,
opens: "center",
drops: "down",
autoApply: true,
autoUpdateInput: false,
showTodayButton: true,
showClearButton: true,
minYear: parseInt(moment().subtract(100, 'year').locale('en').format('YYYY')),
maxYear: parseInt(moment().add(100, 'year').locale('en').format('YYYY')),
locale: {
direction: abp.localization.currentCulture.isRightToLeft ? 'rtl' : 'ltr',
todayLabel: abp.localization.localize('Today', 'AbpUi'),
clearLabel: abp.localization.localize('Clear', 'AbpUi'),
applyLabel: abp.localization.localize('Apply', 'AbpUi'),
},
singleOpenAndClearButton: true
};
var locale = defaultOptions.locale;
$.extend(options, defaultOptions);
$.extend(options, $datePickerElement.data());
if ($.isEmptyObject(options.locale)) {
options.locale = locale;
} else {
locale = options.locale;
}
$.extend(options, $datePickerElement.data("options"));
if ($.isEmptyObject(options.locale)) {
options.locale = locale;
}
if (options.timePicker && options.timePicker24Hour === undefined) {
options.timePicker24Hour = moment.localeData().longDateFormat('LT').indexOf('A') < 1;
}
if (options.dateFormat) {
options.locale = options.locale || {};
options.locale.format = options.dateFormat;
}
if (options.separator) {
options.locale = options.locale || {};
options.locale.separator = options.separator;
}
if (options.ranges) {
$.each(options.ranges, function (key, value) {
let start = value[0];
let end;
if (value.length > 1) {
end = value[1];
} else {
end = value[0];
}
options.ranges[key] = [getMoment(start, options), getMoment(end, options)];
});
}
if (typeof options.template !== 'string' && !(options.template instanceof $))
options.template =
'<div class="daterangepicker">' +
'<div class="ranges"></div>' +
'<div class="drp-calendar left">' +
'<div class="calendar-table"></div>' +
'<div class="calendar-time"></div>' +
'</div>' +
'<div class="drp-calendar right">' +
'<div class="calendar-table"></div>' +
'<div class="calendar-time"></div>' +
'</div>' +
'<div class="drp-buttons">' +
'<button class="applyBtn" disabled="disabled" type="button"></button> ' +
'</div>' +
'</div>';
}
function replaceOpenButton (hasDate,singleOpenAndClearButton, $openButton, $clearButton) {
var hiddenClass = 'd-none';
if (singleOpenAndClearButton) {
if (hasDate) {
$openButton.addClass(hiddenClass);
$clearButton.removeClass(hiddenClass);
$clearButton.insertAfter($openButton);
} else {
$openButton.removeClass(hiddenClass);
$clearButton.addClass(hiddenClass);
$openButton.insertAfter($clearButton);
}
}
}
function getMoment (date, options, dateFormat) {
var isUtc = options.isUtc;
dateFormat = dateFormat || options.dateFormat;
if (!date) {
return isUtc ? moment.utc().startOf('day') : moment().startOf('day');
}
if (isUtc) {
return moment.utc(date, dateFormat);
} else {
return moment(date, dateFormat);
}
}
function getStartDate(options, startDate){
startDate = startDate ? startDate : options.startDate;
startDate = startDate ? getMoment(startDate, options) : null;
if (options.singleDatePicker && !startDate) {
startDate = options.date ? getMoment(options.date, options) : null;
}
if(startDate && startDate.isValid()){
return startDate;
}
return null;
}
function getEndDate(options, endDate){
if (options.singleDatePicker) {
return null;
}
endDate = endDate ? endDate : options.endDate;
endDate = endDate ? getMoment(endDate, options) : null;
if(endDate && endDate.isValid()){
return endDate;
}
return null;
}
function getTodayButton(options, $input){
if (options.showTodayButton) {
var $todayBtn = $('<button type="button" class="btn btn-sm today-btn" data-action="today">' + options.locale.todayLabel + '</button>');
if(options.todayButtonClasses){
$todayBtn.addClass(options.todayButtonClasses);
}else{
$todayBtn.addClass('btn-default');
}
$todayBtn.on('click', function () {
var today = getMoment(undefined, options);
$input.data('daterangepicker').setStartDate(today);
$input.data('daterangepicker').setEndDate(today);
$input.data('daterangepicker').clickApply();
});
return $todayBtn;
}
return null;
}
function getClearButton(options, $input, $dateRangePicker){
if (options.showClearButton) {
var $clearBtn = $('<button type="button" class="btn btn-sm clear-btn" data-action="clear">' + options.locale.clearLabel + '</button>');
if(options.clearButtonClasses){
$clearBtn.addClass(options.clearButtonClasses);
}else{
$clearBtn.addClass('btn-default');
}
$clearBtn.on('click', function () {
$input.val('').trigger('change');
$dateRangePicker.hide();
});
return $clearBtn;
}
return null;
}
function addExtraButtons(options, $dateRangePicker, $input) {
var extraButtons = [getTodayButton(options, $input), getClearButton(options, $input, $dateRangePicker)];
if ($dateRangePicker.container.hasClass('auto-apply')) {
var $div = $('<div class="drp-buttons extra-buttons"></div>');
$div.css('display', 'block');
$.each(extraButtons, function (index, value) {
$div.prepend(value);
});
$div.insertAfter($dateRangePicker.container.find('.drp-buttons'));
} else {
$.each(extraButtons, function (index, value) {
$dateRangePicker.container.find('.drp-buttons').prepend(value);
});
}
}
function addOpenButtonClick($openButton, $dateRangePicker){
if(!$openButton){
return;
}
$dateRangePicker.outsideClick = function (e) {
var target = $(e.target);
// if the page is clicked anywhere except within the daterangerpicker/button itself then call this.hide()
if (
// ie modal dialog fix
e.type == "focusin" ||
target.closest(this.element).length ||
target.closest(this.container).length ||
target.closest('.calendar-table').length ||
target.closest($openButton).length
) {
return;
}
this.hide();
this.element.trigger('outsideClick.daterangepicker', this);
};
$openButton.on('click', function () {
$dateRangePicker.toggle();
});
}
function extendDateFormat (format,options) {
if (options.timePicker) {
if (options.timePicker24Hour) {
if (options.timePickerSeconds) {
format += " HH:mm:ss";
} else {
format += " HH:mm";
}
} else {
if (options.timePickerSeconds) {
format += ' ' + " hh:mm:ss A"
} else {
format += " hh:mm A";
}
}
}
return format;
}
function fillInput($input, startDate, endDate, options) {
if (options.singleDatePicker) {
if (startDate) {
$input.val(startDate.format(options.dateFormat));
}
} else {
if (startDate && endDate) {
$input.val(startDate.format(options.dateFormat) + options.separator + endDate.format(options.dateFormat));
}
}
}
$rootElement
.findWithSelf('abp-date-picker,abp-date-range-picker')
.each(function () {
var $this = $(this);
var $input = $this.find('.input-group input[type="text"]')
if ($input.data('daterangepicker')) {
return;
}
var $openButton = $this.find('button[data-type="open"]')
var $clearButton = $this.find('button[data-type="clear"]')
var singleDatePicker = $this.is('abp-date-picker')
var options = {};
setOptions(options, $this, singleDatePicker);
var isIso = options.isIso;
var dateFormat = options.dateFormat;
var separator = options.separator;
var defaultDateFormat = extendDateFormat("YYYY-MM-DD", options);
var singleOpenAndClearButton = options.singleOpenAndClearButton && $clearButton.length > 0 && $openButton.length > 0;
var startDate = getStartDate(options);
var endDate = getEndDate(options);
if (startDate) {
options.startDate = startDate;
}
if (endDate) {
options.endDate = endDate;
}
$input.daterangepicker(options);
var $dateRangePicker = $input.data('daterangepicker');
addExtraButtons(options, $dateRangePicker, $input);
addOpenButtonClick($openButton, $dateRangePicker);
if (!dateFormat) {
dateFormat = extendDateFormat(moment.localeData().longDateFormat('L'), options);
options.dateFormat = dateFormat;
}
if (!separator) {
separator = $dateRangePicker.locale.separator;
options.separator = separator;
}
fillInput($input, startDate, endDate, options);
$input.on('apply.daterangepicker', function (ev, picker) {
if (singleDatePicker) {
$(this).val(picker.startDate.format(dateFormat));
} else {
$(this).val(picker.startDate.format(dateFormat) + separator + picker.endDate.format(dateFormat));
}
$(this).trigger('change');
});
$input.on('cancel.daterangepicker', function (ev, picker) {
$(this).val('');
$(this).trigger('change');
});
$input.on('show.daterangepicker', function (ev, picker) {
var momentStartDate = getMoment(startDate, options);
var momentEndDate = getMoment(endDate, options);
if (momentStartDate.isValid()) {
picker.setStartDate(momentStartDate);
picker.setEndDate(momentEndDate);
}
if (momentEndDate.isValid() && !singleDatePicker) {
picker.setEndDate(momentEndDate);
}
});
$clearButton.on('click', function () {
$input.val('');
$input.trigger('change');
});
var firstTrigger = true;
$input.on('change', function () {
if ($(this).val() !== '') {
replaceOpenButton(true, singleOpenAndClearButton, $openButton, $clearButton);
} else {
replaceOpenButton(false, singleOpenAndClearButton, $openButton, $clearButton);
}
var dates = $(this).val().split(separator);
if (dates.length === 2) {
startDate = formatDate(getStartDate(options, dates[0]));
endDate = formatDate(getEndDate(options, dates[1]));
} else {
if (dates[0]) {
startDate = formatDate(getStartDate(options, dates[0]));
}
else {
if(!firstTrigger){
startDate = null;
}
}
if(!firstTrigger){
endDate = null;
}
}
if (!startDate) {
replaceOpenButton(false, singleOpenAndClearButton, $openButton, $clearButton);
$(this).val('');
}
if (!singleDatePicker) {
var input1 = $this.find("input[data-start-date]")
input1.val(startDate);
var input2 = $this.find("input[data-end-date]")
input2.val(endDate);
} else {
var input = $this.find("input[data-date]")
input.val(startDate);
}
if (singleDatePicker) {
$this.data('date', startDate);
$input.data('date', startDate);
} else {
$this.data('startDate', startDate);
$this.data('endDate', endDate);
$input.data('startDate', startDate);
$input.data('endDate', endDate);
}
firstTrigger = false;
});
function formatDate(date) {
if (date) {
if (isIso) {
return date.locale('en').format();
}
return date.locale('en').format(defaultDateFormat)
}
return null;
}
function getFormattedStartDate() {
if (startDate) {
return getMoment(startDate, options).format(dateFormat);
}
return null;
}
function getFormattedEndDate() {
if (endDate) {
return getMoment(endDate, options).format(dateFormat);
}
return null;
}
if (singleDatePicker) {
$this[0].getFormattedDate = getFormattedStartDate;
$input[0].getFormattedDate = getFormattedStartDate;
$dateRangePicker.getFormattedDate = getFormattedStartDate;
} else {
$dateRangePicker.getFormattedStartDate = getFormattedStartDate;
$dateRangePicker.getFormattedEndDate = getFormattedEndDate;
$this[0].getFormattedStartDate = getFormattedStartDate;
$this[0].getFormattedEndDate = getFormattedEndDate;
$input[0].getFormattedStartDate = getFormattedStartDate;
$input[0].getFormattedEndDate = getFormattedEndDate;
}
$input.trigger('change');
});
}
abp.dom.initializers.initializeAbpCspStyles = function ($abpCspStyles){
$abpCspStyles.attr("rel", "stylesheet");
@ -769,7 +211,6 @@
abp.dom.initializers.initializeScript(args.$el);
abp.dom.initializers.initializeAutocompleteSelects(args.$el.findWithSelf('.auto-complete-select'));
abp.dom.initializers.initializeAbpCspStyles($("link[abp-csp-style]"));
abp.dom.initializers.initializeDateRangePickers(args.$el);
});
abp.dom.onNodeRemoved(function (args) {
@ -788,7 +229,6 @@
abp.dom.initializers.initializePopovers($('[data-bs-toggle="popover"]'));
abp.dom.initializers.initializeTimeAgos($('.timeago'));
abp.dom.initializers.initializeDatepickers($(document));
abp.dom.initializers.initializeDateRangePickers($(document));
abp.dom.initializers.initializeForms($('form'));
abp.dom.initializers.initializeAutocompleteSelects($('.auto-complete-select'));
$('[data-auto-focus="true"]').first().findWithSelf('input,select').focus();

711
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js

@ -0,0 +1,711 @@
(function ($) {
abp.dom = abp.dom || {};
abp.dom.initializers = abp.dom.initializers || {};
abp.libs.bootstrapDateRangePicker = {
packageName: "bootstrap-daterangepicker",
createDateRangePicker: function (options) {
options = options || {};
options.singleDatePicker = false;
return this.createDatePicker(options);
},
createSinglePicker: function (options) {
options = options || {};
options.singleDatePicker = true;
return this.createDatePicker(options);
},
createDatePicker: function (options) {
var $container = $('<div class="mb-3"></div>')
var label = $('<label class="form-label"></label>')
if (options.label) {
label.text(options.label)
}
$container.append(label)
var $datePicker = options.singleDatePicker ? $('<abp-date-picker></abp-date-picker>') : $('<abp-date-range-picker></abp-date-range-picker>');
$container.append($datePicker)
var $inputGroup = $('<div class="input-group"></div>');
var $dateInput = $('<input type="text" autocomplete="off" class="form-control" />');
if (options.value) {
$dateInput.val(options.value)
}
const setAttribute = attr => {
if (options[attr]) {
$dateInput.attr(attr, options[attr])
}
}
setAttribute('placeholder');
setAttribute('name');
setAttribute('id');
setAttribute('required');
setAttribute('disabled');
setAttribute('readonly');
const sizeMap = {
'Small': 'form-control-sm',
'Medium': 'form-control-md',
'Large': 'form-control-lg'
};
if (options.size && sizeMap[options.size]) {
$dateInput.addClass(sizeMap[options.size])
}
$inputGroup.append($dateInput);
const addButton = (button, buttonHTML) => {
if (options[button] !== false) {
var $button = $(buttonHTML);
$inputGroup.append($button);
if (options.disabled) {
$button.attr('disabled', 'disabled')
}
}
}
addButton('openButton', '<button type="button" class="btn btn-outline-secondary" tabindex="-1" data-type="open"><i class="fa fa-calendar"></i></button>');
addButton('clearButton', '<button type="button" class="btn btn-outline-secondary" tabindex="-1" data-type="clear"><i class="fa fa-times"></i></button>');
$datePicker.append($inputGroup);
const addHiddenInput = (name, attributeName) => {
if (name) {
var $hiddenElement = $(`<input type="hidden" name="${name}" ${attributeName}="true" />`);
$datePicker.append($hiddenElement);
}
}
addHiddenInput(options.startDateName, 'data-start-date');
addHiddenInput(options.endDateName, 'data-end-date');
addHiddenInput(options.dateName, 'data-date');
$datePicker.data('options', options);
abp.dom.initializers.initializeDateRangePickers($datePicker);
$container[0].datePicker = $datePicker[0];
return $container;
}
};
function isEmptyDate(date, options) {
if(!date) {
return true;
}
if(typeof date === 'string') {
return date.trim() === '';
}
return !AbpDate(date, options).isValid();
}
function AbpDate(originalDate, options, format) {
var _moment = convertToMoment(originalDate, options, format);
function _clone() {
return AbpDate(_moment, options, format);
}
function _isSame(date) {
return _format(options.inputDateFormat) === AbpDate(date, options).format(options.inputDateFormat);
}
function _isValid() {
return _moment && _moment.isValid();
}
function _format(format) {
if (_isValid()) {
return _moment.format(format);
}
return '';
}
function _valueOf() {
return _isValid() ? _moment.valueOf() : undefined;
}
function _toString() {
return _moment.toString();
}
return {
_moment: _moment,
clone: _clone,
isSame: _isSame,
isValid: _isValid,
format: _format,
valueOf: _valueOf,
toString: _toString,
date: _moment.toISOString(),
isAbpDate: true
};
}
function replaceOpenButton(hasDate, singleOpenAndClearButton, $openButton, $clearButton) {
const hideButtonClass = 'd-none';
if (!singleOpenAndClearButton) {
return;
}
if (hasDate) {
$openButton.addClass(hideButtonClass);
$clearButton.removeClass(hideButtonClass);
$clearButton.insertAfter($openButton);
} else {
$openButton.removeClass(hideButtonClass);
$clearButton.addClass(hideButtonClass);
$openButton.insertAfter($clearButton);
}
}
function convertToMoment(value, options, dateFormat) {
if(!value) {
// invalid date
return moment('');
}
options = options || {};
var formats = new Set([dateFormat, options.visibleDateFormat, options.inputDateFormat, undefined]);
if (typeof value === 'string') {
for(var format of formats) {
var date = moment(value, format);
if(date.isValid()) {
return maybeUtc(date, options);
}
}
}
if (value.isAbpDate) {
return maybeUtc(value._moment.clone(), options);
}
if(value.isLuxonDateTime) {
return maybeUtc(moment(value.toISO()), options);
}
return maybeUtc(moment(value), options);
}
function maybeUtc(date, options) {
if (options.isUtc) {
date = date.utc();
}else{
date = date.local();
}
return date;
}
function getTodayButton(options, $dateRangePicker) {
if (options.showTodayButton) {
var $todayBtn = $('<button type="button" class="btn btn-sm today-btn" data-action="today">' + options.locale.todayLabel + '</button>');
if (options.todayButtonClasses) {
$todayBtn.addClass(options.todayButtonClasses);
} else {
$todayBtn.addClass('btn-default');
}
$todayBtn.on('click', function () {
var today = moment();
$dateRangePicker.setStartDate(today);
$dateRangePicker.setEndDate(today);
if(options.singleDatePicker && options.autoApply){
$dateRangePicker.clickApply();
}else{
$dateRangePicker.updateView();
}
});
return $todayBtn;
}
return null;
}
function getClearButton(options, $input, $dateRangePicker) {
if (options.showClearButton && options.autoUpdateInput !== true) {
var $clearBtn = $('<button type="button" class="btn btn-sm clear-btn" data-action="clear">' + options.locale.clearLabel + '</button>');
if (options.clearButtonClasses) {
$clearBtn.addClass(options.clearButtonClasses);
} else {
$clearBtn.addClass('btn-default');
}
$clearBtn.on('click', function () {
$input.trigger('cancel.daterangepicker', $dateRangePicker);
$dateRangePicker.hide();
});
return $clearBtn;
}
return null;
}
function addExtraButtons(options, $dateRangePicker, $input) {
var extraButtons = [getTodayButton(options, $dateRangePicker), getClearButton(options, $input, $dateRangePicker)];
if ($dateRangePicker.container.hasClass('auto-apply')) {
var $div = $('<div class="drp-buttons extra-buttons"></div>');
$div.css('display', 'block');
$.each(extraButtons, function (index, value) {
$div.prepend(value);
});
$div.insertAfter($dateRangePicker.container.find('.drp-buttons'));
} else {
$.each(extraButtons, function (index, value) {
$dateRangePicker.container.find('.drp-buttons').prepend(value);
});
}
}
function addOpenButtonClick($openButton, $dateRangePicker) {
if (!$openButton) {
return;
}
$dateRangePicker.outsideClick = function (e) {
var target = $(e.target);
// if the page is clicked anywhere except within the daterangerpicker/button itself then call this.hide()
if (
// ie modal dialog fix
e.type == "focusin" ||
target.closest(this.element).length ||
target.closest(this.container).length ||
target.closest('.calendar-table').length ||
target.closest($openButton).length
) {
return;
}
this.hide();
this.element.trigger('outsideClick.daterangepicker', this);
};
$openButton.on('click', function () {
$dateRangePicker.toggle();
});
}
function extendDateFormat(format, options) {
if (options.timePicker) {
if (options.timePicker24Hour) {
if (options.timePickerSeconds) {
format += " HH:mm:ss";
} else {
format += " HH:mm";
}
} else {
if (options.timePickerSeconds) {
format += ' ' + " hh:mm:ss A"
} else {
format += " hh:mm A";
}
}
}
return format;
}
function setOptions(options, $datePickerElement, singleDatePicker) {
options.singleDatePicker = singleDatePicker;
var defaultOptions = {
showDropdowns: true,
opens: "center",
drops: "down",
autoApply: true,
autoUpdateInput: false,
showTodayButton: true,
showClearButton: true,
minYear: parseInt(moment().subtract(100, 'year').locale('en').format('YYYY')),
maxYear: parseInt(moment().add(100, 'year').locale('en').format('YYYY')),
locale: {
direction: abp.localization.currentCulture.isRightToLeft ? 'rtl' : 'ltr',
todayLabel: abp.localization.localize('Today', 'AbpUi'),
clearLabel: abp.localization.localize('Clear', 'AbpUi'),
applyLabel: abp.localization.localize('Apply', 'AbpUi'),
},
singleOpenAndClearButton: true
};
var locale = defaultOptions.locale;
$.extend(options, defaultOptions);
$.extend(options, $datePickerElement.data());
if ($.isEmptyObject(options.locale)) {
options.locale = locale;
} else {
locale = options.locale;
}
$.extend(options, $datePickerElement.data("options"));
if ($.isEmptyObject(options.locale)) {
options.locale = locale;
}
if(options.timePickerSeconds === true && options.timePicker !== false) {
options.timePicker = true;
}
if (options.timePicker && options.timePicker24Hour === undefined) {
options.timePicker24Hour = moment.localeData().longDateFormat('LT').indexOf('A') < 1;
}
options.visibleDateFormat = options.visibleDateFormat || options.dateFormat || extendDateFormat(moment.localeData().longDateFormat('L'), options);
options.locale = options.locale || {};
options.locale.format = options.visibleDateFormat;
if (options.separator) {
options.locale = options.locale || {};
options.locale.separator = options.separator;
}
if (options.ranges) {
$.each(options.ranges, function (key, value) {
let start = value[0];
let end;
if (value.length > 1) {
end = value[1];
} else {
end = value[0];
}
options.ranges[key] = [AbpDate(start, options), AbpDate(end, options)];
});
}
if (typeof options.template !== 'string' && !(options.template instanceof $))
options.template =
'<div class="daterangepicker">' +
'<div class="ranges"></div>' +
'<div class="drp-calendar left">' +
'<div class="calendar-table"></div>' +
'<div class="calendar-time"></div>' +
'</div>' +
'<div class="drp-calendar right">' +
'<div class="calendar-table"></div>' +
'<div class="calendar-time"></div>' +
'</div>' +
'<div class="drp-buttons">' +
'<button class="applyBtn" disabled="disabled" type="button"></button> ' +
'</div>' +
'</div>';
}
function getAccessorDescriptor(obj, prop) {
if (!obj) {
return;
}
var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
if (descriptor) {
return descriptor;
}
return getAccessorDescriptor(Object.getPrototypeOf(obj), prop);
}
function addHiddenDateInputSetListener(obj, prop, listener, options) {
if (!obj) {
return;
}
var descriptor = getAccessorDescriptor(obj, prop);
if (!descriptor) {
return;
}
var originalSet = descriptor.set;
descriptor.set = function (value) {
originalSet.call(this, formatHiddenDate(value, options));
if (value.isAbpDate) {
return;
}
listener.call(this, value);
};
Object.defineProperty(obj, prop, descriptor);
}
function formatHiddenDate(date, options) {
date = convertToMoment(date, options, options.inputDateFormat);
if (date.isValid()) {
if (options.isIso) {
return date.toISOString();
}
return date.locale('en').format(options.inputDateFormat)
}
return '';
}
abp.dom.initializers.initializeDateRangePickers = function ($rootElement) {
$rootElement
.findWithSelf('abp-date-picker,abp-date-range-picker')
.each(function () {
var $this = $(this);
var $input = $this.find('.input-group input[type="text"]')
var $startDateInput = $this.find('input[data-start-date]');
var $endDateInput = $this.find('input[data-end-date]');
var $dateInput = $this.find('input[data-date]');
if ($input.data('daterangepicker')) {
return;
}
var $openButton = $this.find('button[data-type="open"]')
var $clearButton = $this.find('button[data-type="clear"]')
var singleDatePicker = $this.is('abp-date-picker')
var options = {};
setOptions(options, $this, singleDatePicker);
options.inputDateFormat = options.inputDateFormat || extendDateFormat("YYYY-MM-DD", options);
var singleOpenAndClearButton = options.singleOpenAndClearButton && $clearButton.length > 0 && $openButton.length > 0;
var startDate = AbpDate(options.startDate || options.date || (options.autoUpdateInput ? new Date() : undefined), options);
var oldStartDate = AbpDate(undefined, options);
var endDate = AbpDate(options.endDate || undefined, options);
var oldEndDate = AbpDate(undefined, options);
options.startDate = convertToMoment(startDate, options);
options.endDate = convertToMoment(endDate, options);
$input.daterangepicker(options);
var $dateRangePicker = $input.data('daterangepicker');
$input.data('format', options.visibleDateFormat);
$this.data('daterangepicker', $dateRangePicker);
$startDateInput.data('daterangepicker', $dateRangePicker);
$startDateInput.data('format', options.inputDateFormat);
$endDateInput.data('daterangepicker', $dateRangePicker);
$endDateInput.data('format', options.inputDateFormat);
$dateInput.data('daterangepicker', $dateRangePicker);
$dateInput.data('format', options.inputDateFormat);
addExtraButtons(options, $dateRangePicker, $input);
addOpenButtonClick($openButton, $dateRangePicker);
if (!options.separator) {
options.separator = $dateRangePicker.locale.separator;
}
function fillInput() {
if (options.singleDatePicker) {
if (!isEmptyDate(startDate, options)) {
$input.val(startDate.format(options.visibleDateFormat));
}
} else {
if (!isEmptyDate(startDate, options) && !isEmptyDate(endDate, options)) {
$input.val(startDate.format(options.visibleDateFormat) + options.separator + endDate.format(options.visibleDateFormat));
}
}
}
fillInput();
function changeDate(isTrigger = true, isInputTrigger = true, isDateRangePickerTrigger = true) {
if (singleDatePicker) {
if (oldStartDate.isSame(startDate)) {
return;
}
setDataDates(startDate, $dateInput, '');
$dateInput.val(startDate);
if (isTrigger) {
triggerDateChange($dateInput, startDate);
}
} else {
if (!oldStartDate.isSame(startDate)) {
setDataDates(startDate, $startDateInput, 'start');
$startDateInput.val(startDate);
if (isTrigger) {
triggerDateChange($startDateInput, startDate);
}
}
if (!oldEndDate.isSame(endDate)) {
setDataDates(endDate, $endDateInput, 'end');
$endDateInput.val(endDate);
if (isTrigger) {
triggerDateChange($endDateInput, endDate);
}
}
}
if (isTrigger && isInputTrigger) {
if (!oldStartDate.isSame(startDate) || !oldEndDate.isSame(endDate)) {
triggerDateChange($this, startDate, isDateRangePickerTrigger);
triggerDateChange($input, startDate, isDateRangePickerTrigger);
}
}
}
function setDataDates(date, $selfInput, prefix){
date = AbpDate(date, options).date;
$selfInput.data('date', date);
$this.data(prefix + 'date', date);
$input.data(prefix + 'date', date);
}
function triggerDateChange($selfInput, value, isDateRangePickerTrigger) {
$selfInput.trigger('change');
if(isDateRangePickerTrigger !== false){
if(isEmptyDate(value, options)) {
$selfInput.trigger('cancel.daterangepicker', $dateRangePicker);
}else {
$selfInput.trigger('apply.daterangepicker', $dateRangePicker);
}
}
}
$input.on('apply.daterangepicker', function (ev, picker) {
if(startDate.isSame(picker.startDate) && (singleDatePicker || endDate.isSame(picker.endDate))) {
fillInput();
picker.hide();
return;
}
setStartDateByMomentDate(picker.startDate);
setEndDateByMomentEndDate(picker.endDate);
fillInput();
inputChangeHandler(true, true, false);
});
$input.on('show.daterangepicker', function (ev, picker) {
const today = moment();
if(isEmptyDate(startDate, options)){
picker.setStartDate(today);
}else{
picker.setStartDate(convertToMoment(startDate, options, options.inputDateFormat));
}
if(singleDatePicker){
picker.setEndDate(picker.startDate);
}else if(isEmptyDate(endDate, options)){
picker.setEndDate(today);
}
else{
picker.setEndDate(convertToMoment(endDate, options, options.inputDateFormat));
}
picker.updateView();
});
$input.on('cancel.daterangepicker', function (ev, picker) {
if(!$input.val()){
picker.hide();
return;
}
$input.val('');
setStartDateByMomentDate();
setEndDateByMomentEndDate();
inputChangeHandler(true, true, false);
});
$clearButton.on('click', function (e) {
$input.trigger('cancel.daterangepicker', $dateRangePicker);
});
$input.on('change', function (e) {
var dates = $input.val().split(options.separator);
var newStartDate = convertToMoment(dates[0], options, options.visibleDateFormat);
var newEndDate = undefined;
if (dates.length === 2) {
newEndDate = convertToMoment(dates[1], options, options.visibleDateFormat);
}else{
newEndDate = convertToMoment(undefined, options, options.visibleDateFormat);
}
if (startDate.isSame(newStartDate) && (singleDatePicker || endDate.isSame(newEndDate))) {
fillInput();
return;
}
setStartDateByMomentDate(newStartDate);
setEndDateByMomentEndDate(newEndDate);
if(newStartDate.isValid()){
$dateRangePicker.setStartDate(newStartDate);
}else{
$dateRangePicker.setStartDate();
}
if(newEndDate.isValid()){
$dateRangePicker.setEndDate(newEndDate);
}else{
$dateRangePicker.setEndDate();
}
fillInput();
inputChangeHandler(undefined, false);
});
function inputChangeHandler(isTrigger, isInputTrigger, isDateRangePickerTrigger) {
var value = $input.val();
if (value !== '') {
replaceOpenButton(true, singleOpenAndClearButton, $openButton, $clearButton);
} else {
replaceOpenButton(false, singleOpenAndClearButton, $openButton, $clearButton);
}
if (isEmptyDate(startDate, options)) {
replaceOpenButton(false, singleOpenAndClearButton, $openButton, $clearButton);
$this.val('');
}
changeDate(isTrigger, isInputTrigger, isDateRangePickerTrigger);
}
const setStartDateByMomentDate = (momentDate) => {
oldStartDate = startDate;
startDate = AbpDate(momentDate, options);
}
const setEndDateByMomentEndDate = (momentDate) => {
if(singleDatePicker){
return;
}
oldEndDate = endDate;
endDate = AbpDate(momentDate, options);
}
function startDateInputHandler(value) {
value = convertToMoment(value, options);
if (startDate.isSame(value)) {
return;
}
setStartDateByMomentDate(value);
$dateRangePicker.setStartDate(value);
fillInput();
inputChangeHandler(false);
}
function endDateInputHandler(value) {
value = convertToMoment(value, options);
if (endDate.isSame(value)) {
return;
}
setEndDateByMomentEndDate(value);
$dateRangePicker.setEndDate(value);
fillInput();
inputChangeHandler(false);
}
addHiddenDateInputSetListener($startDateInput[0], 'value', startDateInputHandler, options);
addHiddenDateInputSetListener($endDateInput[0], 'value', endDateInputHandler, options);
addHiddenDateInputSetListener($dateInput[0], 'value', startDateInputHandler, options);
inputChangeHandler(false, false, false);
});
}
$(function () {
abp.dom.initializers.initializeDateRangePickers($('body'));
});
})(jQuery);
Loading…
Cancel
Save