UNPKG

@progress/telerik-jquery-report-viewer

Version:

Progress® Telerik® Report Viewer for jQuery

917 lines (914 loc) 31.6 kB
import { parseToLocalDate, areEqual, stringFormat, adjustTimezone, tryParseInt, areEqualArrays, unadjustTimezone, isSpecialKey } from './utils.js'; import { stringResources } from './stringResources.js'; import { ParameterEditorTypes, ParameterTypes } from './enums.js'; var parameterEditorsMatch = { // AvailableValues PROVIDED, MultiValue is TRUE and trv.parameters.editors.multiSelect is unset MultiSelect: function(parameter, editorsType) { return Boolean(parameter.availableValues) && parameter.multivalue && (!editorsType || !editorsType.multiSelect || editorsType.multiSelect !== ParameterEditorTypes.COMBO_BOX); }, // AvailableValues PROVIDED, MultiValue is TRUE and trv.parameters.editors.multiSelect is set to COMBO_BOX MultiSelectCombo: function(parameter, editorsType) { return Boolean(parameter.availableValues) && parameter.multivalue && (editorsType && editorsType.multiSelect && editorsType.multiSelect === ParameterEditorTypes.COMBO_BOX); }, // AvailableValues PROVIDED, MultiValue is FALSE and trv.parameters.editors.singleSelect is unset SingleSelect: function(parameter, editorsType) { return Boolean(parameter.availableValues) && !parameter.multivalue && (!editorsType || !editorsType.singleSelect || editorsType.singleSelect !== ParameterEditorTypes.COMBO_BOX); }, // AvailableValues PROVIDED, MultiValue is FALSE and trv.parameters.editors.singleSelect is set to COMBO_BOX SingleSelectCombo: function(parameter, editorsType) { return Boolean(parameter.availableValues) && !parameter.multivalue && (editorsType && editorsType.singleSelect && editorsType.singleSelect === ParameterEditorTypes.COMBO_BOX); }, // AvailableValues NOT PROVIDED and MultiValue is TRUE MultiValue: function(parameter) { return Boolean(parameter.multivalue); }, DateTime: function(parameter) { return parameter.type === ParameterTypes.DATETIME; }, String: function(parameter) { return parameter.type === ParameterTypes.STRING; }, Number: function(parameter) { switch (parameter.type) { case ParameterTypes.INTEGER: case ParameterTypes.FLOAT: return true; default: return false; } }, Boolean: function(parameter) { return parameter.type === ParameterTypes.BOOLEAN; }, Default: function(parameter) { return true; } }; var multivalueUtils = function() { var lineSeparator = "\n"; return { formatValue: function(value) { var text = ""; if (value) { [].concat(value).forEach(function(val) { if (text.length > 0) { text += lineSeparator; } text += val; }); } return text; }, parseValues: function(text) { return ("" + text).split(lineSeparator); } }; }(); function integerInputBehavior(input) { function isValid(newValue) { return /^(\-|\+)?([0-9]*)$/.test(newValue); } function onKeyPress(event) { if (isSpecialKey(event.keyCode)) { return true; } return isValid($(input).val() + String.fromCharCode(event.charCode)); } function onPaste(event) { } function attach(input2) { $(input2).on("keypress", onKeyPress).on("paste", onPaste); } function detach(input2) { $(input2).off("keypress", onKeyPress).off("paste", onPaste); } attach(input); return { dispose: function() { detach(input); } }; } function floatInputBehavior(input) { function isValid(newValue) { return /^(\-|\+)?([0-9]*(\.[0-9]*)?)$/.test(newValue); } function onKeyPress(event) { if (isSpecialKey(event.keyCode)) { return true; } return isValid($(input).val() + String.fromCharCode(event.charCode)); } function onPaste(event) { } function attach(input2) { $(input2).on("keypress", onKeyPress).on("paste", onPaste); } function detach(input2) { $(input2).off("keypress", onKeyPress).off("paste", onPaste); } attach(input); return { dispose: function() { detach(input); } }; } function applyClass(apply, cssClass, item) { var fn = apply ? $.fn.addClass : $.fn.removeClass; fn.call(item, cssClass); } function enableItem(item, enable) { applyClass(!enable, "k-disabled", item); } function selectItem(item, select) { applyClass(select, "k-selected", item); item.attr("aria-selected", select); } function addAccessibilityAttributes(editor, type, caption, additionalInfo, error) { if (!additionalInfo) { additionalInfo = ""; } var label = stringFormat("{0}. {1} {2}. {3}", [caption, type, stringResources.ariaLabelParameter, additionalInfo]); editor.attr("aria-label", label); setAccessibilityErrorAttributes(editor, error); } var containerTabIndex; var editorsIndex = 0; function setEditorTabIndex(editor) { if (!containerTabIndex) { var $container = $("div.trv-parameters-area-content"); if ($container.length > 0) { var tabIndexAttr = $container.attr("tabIndex"); if (tabIndexAttr) { containerTabIndex = tryParseInt(tabIndexAttr); } } if (!containerTabIndex || isNaN(containerTabIndex)) { containerTabIndex = 300; } } var wrapper = editor.closest(".trv-parameter-value"); var selectAll = wrapper.find(".trv-select-all"); var clearSelection = wrapper.find(".trv-select-none"); var widgetParent = editor.closest(".k-widget"); var hasFocusableElement = widgetParent.find(".k-input"); var isComboWidget = hasFocusableElement && hasFocusableElement.length; if (selectAll && selectAll.length) { selectAll.attr("tabindex", containerTabIndex + ++editorsIndex); } if (clearSelection && clearSelection.length) { clearSelection.attr("tabindex", containerTabIndex + ++editorsIndex); } if (isComboWidget) { hasFocusableElement.attr("tabindex", containerTabIndex + ++editorsIndex); } else { editor.attr("tabindex", containerTabIndex + ++editorsIndex); } } function setAccessibilityErrorAttributes(editor, error) { var errToken = stringFormat(" {0}:", [stringResources.ariaLabelErrorMessage]); var label = editor.attr("aria-label"); if (!label) { return; } var errIdx = label.indexOf(errToken); if (errIdx > -1) { label = label.substring(0, errIdx); } if (error && error !== "") { editor.attr("aria-required", true); editor.attr("aria-invalid", true); label += errToken + error; } else { editor.removeAttr("aria-invalid"); } editor.attr("aria-label", label); } function navigatableEnabledForList(enableAccessibility) { return kendo.version >= "2017.3.1018" || enableAccessibility; } var ParameterEditors = [ { match: parameterEditorsMatch.MultiSelect, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); var enabled = true; $placeholder.html(options.templates["trv-parameter-editor-available-values-multiselect"]); var $list = $placeholder.find(".trv-list"); var $selectAll = $placeholder.find(".trv-select-all"); var $selectNone = $placeholder.find(".trv-select-none"); var listView; var parameter; var updateTimeout; var valueChangeCallback = options.parameterChanged; var initialized; $selectAll.text(stringResources[$selectAll.text()]); $selectAll.click(function(e) { e.preventDefault(); if (!enabled) return; setSelectedItems(parameter.availableValues.map(function(av) { return av.value; })); }); $selectNone.text(stringResources[$selectNone.text()]); $selectNone.click(function(e) { e.preventDefault(); if (!enabled) return; setSelectedItems([]); }); function onSelectionChanged(selection) { if (initialized) { applyAriaSelected(selection); notifyParameterChanged(selection); } } function applyAriaSelected(selection) { var children = $list.find(".trv-listviewitem"); Array.from(children).forEach((item) => { var $item = $(item); var isSelected = selection.filter($item).length > 0; $item.attr("aria-selected", isSelected); }); } function notifyParameterChanged(selection) { var availableValues = parameter.availableValues; var values = $.map(selection, function(item) { return availableValues[$(item).index()].value; }); clearPendingChange(); var immediateUpdate = !parameter.autoRefresh && !parameter.childParameters; updateTimeout = window.setTimeout( function() { if (!areEqualArrays(parameter.value, values)) { valueChangeCallback(parameter, values); } updateTimeout = null; }, immediateUpdate ? 0 : 1e3 ); } function clearPendingChange() { if (updateTimeout) { window.clearTimeout(updateTimeout); } } function getSelectedItems() { return $(listView.element).find(".k-selected"); } function onItemClick(e) { if (!enabled) return; var clickedItem = $(e.target); var selectedItems = listView.select(); if (clickedItem.hasClass("k-selected")) { selectedItems.splice($.inArray(clickedItem[0], selectedItems), 1); } else { selectedItems.push(clickedItem); } listView.clearSelection(); listView.select(selectedItems); listView.trigger("change"); } function onChange(e) { onSelectionChanged(getSelectedItems()); } function onKeydown(event) { if (!enabled) return; if (event.which !== 32) { return; } var focused = listView.element.find(".k-focus"); if (focused.length > 0) { focused.toggleClass("k-selected"); onSelectionChanged(getSelectedItems()); event.preventDefault(); } } function init() { setEditorTabIndex($list); setSelectedItems(parameter.value); listView.element.off().on("touch click", ".trv-listviewitem", onItemClick); listView.element.on("keydown", onKeydown); initialized = true; } function clear() { initialized = false; if (listView) { listView.element.off("touch click", ".trv-listviewitem", onItemClick); listView.element.off("keydown", onKeydown); } } function setSelectedItems(items) { setSelectedItemsCore(items); onSelectionChanged(getSelectedItems()); } function setSelectedItemsCore(items) { if (!Array.isArray(items)) { items = [items]; } var children = $list.find(".trv-listviewitem"); $.each(parameter.availableValues, (i, av) => { var selected = false; $.each(items, (j, v) => { var availableValue = av.value; if (v instanceof Date) { availableValue = parseToLocalDate(av.value); } selected = areEqual(v, availableValue); return !selected; }); selectItem($(children[i]), selected); }); } return { beginEdit: function(param) { clear(); parameter = param; try { listView = $list.kendoListView({ template: kendo.template('<div class="trv-listviewitem" style="cursor: pointer">${name}</div>'), dataSource: { data: parameter.availableValues }, selectable: "MULTIPLE", navigatable: navigatableEnabledForList(options.enableAccessibility), change: onChange }).data("kendoListView"); } catch (e) { console.error("Instantiation of Kendo ListView as MultiSelect parameter editor threw an exception", e); throw e; } init(); }, enable: function(enable) { enabled = enable; enableItem($list, enabled); }, clearPendingChange, addAccessibility: function(param) { var info = stringFormat(stringResources.ariaLabelParameterInfo, [param.availableValues.length]); addAccessibilityAttributes($list, stringResources.ariaLabelMultiSelect, param.text, info, param.Error); $list.attr("aria-multiselectable", "true"); var items = $list.find(".trv-listviewitem"); Array.from(items).forEach((item) => { $(item).attr("aria-label", item.innerText); }); }, setAccessibilityErrorState: function(param) { setAccessibilityErrorAttributes($list, param.Error); }, destroy: function() { listView.destroy(); } }; } }, { match: parameterEditorsMatch.MultiSelectCombo, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); var enabled = true; var selector = ".trv-combo"; var template = "trv-parameter-editor-available-values-multiselect-combo"; var valueChangeCallback = options.parameterChanged; var $editorDom; var $selectNone; var $selectAll; var editor; var updateTimeout; var popUpIsClosed = true; var parameter; $placeholder.html(options.templates[template]); $editorDom = $placeholder.find(selector); $selectNone = $placeholder.find(".trv-select-none"); if ($selectNone) { $selectNone.text(stringResources[$selectNone.text()]); $selectNone.click(function(e) { e.preventDefault(); editor.value([]); editor.trigger("change"); }); } $selectAll = $placeholder.find(".trv-select-all"); if ($selectAll) { $selectAll.text(stringResources[$selectAll.text()]); $selectAll.click(function(e) { e.preventDefault(); if (!enabled) return; var values = $.map(parameter.availableValues, function(dataItem) { return dataItem.value; }); editor.value(values); editor.trigger("change"); }); } function onSelectionChanged(selection) { notifyParameterChanged(selection); } function notifyParameterChanged(values) { clearPendingChange(); var immediateUpdate = !parameter.autoRefresh && !parameter.childParameters; updateTimeout = window.setTimeout( function() { if (!areEqualArrays(parameter.value, values)) { valueChangeCallback(parameter, values); } updateTimeout = null; }, immediateUpdate ? 0 : 1e3 ); } function clearPendingChange() { if (updateTimeout) { window.clearTimeout(updateTimeout); } } function getSelectedItems() { return editor.value(); } function onChange() { if (popUpIsClosed) { onSelectionChanged(getSelectedItems()); } } function init() { setEditorTabIndex($editorDom); editor.bind("change", onChange); } function reset() { if (editor) { editor.unbind("change", onChange); } } return { beginEdit: function(param) { reset(); parameter = param; try { editor = $editorDom.kendoMultiSelect({ itemTemplate: '<div class="trv-editoritem">${name}</div>', dataSource: parameter.availableValues, dataTextField: "name", dataValueField: "value", value: parameter.value, filter: "contains", autoClose: false, open: function() { popUpIsClosed = false; }, close: function(e) { popUpIsClosed = true; onChange(); }, autoWidth: true, clearButton: false }).data("kendoMultiSelect"); } catch (e) { console.error("Instantiation of Kendo MultiSelect as MultiSelectCombo parameter editor threw an exception", e); throw e; } init(); }, enable: function(enable) { enabled = enable; editor.enable(enable); }, clearPendingChange, addAccessibility: function(param) { var $accessibilityDom = editor.input; var info = stringFormat(stringResources.ariaLabelParameterInfo, [param.availableValues.length]); addAccessibilityAttributes($accessibilityDom, stringResources.ariaLabelMultiSelect, param.text, info, param.Error); var items = editor.items(); Array.from(items).forEach((item) => { $(item).attr("aria-label", item.innerText); }); }, setAccessibilityErrorState: function(param) { setAccessibilityErrorAttributes($editorDom, param.Error); }, destroy: function() { editor.destroy(); } }; } }, { match: parameterEditorsMatch.SingleSelect, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); var enabled = true; $placeholder.html(options.templates["trv-parameter-editor-available-values"]); var $list = $placeholder.find(".trv-list"); var $selectNone = $placeholder.find(".trv-select-none"); var listView; var parameter; var valueChangeCallback = options.parameterChanged; if ($selectNone) { $selectNone.text(stringResources[$selectNone.text()]); $selectNone.click(function(e) { e.preventDefault(); listView.clearSelection(); listView.trigger("change"); }); } function onSelectionChanged(selection) { notifyParameterChanged(selection); } function notifyParameterChanged(selection) { var availableValues = parameter.availableValues; var values = $.map(selection, function(item) { return availableValues[$(item).index()].value; }); if (Array.isArray(values)) { values = values[0]; } valueChangeCallback(parameter, values); } function getSelectedItems() { return listView.select(); } function onChange() { onSelectionChanged(getSelectedItems()); } function init() { setEditorTabIndex($list); setSelectedItems(parameter.value); listView.bind("change", onChange); } function reset() { if (listView) { listView.unbind("change", onChange); } } function setSelectedItems(value) { var items = $list.find(".trv-listviewitem"); $.each(parameter.availableValues, (i, av) => { var availableValue = av.value; if (value instanceof Date) { availableValue = parseToLocalDate(av.value); } if (areEqual(value, availableValue)) { listView.select(items[i]); return false; } return true; }); } return { beginEdit: function(param) { reset(); parameter = param; try { listView = $list.kendoListView({ template: '<div class="trv-listviewitem">${name}</div>', dataSource: { data: parameter.availableValues }, selectable: true, navigatable: navigatableEnabledForList(options.enableAccessibility) }).data("kendoListView"); } catch (e) { console.error("Instantiation of Kendo ListView as SingleSelect parameter editor threw an exception", e); throw e; } init(); }, enable: function(enable) { enabled = enable; enableItem($list, enabled); if (enabled) { listView.bind("change", onChange); $list.addClass("k-selectable"); } else { listView.unbind("change", onChange); $list.removeClass("k-selectable"); } }, addAccessibility: function(param) { var info = stringFormat(stringResources.ariaLabelParameterInfo, [param.availableValues.length]); addAccessibilityAttributes($list, stringResources.ariaLabelSingleValue, param.text, info, param.Error); var items = $list.find(".trv-listviewitem"); Array.from(items).forEach((item) => { $(item).attr("aria-label", item.innerText); }); }, setAccessibilityErrorState: function(param) { setAccessibilityErrorAttributes($list, param.Error); }, destroy: function() { listView.destroy(); } }; } }, { match: parameterEditorsMatch.SingleSelectCombo, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); var selector = ".trv-combo"; var template = "trv-parameter-editor-available-values-combo"; var valueChangeCallback = options.parameterChanged; var $editorDom; var $selectNone; var editor; var parameter; $placeholder.html(options.templates[template]); $editorDom = $placeholder.find(selector); $selectNone = $placeholder.find(".trv-select-none"); if ($selectNone) { $selectNone.text(stringResources[$selectNone.text()]); $selectNone.click(function(e) { e.preventDefault(); editor.value(""); editor.trigger("change"); }); } function onSelectionChanged(selection, value) { notifyParameterChanged(selection, value); } function notifyParameterChanged(selection, value) { var values = value || ""; var availableValues; if (!value && selection >= 0) { availableValues = parameter.availableValues; values = availableValues[selection].value; } valueChangeCallback(parameter, values); } function getSelectedItems() { return editor.select(); } function onChange(e) { onSelectionChanged(getSelectedItems(), this.value()); } function init() { setEditorTabIndex($editorDom); editor.bind("change", onChange); } function reset() { if (editor) { editor.unbind("change", onChange); } } return { beginEdit: function(param) { reset(); parameter = param; try { editor = $editorDom.kendoComboBox({ template: '<div class="trv-editoritem">${name}</div>', dataSource: parameter.availableValues, dataTextField: "name", dataValueField: "value", value: parameter.value, filter: "contains", suggest: true, clearButton: false }).data("kendoComboBox"); } catch (e) { console.error("Instantiation of Kendo ComboBox as SingleSelectCombo parameter editor threw an exception", e); throw e; } init(); }, enable: function(enable) { editor.enable(enable); }, addAccessibility: function(param) { var $accessibilityDom = editor.input; var info = stringFormat(stringResources.ariaLabelParameterInfo, [param.availableValues.length]); addAccessibilityAttributes($accessibilityDom, stringResources.ariaLabelSingleValue, param.text, info, param.Error); var items = editor.items(); Array.from(items).forEach((item) => { $(item).attr("aria-label", item.innerText); }); }, setAccessibilityErrorState: function(param) { setAccessibilityErrorAttributes($editorDom, param.Error); }, destroy: function() { editor.destroy(); } }; } }, { match: parameterEditorsMatch.MultiValue, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); var parameter; $placeholder.html(options.templates["trv-parameter-editor-multivalue"]); var $textArea = $placeholder.find("textarea").on("change", function() { if (options.parameterChanged) { options.parameterChanged(parameter, multivalueUtils.parseValues(this.value)); } }); function setValue(value) { parameter.value = value; $textArea.val(multivalueUtils.formatValue(value)); } return { beginEdit: function(param) { parameter = param; setValue(param.value); setEditorTabIndex($textArea); }, enable: function(enable) { enableItem($textArea, enable); $textArea.prop("disabled", !enable); }, addAccessibility: function(param) { addAccessibilityAttributes($textArea, stringResources.ariaLabelMultiValue, param.text, null, param.Error); }, setAccessibilityErrorState: function(param) { setAccessibilityErrorAttributes($textArea, param.Error); } }; } }, { match: parameterEditorsMatch.DateTime, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); var parameter; $placeholder.html(options.templates["trv-parameter-editor-datetime"]); try { var $dateTimePicker = $placeholder.find("input[type=datetime]").kendoDatePicker({ change: function() { var handler = options.parameterChanged; if (handler) { var dtv = this.value(); if (null !== dtv) { dtv = adjustTimezone(dtv); } handler(parameter, dtv); } } }); var dateTimePicker = $dateTimePicker.data("kendoDatePicker"); } catch (e) { console.error("Instantiation of Kendo DatePicker as DateTime parameter editor threw an exception", e); throw e; } function setValue(value) { parameter.value = value; var dt = null; try { if (value) { dt = unadjustTimezone(value); } } catch (e) { dt = null; } dateTimePicker.value(dt); } return { beginEdit: function(param) { parameter = param; setValue(param.value); setEditorTabIndex($dateTimePicker); }, enable: function(enable) { dateTimePicker.enable(enable); enableItem($dateTimePicker, enable); }, addAccessibility: function(param) { addAccessibilityAttributes($dateTimePicker, stringResources.ariaLabelParameterDateTime, param.text, null, param.Error); $dateTimePicker.attr("aria-live", "assertive"); }, setAccessibilityErrorState: function(param) { setAccessibilityErrorAttributes($dateTimePicker, param.Error); }, destroy: function() { dateTimePicker.destroy(); } }; } }, { match: parameterEditorsMatch.String, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); var parameter; $placeholder.html(options.templates["trv-parameter-editor-text"]); var $input = $placeholder.find('input[type="text"]').change(function() { if (options.parameterChanged) { options.parameterChanged(parameter, $input.val()); } }); function setValue(value) { parameter.value = value; $input.val(value); } return { beginEdit: function(param) { parameter = param; setValue(param.value); setEditorTabIndex($input); }, enable: function(enabled) { $input.prop("disabled", !enabled); enableItem($input, enabled); }, addAccessibility: function(param) { addAccessibilityAttributes($input, stringResources.ariaLabelParameterString, param.text, null, param.Error); $input.attr("aria-live", "assertive"); }, setAccessibilityErrorState: function(param) { setAccessibilityErrorAttributes($input, param.Error); } }; } }, { match: parameterEditorsMatch.Number, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); var parameter; var inputBehavior; $placeholder.html(options.templates["trv-parameter-editor-number"]); var $input = $placeholder.find("input[type=number]").on("change", function() { if (options.parameterChanged) { options.parameterChanged(parameter, $input.val()); } }); return { beginEdit: function(param) { if (inputBehavior) { inputBehavior.dispose(); } parameter = param; $input.val(parameter.value); if (parameter.type === ParameterTypes.INTEGER) { inputBehavior = integerInputBehavior($input); } else { inputBehavior = floatInputBehavior($input); } setEditorTabIndex($input); }, enable: function(enable) { $input.prop("disabled", !enable); enableItem($input, enable); }, addAccessibility: function(param) { addAccessibilityAttributes($input, stringResources.ariaLabelParameterNumerical, param.text, null, param.Error); $input.attr("aria-live", "assertive"); }, setAccessibilityErrorState: function(param) { setAccessibilityErrorAttributes($input, param.Error); } }; } }, { match: parameterEditorsMatch.Boolean, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); var parameter; $placeholder.html(options.templates["trv-parameter-editor-boolean"]); var $input = $placeholder.find("input[type=checkbox]").on("change", function() { if (options.parameterChanged) { options.parameterChanged(parameter, this.checked); } }); function setValue(value) { parameter.value = value; $input[0].checked = value === true; } return { beginEdit: function(param) { parameter = param; setValue(param.value); setEditorTabIndex($input); }, enable: function(enable) { enableItem($input, enable); $input.attr("disabled", !enable); }, addAccessibility: function(param) { addAccessibilityAttributes($input, stringResources.ariaLabelParameterBoolean, param.text, null, param.Error); $input.attr("aria-live", "assertive"); }, setAccessibilityErrorState: function(param) { setAccessibilityErrorAttributes($input, param.Error); } }; } }, { match: parameterEditorsMatch.Default, createEditor: function(placeholder, options) { var $placeholder = $(placeholder); $placeholder.html('<div class="trv-parameter-editor-generic"></div>'); return { beginEdit: function(parameter) { $placeholder.find(".trv-parameter-editor-generic").text(parameter.Error ? "(error)" : parameter.value); }, enable: function(enable) { } }; } } ]; export { ParameterEditors, parameterEditorsMatch };