website/_webpack/js/editor.js (94 lines of code) (raw):
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
function toArray(list) {
return Array.prototype.slice.call(list);
}
var EDITOR_CLASS = '.editor';
var EDITOR_CONTENT_CLASS = '.editor-content';
var EDITOR_GUTTER_CLASS = '.editor-gutter';
var EDITOR_CODE_CLASS = '.editor-code';
var EDITOR_DATA_CLASS = '.editor-data';
var EDITOR_MESSAGES_CLASS = '.editor-messages';
var FLOW_ERROR_CLASS = '.flow-error';
var FLOW_ERROR_TARGET_CLASS = '.flow-error-target';
var FLOW_ERROR_TARGET_ACTIVE_CLASS = 'flow-error-target-active';
var FLOW_ERROR_MESSAGE_ACTIVE_CLASS = 'flow-error-active';
var FLOW_ERROR_MESSAGE_HIGHLIGHTED_CLASS = 'flow-error-highlighted';
function Editor(block) {
this.block = block;
this.data = JSON.parse(block.querySelector(EDITOR_DATA_CLASS).textContent);
this.overlay = this.block.querySelector(EDITOR_MESSAGES_CLASS);
this.errors = toArray(block.querySelectorAll(FLOW_ERROR_CLASS));
this.targets = toArray(block.querySelectorAll(FLOW_ERROR_TARGET_CLASS));
this.onMouseEnter = this.onMouseEnter.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);
this.bindEvents();
}
Editor.prototype.getError = function(errorId) {
return this.errors.find(function(error) {
return error.dataset.errorId === errorId;
});
};
Editor.prototype.getErrorMessage = function(error, messageId) {
return error.querySelector('[data-message-id="' + messageId + '"]');
};
Editor.prototype.getErrorTargets = function(errorId) {
return this.targets.filter(function(target) {
return target.dataset.errorId === errorId;
});
};
Editor.prototype.focusError = function(target) {
var data = target.dataset;
var error = this.getError(data.errorId);
var message = this.getErrorMessage(error, data.messageId);
var targets = this.getErrorTargets(data.errorId);
error.classList.add(FLOW_ERROR_MESSAGE_ACTIVE_CLASS);
message.classList.add(FLOW_ERROR_MESSAGE_HIGHLIGHTED_CLASS);
targets.forEach(function(target) {
target.classList.add(FLOW_ERROR_TARGET_ACTIVE_CLASS);
});
if (this.overlay.style.top === '') {
this.overlay.style.top = (target.offsetTop + target.offsetHeight) + 'px';
}
};
Editor.prototype.unfocusError = function(target) {
var data = target.dataset;
var error = this.getError(data.errorId);
var message = this.getErrorMessage(error, data.messageId);
var targets = this.getErrorTargets(data.errorId);
error.classList.remove(FLOW_ERROR_MESSAGE_ACTIVE_CLASS);
message.classList.remove(FLOW_ERROR_MESSAGE_HIGHLIGHTED_CLASS);
targets.forEach(function(target) {
target.classList.remove(FLOW_ERROR_TARGET_ACTIVE_CLASS);
});
this.overlay.style.top = '';
};
Editor.prototype.onMouseEnter = function(event) {
this.focusError(event.currentTarget);
};
Editor.prototype.onMouseLeave = function(event) {
this.unfocusError(event.currentTarget);
};
Editor.prototype.bindEvents = function() {
var onMouseEnter = this.onMouseEnter;
var onMouseLeave = this.onMouseLeave;
this.targets.forEach(function(target) {
target.addEventListener('mouseenter', onMouseEnter);
target.addEventListener('mouseleave', onMouseLeave);
});
};
Editor.prototype.unbindEvents = function() {
var onMouseEnter = this.onMouseEnter;
var onMouseLeave = this.onMouseLeave;
this.targets.forEach(function(target) {
target.removeEventListener('mouseenter', onMouseEnter);
target.removeEventListener('mouseleave', onMouseLeave);
});
};
Editor.getEditors = function() {
return toArray(document.querySelectorAll(EDITOR_CLASS));
};
Editor.init = function() {
var editors = Editor.getEditors().map(function(block) {
return new Editor(block);
});
};
export default Editor;