You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
8.6 KiB
222 lines
8.6 KiB
// Copyright (c) MudBlazor 2021
|
|
// MudBlazor licenses this file to you under the MIT license.
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
class MudJsEventFactory {
|
|
connect(dotNetRef, elementId, options) {
|
|
//console.log('[MudBlazor | MudJsEventFactory] connect ', { dotNetRef, elementId, options });
|
|
if (!elementId)
|
|
throw "[MudBlazor | JsEvent] elementId: expected element id!";
|
|
var element = document.getElementById(elementId);
|
|
if (!element)
|
|
throw "[MudBlazor | JsEvent] no element found for id: " + elementId;
|
|
if (!element.mudJsEvent)
|
|
element.mudJsEvent = new MudJsEvent(dotNetRef, options);
|
|
element.mudJsEvent.connect(element);
|
|
}
|
|
|
|
disconnect(elementId) {
|
|
var element = document.getElementById(elementId);
|
|
if (!element || !element.mudJsEvent)
|
|
return;
|
|
element.mudJsEvent.disconnect();
|
|
}
|
|
|
|
subscribe(elementId, eventName) {
|
|
//console.log('[MudBlazor | MudJsEventFactory] subscribe ', { elementId, eventName});
|
|
if (!elementId)
|
|
throw "[MudBlazor | JsEvent] elementId: expected element id!";
|
|
var element = document.getElementById(elementId);
|
|
if (!element)
|
|
throw "[MudBlazor | JsEvent] no element found for id: " +elementId;
|
|
if (!element.mudJsEvent)
|
|
throw "[MudBlazor | JsEvent] please connect before subscribing"
|
|
element.mudJsEvent.subscribe(eventName);
|
|
}
|
|
|
|
unsubscribe(elementId, eventName) {
|
|
var element = document.getElementById(elementId);
|
|
if (!element || !element.mudJsEvent)
|
|
return;
|
|
element.mudJsEvent.unsubscribe(element, eventName);
|
|
}
|
|
}
|
|
window.mudJsEvent = new MudJsEventFactory();
|
|
|
|
|
|
class MudJsEvent {
|
|
|
|
constructor(dotNetRef, options) {
|
|
this._dotNetRef = dotNetRef;
|
|
this._options = options || {};
|
|
this.logger = options.enableLogging ? console.log : (message) => { };
|
|
this.logger('[MudBlazor | JsEvent] Initialized', { options });
|
|
this._subscribedEvents = {};
|
|
}
|
|
|
|
connect(element) {
|
|
if (!this._options)
|
|
return;
|
|
if (!this._options.targetClass)
|
|
throw "_options.targetClass: css class name expected";
|
|
if (this._observer) {
|
|
// don't do double registration
|
|
return;
|
|
}
|
|
var targetClass = this._options.targetClass;
|
|
this.logger('[MudBlazor | JsEvent] Start observing DOM of element for changes to child with class ', { element, targetClass });
|
|
this._element = element;
|
|
this._observer = new MutationObserver(this.onDomChanged);
|
|
this._observer.mudJsEvent = this;
|
|
this._observer.observe(this._element, { attributes: false, childList: true, subtree: true });
|
|
this._observedChildren = [];
|
|
}
|
|
|
|
disconnect() {
|
|
if (!this._observer)
|
|
return;
|
|
this.logger('[MudBlazor | JsEvent] disconnect mutation observer and event handler ');
|
|
this._observer.disconnect();
|
|
this._observer = null;
|
|
for (const child of this._observedChildren)
|
|
this.detachHandlers(child);
|
|
}
|
|
|
|
subscribe(eventName) {
|
|
// register handlers
|
|
if (this._subscribedEvents[eventName]) {
|
|
//console.log("... already attached");
|
|
return;
|
|
}
|
|
var element = this._element;
|
|
var targetClass = this._options.targetClass;
|
|
//this.logger('[MudBlazor | JsEvent] Subscribe event ' + eventName, { element, targetClass });
|
|
this._subscribedEvents[eventName]=true;
|
|
for (const child of element.getElementsByClassName(targetClass)) {
|
|
this.attachHandlers(child);
|
|
}
|
|
}
|
|
|
|
unsubscribe(eventName) {
|
|
if (!this._observer)
|
|
return;
|
|
this.logger('[MudBlazor | JsEvent] unsubscribe event handler ' + eventName );
|
|
this._observer.disconnect();
|
|
this._observer = null;
|
|
this._subscribedEvents[eventName] = false;
|
|
for (const child of this._observedChildren) {
|
|
this.detachHandler(child, eventName);
|
|
}
|
|
}
|
|
|
|
attachHandlers(child) {
|
|
child.mudJsEvent = this;
|
|
//this.logger('[MudBlazor | JsEvent] attachHandlers ', this._subscribedEvents, child);
|
|
for (var eventName of Object.getOwnPropertyNames(this._subscribedEvents)) {
|
|
if (!this._subscribedEvents[eventName])
|
|
continue;
|
|
// note: multiple registration of the same event not possible due to the use of the same handler func
|
|
this.logger('[MudBlazor | JsEvent] attaching event ' + eventName, child);
|
|
child.addEventListener(eventName, this.eventHandler);
|
|
}
|
|
if(this._observedChildren.indexOf(child) < 0)
|
|
this._observedChildren.push(child);
|
|
}
|
|
|
|
detachHandler(child, eventName) {
|
|
this.logger('[MudBlazor | JsEvent] detaching handler ' + eventName, child);
|
|
child.removeEventListener(eventName, this.eventHandler);
|
|
}
|
|
|
|
detachHandlers(child) {
|
|
this.logger('[MudBlazor | JsEvent] detaching handlers ', child);
|
|
for (var eventName of Object.getOwnPropertyNames(this._subscribedEvents)) {
|
|
if (!this._subscribedEvents[eventName])
|
|
continue;
|
|
child.removeEventListener(eventName, this.eventHandler);
|
|
}
|
|
this._observedChildren = this._observedChildren.filter(x=>x!==child);
|
|
}
|
|
|
|
onDomChanged(mutationsList, observer) {
|
|
var self = this.mudJsEvent; // func is invoked with this == _observer
|
|
//self.logger('[MudBlazor | JsEvent] onDomChanged: ', { self });
|
|
var targetClass = self._options.targetClass;
|
|
for (const mutation of mutationsList) {
|
|
//self.logger('[MudBlazor | JsEvent] Subtree mutation: ', { mutation });
|
|
for (const element of mutation.addedNodes) {
|
|
if (element.classList && element.classList.contains(targetClass)) {
|
|
if (!self._options.TagName || element.tagName == self._options.TagName)
|
|
self.attachHandlers(element);
|
|
}
|
|
}
|
|
for (const element of mutation.removedNodes) {
|
|
if (element.classList && element.classList.contains(targetClass)) {
|
|
if (!self._options.tagName || element.tagName == self._options.tagName)
|
|
self.detachHandlers(element);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
eventHandler(e) {
|
|
var self = this.mudJsEvent; // func is invoked with this == child
|
|
var eventName = e.type;
|
|
self.logger('[MudBlazor | JsEvent] "' + eventName + '"', e);
|
|
// call specific handler
|
|
self["on" + eventName](self, e);
|
|
}
|
|
|
|
onkeyup(self, e) {
|
|
const caretPosition = e.target.selectionStart;
|
|
const invoke = self._subscribedEvents["keyup"];
|
|
if (invoke) {
|
|
//self.logger('[MudBlazor | JsEvent] caret pos: ' + caretPosition);
|
|
self._dotNetRef.invokeMethodAsync('OnCaretPositionChanged', caretPosition);
|
|
}
|
|
}
|
|
|
|
onclick(self, e) {
|
|
const caretPosition = e.target.selectionStart;
|
|
const invoke = self._subscribedEvents["click"];
|
|
if (invoke) {
|
|
//self.logger('[MudBlazor | JsEvent] caret pos: ' + caretPosition);
|
|
self._dotNetRef.invokeMethodAsync('OnCaretPositionChanged', caretPosition);
|
|
}
|
|
}
|
|
|
|
//oncopy(self, e) {
|
|
// const invoke = self._subscribedEvents["copy"];
|
|
// if (invoke) {
|
|
// //self.logger('[MudBlazor | JsEvent] copy (preventing default and stopping propagation)');
|
|
// e.preventDefault();
|
|
// e.stopPropagation();
|
|
// self._dotNetRef.invokeMethodAsync('OnCopy');
|
|
// }
|
|
//}
|
|
|
|
onpaste(self, e) {
|
|
const invoke = self._subscribedEvents["paste"];
|
|
if (invoke) {
|
|
//self.logger('[MudBlazor | JsEvent] paste (preventing default and stopping propagation)');
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
const text = (e.originalEvent || e).clipboardData.getData('text/plain');
|
|
self._dotNetRef.invokeMethodAsync('OnPaste', text);
|
|
}
|
|
}
|
|
|
|
onselect(self, e) {
|
|
const invoke = self._subscribedEvents["select"];
|
|
if (invoke) {
|
|
const start = e.target.selectionStart;
|
|
const end = e.target.selectionEnd;
|
|
if (start === end)
|
|
return; // <-- we have caret position changed for that.
|
|
//self.logger('[MudBlazor | JsEvent] select ' + start + "-" + end);
|
|
self._dotNetRef.invokeMethodAsync('OnSelect', start, end);
|
|
}
|
|
}
|
|
}
|
|
|