UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

996 lines (804 loc) 32.3 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); require('./kendo.core.js'); require('./kendo.userevents.js'); require('./kendo.licensing.js'); require('@progress/kendo-licensing'); const __meta__ = { id: "selectable", name: "Selectable", category: "framework", depends: [ "core", "userevents" ], advanced: true }; (function($, undefined$1) { let kendo = window.kendo, Widget = kendo.ui.Widget, support = kendo.support, abs = Math.abs, ARIASELECTED = "aria-selected", SELECTED = "k-selected", ACTIVE = "k-selecting", SELECTABLE = "k-selectable", CHANGE = "change", CHANGING = "changing", NS = ".kendoSelectable", UNSELECT = "unselect", UNSELECTING = "k-unselecting", HOVER = "k-hover", MID = "k-range-mid", SPLITEND = "k-range-split-end", SPLITSTART = "k-range-split-start", RANGESTART = "k-range-start", RANGEEND = "k-range-end", START = "start", END = "end", NONE = "none", MOUSEENTER = "mouseenter", MOUSELEAVE = "mouseleave", TOUCHSTART = "touchstart", TOUCHMOVE = "touchmove", TOUCHEND = "touchend", INPUTSELECTOR_ICONSSELECTOR_FONT = "span.k-icon.k-i-caret-alt-down,span.k-icon.k-i-caret-alt-up,.k-icon.k-i-caret-alt-down,.k-icon.k-i-caret-alt-right,.k-icon.k-i-caret-alt-left", INPUTSELECTOR_ICONSSELECTOR_SVG = INPUTSELECTOR_ICONSSELECTOR_FONT.replaceAll('k-i', 'k-svg-i'), INPUTSELECTOR_SVG_PARTS = INPUTSELECTOR_ICONSSELECTOR_SVG.split(",").map((selector) => selector + " *").join(","), INPUTSELECTOR = `input,a,textarea,.k-multiselect-wrap,select,button,${INPUTSELECTOR_ICONSSELECTOR_FONT},${INPUTSELECTOR_ICONSSELECTOR_SVG},${INPUTSELECTOR_SVG_PARTS},.k-button>span,.k-button>span *,.k-button>img,label.k-checkbox-label.k-no-text,span.k-numeric-wrap,.k-focusable`, msie = kendo.support.browser.msie, supportEventDelegation = false, extend = $.extend; (function($) { (function() { $('<div class="parent"><span></span></div>') .on("click", ">*", function() { supportEventDelegation = true; }) .find("span") .trigger("click") .end() .off(); })(); })($); const Selectable = Widget.extend({ init: function(element, options) { let that = this, multiple, dragToSelect, selectableClass; Widget.fn.init.call(that, element, options); selectableClass = that.selectableClass = that.options.selectableClass || SELECTABLE; that._marquee = $("<div class='k-marquee'><div class='k-marquee-color'></div></div>"); that._lastActive = null; that.element.addClass(selectableClass); that.relatedTarget = that.options.relatedTarget; multiple = that.options.multiple; dragToSelect = that.options.dragToSelect; that.userEvents = new kendo.UserEvents(that.element, { global: true, allowSelection: true, filter: (!supportEventDelegation ? "." + selectableClass + " " : "") + that.options.filter, tap: that._tap.bind(that), touchAction: multiple ? "none" : "pan-x pan-y" }); if (multiple) { if (dragToSelect) { that.userEvents .bind("hold", that._hold.bind(that)) .bind("start", that._start.bind(that)) .bind("move", that._move.bind(that)) .bind("end", that._end.bind(that)); } that.userEvents .bind("select", that._select.bind(that)); } }, events: [CHANGE, CHANGING, UNSELECT], options: { name: "Selectable", filter: ">*", inputSelectors: INPUTSELECTOR, multiple: false, holdToDrag: false, dragToSelect: true, relatedTarget: $.noop, ignoreOverlapped: false, addIdToRanges: false, toggleable: false, selectableClass: "" }, _isElement: function(target) { var elements = this.element; var idx, length = elements.length, result = false; target = target[0]; for (idx = 0; idx < length; idx ++) { if (elements[idx] === target) { result = true; break; } } return result; }, _tap: function(e) { let target = $(e.target), that = this, options = that.options, ctrlKey = e.event.ctrlKey || e.event.metaKey, multiple = that.options.multiple, shiftKey = multiple && e.event.shiftKey, selectedClass = that.options.selectedClass || SELECTED, selected, whichCode = e.event.which, buttonCode = e.event.button; //in case of hierarchy or right-click if (!that._isElement(target.closest("." + that.selectableClass)) || whichCode && whichCode == 3 || buttonCode && buttonCode == 2) { return; } if (!this._allowSelection(e.event.target)) { return; } if (that.trigger(CHANGING, { target: target, originalEvent: e.event })) { return; } selected = target.hasClass(selectedClass); target = target.add(that.relatedTarget(target)); if (!multiple) { if (selected && ctrlKey) { that._unselect(target); that._notify(CHANGE, e); } else if (!selected) { that.clear(); that.value(target, e); that._notify(CHANGE, e); } } else { if (shiftKey) { if (!that._lastRange || !compareElements(that._lastRange, target)) { that.selectRange(that._firstSelectee(), target, e); that._notify(CHANGE, e); } that._lastRange = target; } else { that._lastRange = null; if (selected && (ctrlKey || options.toggleable)) { that._unselect(target); that._notify(CHANGE, e); } else if (ctrlKey || options.toggleable) { that.value(target, e); that._notify(CHANGE, e); } else if (!selected || that.value().length > 1) { that.clear(); that.value(target, e); that._notify(CHANGE, e); } that._lastActive = that._downTarget = target; } } }, _hold: function(e) { if (this.options.holdToDrag) { // serves as a drag hint to indicate start of selection this._tap(e); } this._activated = true; }, _isActivated: function() { return this.options.holdToDrag ? this._activated : true; }, _start: function(e) { let that = this, target = $(e.target), selectedClass = that.options.selectedClass || SELECTED, selected = target.hasClass(selectedClass), currentElement, ctrlKey = e.event.ctrlKey || e.event.metaKey; if (!that._isActivated() || !this._allowSelection(e.event.target)) { return; } if (that.trigger(CHANGING, { target: target, originalEvent: e.event })) { that.userEvents.cancel(); return; } that._downTarget = target; //in case of hierarchy if (!that._isElement(target.closest("." + that.selectableClass))) { that.userEvents.cancel(); return; } if (that.options.useAllItems) { that._items = that.element.find(that.options.filter); } else { currentElement = target.closest(that.element); that._items = currentElement.find(that.options.filter); } e.sender.capture(); that._marquee .appendTo(document.body) .css({ left: e.x.client + 1, top: e.y.client + 1, width: 0, height: 0 }); if (!ctrlKey) { that.clear(); } target = target.add(that.relatedTarget(target)); if (selected) { that._selectElement(target, true); if (ctrlKey) { target.addClass(UNSELECTING); } } }, _move: function(e) { var that = this, position = { left: e.x.startLocation > e.x.location ? e.x.location : e.x.startLocation, top: e.y.startLocation > e.y.location ? e.y.location : e.y.startLocation, width: abs(e.x.initialDelta), height: abs(e.y.initialDelta) }; if (!that._isActivated()) { return; } that._marquee.css(position); that._invalidateSelectables(position, (e.event.ctrlKey || e.event.metaKey)); e.preventDefault(); }, _end: function(e) { var that = this, rangeSelectedAttr = kendo.attr("range-selected"), uid = kendo.guid(); if (!that._isActivated()) { return; } that._activated = false; that._marquee.remove(); that._unselect(that.element .find(that.options.filter + "." + UNSELECTING)) .removeClass(UNSELECTING); var target = that.element.find(that.options.filter + "." + ACTIVE); target = target.add(that.relatedTarget(target)); if (that.options.addIdToRanges) { for (var i = 0; i < that._currentlyActive.length; i++) { $(that._currentlyActive[i]).attr(rangeSelectedAttr, uid); } } if (!that._lastRange || !compareElements(that._lastRange, target)) { that.value(target, e); that._notify(CHANGE, e); } that._lastRange = target; that._lastActive = that._downTarget; that._items = null; }, _invalidateSelectables: function(position, ctrlKey) { var idx, length, target = this._downTarget[0], items = this._items, selectedClass = this.options.selectedClass || SELECTED, related, toSelect; this._currentlyActive = []; for (idx = 0, length = items.length; idx < length; idx ++) { toSelect = items.eq(idx); related = toSelect.add(this.relatedTarget(toSelect)); if (collision(toSelect, position)) { if (toSelect.hasClass(selectedClass)) { if (ctrlKey && target !== toSelect[0]) { related.removeClass(selectedClass).addClass(UNSELECTING); } } else if (!toSelect.hasClass(ACTIVE) && !toSelect.hasClass(UNSELECTING) && !this._collidesWithActiveElement(related, position)) { related.addClass(ACTIVE); } this._currentlyActive.push(related[0]); } else { if (toSelect.hasClass(ACTIVE)) { related.removeClass(ACTIVE); } else if (ctrlKey && toSelect.hasClass(UNSELECTING)) { related.removeClass(UNSELECTING).addClass(selectedClass); } } } }, _collidesWithActiveElement: function(element, marqueeRect) { if (!this.options.ignoreOverlapped) { return false; } var activeElements = this._currentlyActive; var elemRect = element[0].getBoundingClientRect(); var activeElementRect; var collision = false; var isRtl = kendo.support.isRtl(element); var leftRight = isRtl ? "right" : "left"; var tempRect = {}; marqueeRect.right = marqueeRect.left + marqueeRect.width; marqueeRect.bottom = marqueeRect.top + marqueeRect.height; for (var i = 0; i < activeElements.length; i++) { activeElementRect = activeElements[i].getBoundingClientRect(); if (overlaps(elemRect, activeElementRect)) { tempRect[leftRight] = leftRight === "left" ? activeElementRect.right : activeElementRect.left; elemRect = extend({}, elemRect, tempRect); if (elemRect.left > elemRect.right) { return true; } collision = !overlaps(elemRect, marqueeRect); } } return collision; }, value: function(val) { var that = this, selectElement = that._selectElement.bind(that); if (val) { val.each(function() { selectElement(this); }); return; } return that.element.find(that.options.filter + "." + (that.options.selectedClass || SELECTED)); }, selectedRanges: function() { var that = this; var rangeSelectedAttr = kendo.attr("range-selected"); var map = {}; that.element.find("[" + rangeSelectedAttr + "]").each(function(_, elem) { var rangeId = $(elem).attr(rangeSelectedAttr); var mapLocation = map[rangeId]; if (!mapLocation) { mapLocation = map[rangeId] = []; } mapLocation.push($(elem)); }); return map; }, selectedSingleItems: function() { var that = this; var rangeSelectedAttr = kendo.attr("range-selected"); return that.element.find(that.options.filter + "." + (that.options.selectedClass || SELECTED) + ":not([" + rangeSelectedAttr + "])").toArray().map(function(elem) { return $(elem); }); }, _firstSelectee: function() { var that = this, selected; if (that._lastActive !== null) { return that._lastActive; } selected = that.value(); return selected.length > 0 ? selected[0] : that.element.find(that.options.filter)[0]; }, _selectElement: function(element, preventNotify) { var toSelect = $(element), selectedClass = this.options.selectedClass || SELECTED, isPrevented = !preventNotify && this._notify("select", { element: element }); toSelect.removeClass(ACTIVE); if (!isPrevented) { toSelect.addClass(selectedClass); if (this.options.aria) { toSelect.attr(ARIASELECTED, true); } } }, _notify: function(name, args) { args = args || { }; return this.trigger(name, args); }, _unselect: function(element) { if (this.trigger(UNSELECT, { element: element })) { return; } var rangeSelectedAttr = kendo.attr("range-selected"); element.removeClass(this.options.selectedClass || SELECTED).removeAttr(rangeSelectedAttr); if (this.options.aria) { element.attr(ARIASELECTED, false); } return element; }, _select: function(e) { if (this._allowSelection(e.event.target)) { if (!msie || (msie && !$(kendo._activeElement()).is(this.options.inputSelectors))) { if (this._allowPreventDefault(e.event.target)) { e.preventDefault(); } } } }, _allowPreventDefault: function(target) { var disallowedSelectors = ".k-table-td"; // Required for the paste event in the Grid to work in Chrome. return !$(target).is(disallowedSelectors) || !this.options.allowPaste; }, _allowSelection: function(target) { if ($(target).is(this.options.inputSelectors)) { this.userEvents.cancel(); this._downTarget = null; return false; } return true; }, resetTouchEvents: function() { this.userEvents.cancel(); }, clear: function() { var items = this.element.find(this.options.filter + "." + (this.options.selectedClass || SELECTED)); this._unselect(items); }, selectRange: function(start, end) { var that = this, idx, tmp, items; that.clear(); if (that.element.length > 1) { items = that.options.continuousItems(); } if (!items || !items.length) { items = that.element.find(that.options.filter); } start = $.inArray($(start)[0], items); end = $.inArray($(end)[0], items); if (start > end) { tmp = start; start = end; end = tmp; } if (!that.options.useAllItems) { end += that.element.length - 1; } for (idx = start; idx <= end; idx ++ ) { that._selectElement(items[idx], true); } }, destroy: function() { var that = this; Widget.fn.destroy.call(that); that.element.off(NS); that.userEvents.destroy(); that._marquee = that._lastActive = that.element = that.userEvents = null; } }); const RangeSelectable = Widget.extend({ init: function(element, options) { let that = this, ns, cellSelectorValid; Widget.fn.init.call(that, element, options); that.widget = options.widget; ns = options.ns; cellSelectorValid = options.filter; that.userEvents = new kendo.UserEvents(that.element, { global: true, allowSelection: true, filter: that.options.filter, tap: that._tap.bind(that), touchAction: NONE }); if (support.touch) { element.on(TOUCHSTART + ns, cellSelectorValid, that._mouseEnter.bind(that)) .on(TOUCHEND + ns + " " + TOUCHMOVE + ns, cellSelectorValid, that._mouseLeave.bind(that)); } else { element.on(MOUSEENTER + ns, cellSelectorValid, that._mouseEnter.bind(that)) .on(MOUSELEAVE + ns, cellSelectorValid, that._mouseLeave.bind(that)); } }, events: [CHANGE], options: { name: "RangeSelectable", filter: ">*", inputSelectors: INPUTSELECTOR, resetOnStart: false, multiple: false, dragToSelect: true, cellSelector: "*", ns: "", reverse: false, relatedTarget: $.noop }, destroy: function() { let that = this; Widget.fn.destroy.call(that); that.userEvents.destroy(); that.widget = null; that._lastActive = that.element = that.userEvents = that._start = that._end = null; }, _allowSelection: function(target) { if ($(target).is(this.options.inputSelectors)) { this.userEvents.cancel(); return false; } return true; }, _mouseEnter: function(e) { let that = this, cell = $(e.currentTarget), range; cell.addClass(HOVER); range = that.widget.selectRange(); if (that.options.resetOnStart && range.end) { return; } if (range.target === START && that._end) { that.range(cell, that._end, true, that.options.reverse); } if (range.target === END) { that.range(that._start, cell, true, that.options.reverse); } }, _mouseLeave: function(e) { $(e.currentTarget).removeClass(HOVER); }, start: function(element, preventFlagUpdate) { if (element === undefined$1 || element === null) { return this._start; } element.addClass(SELECTED + " " + RANGESTART).attr(ARIASELECTED, true); if (!preventFlagUpdate) { this._start = element; } }, end: function(element, preventFlagUpdate) { if (element === undefined$1 || element === null) { return this._start; } element.addClass(SELECTED + " " + RANGEEND).attr(ARIASELECTED, true); if (!preventFlagUpdate) { this._end = element; } }, mid: function(elements) { let tables = this.element.find("table"), options = this.options; elements.addClass(MID).attr(ARIASELECTED, true); tables.each(function() { let that = $(this); let lastCell = that.find(options.cellSelectorValid).last(); let firstCell = that.find(options.cellSelectorValid).first(); if (lastCell.hasClass(MID)) { lastCell.addClass(SPLITEND); } if (firstCell.hasClass(MID)) { firstCell.addClass(SPLITSTART); } }); }, clear: function(clearVariables) { let options = this.options; this.element.find(options.cellSelector) .removeClass(MID + " " + SPLITEND + " " + SPLITSTART); this.clearStartEnd(); if (clearVariables) { this._start = this._end = null; } }, clearStartEnd: function() { let that = this, options = that.options; that.element.find(options.cellSelector).removeClass(RANGESTART + " " + SELECTED + " " + RANGEEND).removeAttr(ARIASELECTED); }, selectFrom: function(start) { let that = this, options = this.options, items, startIdx; items = that.element.find(options.cellSelector); startIdx = $.inArray($(start)[0], items); that.clear(); that.start(start); items = items.filter(function(index) { return index > startIdx; }); that.mid(items); }, selectTo: function(end) { let that = this, options = this.options, items, endIdx; items = that.element.find(options.cellSelector); endIdx = $.inArray($(end)[0], items); that.clear(); items = items.filter(function(index) { return index < endIdx; }); that.mid(items); that.end($(end)); }, range: function(start, end, preventFlagUpdate, invert) { let that = this, options = this.options, items, startIdx, endIdx; if (start === undefined$1) { return { start: that._start, end: that._end }; } that._clearFlags(); items = that.element.find(options.cellSelector); startIdx = $.inArray($(start)[0], items); endIdx = $.inArray($(end)[0], items); if (!start || (start && !start.length)) { that._useStart = true; } that.clear(); if (start) { that.start($(start), preventFlagUpdate); } items = items.filter(function(index) { if (endIdx < 0 || (!start && startIdx < 0)) { return; } return (index > startIdx && index < endIdx) || options.reverse && (index < startIdx && index > endIdx); }); that.mid(items); if (end) { that.end($(end), preventFlagUpdate); } else { that._useEnd = true; } if (startIdx > endIdx && invert) { that.clearStartEnd(); that.start($(end), true); that.end($(start), true); } }, change: function() { this.trigger(CHANGE); }, _clearFlags: function() { this._useStart = this._useEnd = false; }, _tap: function(e) { let target = $(e.target), that = this, range = that.widget.selectRange() || {}, start = range.start, end = range.end, currentDate = kendo.calendar.toDateObject($(target).find("span")), options = that.options, resetOnStart = options.resetOnStart; that._lastActive = target; if (!start && !end) { that.clear(true); if (range.target === START) { that.start(target); } if (range.target === END) { that.end(target); } that._clearFlags(); that.trigger(CHANGE); return; } if (!start && end) { if (range.target === END) { that.end(target); } else { if (+currentDate > +range.end && !options.reverse) { that.clear(true); that.start(target); } else { that.range(target, that._end, false, true); } } that.trigger(CHANGE); that._clearFlags(); return; } if (start && !end) { if (range.target === END && !options.reverse && +start > +currentDate) { that.clear(true); if (resetOnStart) { that.start(target); } else { that.end(target); } } else if (range.target === START) { that.start(target); } else { that.range(that._start, target, false, true); } that.trigger(CHANGE); that._clearFlags(); return; } if (start && end) { if (!options.reverse) { if (+start > +currentDate && range.target === END) { that.clear(true); if (resetOnStart) { that.start(target); that.end(null); range.target = START; } else { that.start(null); that.end(target); } that.trigger(CHANGE); return; } if (+start < +currentDate && range.target === START) { if (+currentDate > +range.end) { that.clear(true); that.start(target); that.end(null); } else { that.range(target, that._end); } that.trigger(CHANGE); return; } if (range.target === START) { that.range(target, that._end); } if (range.target === END) { that.range(that._start, target); } that.trigger(CHANGE); return; } if (resetOnStart) { if (range.target === START) { that.range(target, that._end, false, true); } else { that.range(that._start, target, false, true); } } else { if (range.target === START) { that.start(target); } else { that.end(target); } } that.trigger(CHANGE); } } }); Selectable.parseOptions = function(selectable) { var selectableMode = selectable.mode || selectable; var asLowerString = typeof selectableMode === "string" && selectableMode.toLowerCase(); return { multiple: asLowerString && asLowerString.indexOf("multiple") > -1, cell: asLowerString && asLowerString.indexOf("cell") > -1, range: asLowerString && asLowerString.indexOf("range") > -1, single: asLowerString && asLowerString.indexOf("single") > -1 }; }; function compareElements(element, toCompare) { if (element.length !== toCompare.length) { return false; } for (var i = 0; i < element.length; i++) { if (element[i] !== toCompare[i]) { return false; } } return true; } function collision(element, position) { if (!element.is(":visible")) { return false; } var elementPosition = kendo.getOffset(element), right = position.left + position.width, bottom = position.top + position.height; elementPosition.right = elementPosition.left + kendo._outerWidth(element); elementPosition.bottom = elementPosition.top + kendo._outerHeight(element); return !(elementPosition.left > right || elementPosition.right < position.left || elementPosition.top > bottom || elementPosition.bottom < position.top); } function overlaps(firstRect, secondRect) { return !(firstRect.right <= secondRect.left || firstRect.left >= secondRect.right || firstRect.bottom <= secondRect.top || firstRect.top >= secondRect.bottom); } kendo.ui.plugin(Selectable); kendo.ui.plugin(RangeSelectable); })(window.kendo.jQuery); var kendo$1 = kendo; exports.__meta__ = __meta__; exports.default = kendo$1;