124 lines
3.2 KiB
Vue
124 lines
3.2 KiB
Vue
<template>
|
|
<div :class="`password-visibility-${inputId} h-100`">
|
|
<span
|
|
v-if="visible"
|
|
class="text-bg-primary reveal d-flex justify-content-center align-items-center h-100"
|
|
@click.prevent="toggleVisibility()"
|
|
type="button"
|
|
:title="__('Cacher le mot de passe')"
|
|
data-bs="tooltip"
|
|
>
|
|
<FontAwesomeIcon
|
|
icon="fas fa-eye-slash"
|
|
:aria-hidden="true"
|
|
/>
|
|
</span>
|
|
<span
|
|
v-else
|
|
class="text-bg-primary reveal d-flex justify-content-center align-items-center h-100"
|
|
@click.prevent="toggleVisibility()"
|
|
type="button"
|
|
:title="__('Dévoiler le mot de passe')"
|
|
data-bs="tooltip"
|
|
>
|
|
<FontAwesomeIcon
|
|
icon="fas fa-eye"
|
|
:aria-hidden="true"
|
|
/>
|
|
</span>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
|
import { Tooltip } from "bootstrap";
|
|
import { defineComponent } from "vue";
|
|
import trans from "./../../modules/trans";
|
|
|
|
export default defineComponent({
|
|
name: "PasswordVisibility",
|
|
mixins: [trans],
|
|
components: { FontAwesomeIcon },
|
|
data(): {
|
|
inputId: string;
|
|
input: HTMLInputElement;
|
|
visible: boolean;
|
|
tooltipList: HTMLButtonElement[];
|
|
} {
|
|
return {
|
|
inputId: "",
|
|
input: document.createElement("input"),
|
|
visible: false,
|
|
tooltipList: [],
|
|
};
|
|
},
|
|
computed: {},
|
|
mounted() {
|
|
const json = String(this.$attrs.json ?? "{}"),
|
|
data = JSON.parse(json);
|
|
this.inputId = data.inputId;
|
|
this.input = document.getElementById(this.inputId) as HTMLInputElement;
|
|
if (!this.input) {
|
|
throw new Error(`Cannot find input id '${this.inputId}'`);
|
|
}
|
|
if (this.input.tagName !== "INPUT") {
|
|
throw new Error(`id '${this.inputId}' is not an input`);
|
|
}
|
|
if ((this.input as HTMLInputElement).type !== "password") {
|
|
throw new Error(`id '${this.inputId}' is not an input password`);
|
|
}
|
|
this.input = this.input as HTMLInputElement;
|
|
this.$nextTick(() => {
|
|
this.updateBootstrapTooltip();
|
|
});
|
|
},
|
|
methods: {
|
|
/**
|
|
* Update password status (visible, hidden).
|
|
*/
|
|
toggleVisibility(): void {
|
|
if (this.input.type === "password") {
|
|
this.input.type = "text";
|
|
this.visible = true;
|
|
} else {
|
|
this.input.type = "password";
|
|
this.visible = false;
|
|
}
|
|
this.$nextTick(() => {
|
|
this.updateBootstrapTooltip();
|
|
});
|
|
},
|
|
/**
|
|
* Update Bootstrap tooltips.
|
|
*/
|
|
updateBootstrapTooltip() {
|
|
let newTooltipList = [].slice.call(
|
|
document.querySelectorAll(
|
|
".password-visibility-" + this.inputId + " [data-bs=\"tooltip\"]"
|
|
)
|
|
) as HTMLButtonElement[];
|
|
let tmp = newTooltipList.filter((x) => !this.tooltipList.includes(x));
|
|
tmp.map((tooltip) => {
|
|
return new Tooltip(tooltip);
|
|
});
|
|
this.closeBootstrapTooltip();
|
|
this.tooltipList = newTooltipList;
|
|
},
|
|
/**
|
|
* Close all Bootstrap tooltips.
|
|
*/
|
|
closeBootstrapTooltip() {
|
|
this.tooltipList.forEach((tooltip) => {
|
|
tooltip.blur();
|
|
Tooltip.getInstance(tooltip)?.hide();
|
|
});
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.reveal {
|
|
width: 52px;
|
|
}
|
|
</style>
|