105 lines
2.2 KiB
Vue
105 lines
2.2 KiB
Vue
<template>
|
|
<div class="wordCounter">
|
|
<span class="words"
|
|
><u>{{ __("Mots") }}</u
|
|
> : <b>{{ words }}</b></span
|
|
>
|
|
<span class="chars"
|
|
><u>{{ __("Caractères") }}</u
|
|
> : <b>{{ chars }}</b></span
|
|
>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent } from "vue";
|
|
import trans from "../../modules/trans";
|
|
|
|
export default defineComponent({
|
|
mixins: [trans],
|
|
beforeMount() {
|
|
if (!this.$attrs.json) {
|
|
throw new Error("this component requires json");
|
|
}
|
|
},
|
|
mounted() {
|
|
const json = String(this.$attrs.json ?? ""),
|
|
data = JSON.parse(json);
|
|
this.id = data.id;
|
|
},
|
|
data(): {
|
|
id: string;
|
|
words: number;
|
|
chars: number;
|
|
input: HTMLInputElement | null;
|
|
} {
|
|
return {
|
|
id: "",
|
|
words: 0,
|
|
chars: 0,
|
|
input: null,
|
|
};
|
|
},
|
|
watch: {
|
|
id() {
|
|
if (!this.id) {
|
|
throw new Error("Missing ID");
|
|
}
|
|
const input = document.getElementById(this.id);
|
|
if (!input) {
|
|
throw new Error(`Input ${this.id} could not be found`);
|
|
}
|
|
},
|
|
input() {
|
|
if (!this.input) {
|
|
throw new Error("input has to be set");
|
|
}
|
|
if (this.input && !(this.input instanceof HTMLInputElement)) {
|
|
throw new Error("input as to be HTMLInputElement");
|
|
}
|
|
this.input.addEventListener("input", (e) => {
|
|
const el = e.target;
|
|
if (!el || !(el instanceof HTMLInputElement)) {
|
|
throw new Error();
|
|
}
|
|
this.updateValues(el.value);
|
|
});
|
|
this.updateValues(this.input.value);
|
|
},
|
|
},
|
|
methods: {
|
|
updateValues(string: string) {
|
|
let chars, words;
|
|
[words, chars] = this.calculateValues(string);
|
|
this.words = words;
|
|
this.chars = chars;
|
|
},
|
|
calculateValues(string: string) {
|
|
const arr = string.split(" ");
|
|
return [arr.filter((word) => word !== "").length, string.length];
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.wordCounter {
|
|
display: inline-block;
|
|
color: initial;
|
|
border: 1px solid rgb(196, 196, 196);
|
|
border-bottom: 0;
|
|
background-color: #fafafa;
|
|
position: relative;
|
|
width: 100%;
|
|
|
|
.words {
|
|
position: relative;
|
|
left: 2rem;
|
|
}
|
|
|
|
.chars {
|
|
position: absolute;
|
|
left: 9rem;
|
|
}
|
|
}
|
|
</style>
|