ignite-html-material/editable-label.js

165 lines
4.9 KiB
JavaScript
Raw Normal View History

import { IgniteHtml } from '../ignite-html/ignite-html.js';
import { IgniteElement } from "../ignite-html/ignite-element.js";
import { IgniteTemplate, button, ul, slot, span, div } from "../ignite-html/ignite-template.js";
import { IgniteProperty } from "../ignite-html/ignite-html.js";
class EditableLabel extends IgniteElement {
constructor() {
super();
}
get styles() {
return /*css*/`
mt-editable-label {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
border-radius: 0.3rem;
border: solid 0.13rem #ced4da;
padding: 0.4rem;
}
mt-editable-label.no-border {
border-color: transparent;
}
mt-editable-label.editing {
border: solid 0.13rem rgba(0,0,0,0.1);
}
mt-editable-label.truncate > div {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
mt-editable-label:hover {
cursor: pointer;
}
mt-editable-label>div {
flex: 1;
word-break: break-word;
}
mt-editable-label>div:focus {
outline: none;
}
mt-editable-label>div:empty:before {
content: attr(data-placeholder);
opacity: 0.5;
}
mt-editable-label>button {
margin-left: 0.5em;
background-color: #2196F3;
color: #fff;
border: none;
border-radius: 0.3rem;
padding: 0;
width: 1.5em;
height: 1.5em;
min-width: 1.5em;
min-height: 1.5em;
font-size: 0.8rem;
}
`;
}
get properties() {
return {
stopEditingOnBlur: true,
editing: false,
value: null,
multiLine: false,
truncate: false,
saveButton: true,
input: null,
placeholder: null,
border: false
};
}
render() {
return this.template
.attribute("tabindex", "0")
.class(this.border, value => value ? null : "no-border")
.class(this.editing, value => value ? "editing" : null)
.class([this.editing, this.truncate], (editing, truncate) => !editing && truncate ? "truncate" : null)
.onFocus(e => this.onFocus(e))
.child(
new div()
.innerHTML(this.value)
.class(this.editing, (value) => { return value ? "focus" : null; })
.attribute("contenteditable", this.editing)
.data("placeholder", this.placeholder)
.ref(this.input)
.onBlur(e => this.onBlur(e))
.on("keydown", (e) => this.onKeyDown(e)),
new button(`<i class="fas fa-check"></i>`)
.onClick(e => this.onBlur(e))
.style("display", this.editing, true, (value) => { return value && this.saveButton ? null : "none" })
);
}
onKeyDown(e) {
if ((e.keyCode === 13 || e.keyCode === 27) && !this.multiLine) {
this.input.blur();
e.preventDefault();
e.stopPropagation();
}
}
onBlur(e) {
if (this.editing) {
if (this.stopEditingOnBlur) {
this.editing = false;
}
if (this.input.innerText !== this.value) {
this.value = this.input.innerText;
//Dispatch a native change event
this.dispatchEvent(new CustomEvent("change", { bubbles: true }));
}
}
}
onFocus(e) {
this.editing = true;
this.input.focus();
this.placeCaretAtEnd(this.input);
}
placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
}
class EditableLabelTemplate extends IgniteTemplate {
constructor(...children) {
super("mt-editable-label", children);
}
}
IgniteHtml.register("mt-editable-label", EditableLabel);
export {
EditableLabelTemplate as EditableLabel
}