<template> <div class="form-row form-group" :key="$attrs.key"> <vue-tribute class="tribute-container" :options="tributeOptions"> <div class="ta-header"> <div class="ta-type-selection"> <multiselect v-model="types[0]" id="group-filter" placeholder="" track-by="id" label="title" :options="types" :searchable="true" :options-limit="300" :limit="10" :max-height="350" selectLabel="" selectedLabel="" deselectLabel="" :close-on-select="true" :clear-on-select="false" :preserve-search="true" > <!-- <template slot="selection" slot-scope="{ values, search, isOpen }" ><span class="multiselect__single" v-if="values.length" v-show="!isOpen" >{{ values.length }} فیلتر</span ></template > --> <!-- <template slot="noResult" slot-scope="{ values, search, isOpen }"> چیزی یافت نشد. </template> <template slot="noOptions" slot-scope="{ values, search, isOpen }"> فهرست خالی است. </template> --> </multiselect> </div> <div class="ta-options"> <div class="ta-options-item"> <svg role="graphics-symbol" viewBox="0 0 14 16" class="copy"> <path d="M2.404 15.322h5.701c1.26 0 1.887-.662 1.887-1.927V12.38h1.154c1.254 0 1.91-.662 1.91-1.928V5.555c0-.774-.158-1.266-.626-1.74L9.512.837C9.066.387 8.545.21 7.865.21H5.463c-1.254 0-1.91.662-1.91 1.928v1.084H2.404c-1.254 0-1.91.668-1.91 1.933v8.239c0 1.265.656 1.927 1.91 1.927zm7.588-6.62c0-.792-.1-1.161-.592-1.665L6.225 3.814c-.452-.462-.844-.58-1.5-.591V2.215c0-.533.28-.832.843-.832h2.38v2.883c0 .726.386 1.113 1.107 1.113h2.83v4.998c0 .539-.276.832-.844.832H9.992V8.701zm-.79-4.29c-.206 0-.288-.088-.288-.287V1.594l2.771 2.818H9.201zM2.503 14.15c-.563 0-.844-.293-.844-.832V5.232c0-.539.281-.837.85-.837h1.91v3.187c0 .85.416 1.26 1.26 1.26h3.14v4.476c0 .54-.28.832-.843.832H2.504zM5.79 7.816c-.24 0-.346-.105-.346-.345V4.547l3.223 3.27H5.791z" ></path> </svg> کپی </div> <div class="ta-options-item">کپشن</div> <div class="ta-options-item"> <div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" > <svg role="graphics-symbol" viewBox="0 0 13 3" class="dots" style=" width: 14px; height: 14px; display: block; fill: inherit; flex-shrink: 0; " > <g> <path d="M3,1.5A1.5,1.5,0,1,1,1.5,0,1.5,1.5,0,0,1,3,1.5Z" ></path> <path d="M8,1.5A1.5,1.5,0,1,1,6.5,0,1.5,1.5,0,0,1,8,1.5Z" ></path> <path d="M13,1.5A1.5,1.5,0,1,1,11.5,0,1.5,1.5,0,0,1,13,1.5Z" ></path> </g> </svg> </button> <div class="dropdown-menu" aria-labelledby="dropdownMenu2"> <button class="dropdown-item" type="button">Action</button> <button class="dropdown-item" type="button"> Another action </button> <button class="dropdown-item" type="button"> Something else here </button> </div> </div> </div> </div> </div> <textarea @tribute-no-match="noMatchFound" @tribute-replaced="textReplaced" :ref="localFormElement.key" class="form-control" @focus="clearErrors" @blur="validate" @change="validate" :placeholder="localFormElement.placeholder" :id="localFormElement.key" :name="localFormElement.key" v-model="textValue" cols="1" rows="1" > </textarea> <div class="ta-footer"> <input class="form-control ta-footer-input" type="text" value="فریم وظیفه" /> </div> </vue-tribute> <context-menu style="position: static; display: inline-flex" v-if="contextMenu.length" :id="'context-menu-' + localFormElement.key" :contextMenu="contextMenu" @other="methodName($event)" > </context-menu> </div> </template> <script> import formBuilderMixin from "~/extensions/formBuilderExtension"; import VueTribute from "vue-tribute"; import apis from "~/apis/borhanApi.js"; export default { props: { enableSuggestion: { default: false, }, contextMenu: { default() { return []; }, }, }, extends: formBuilderMixin, data() { return { types: [ { id: "1", title: "javascript", }, { id: "2", title: "PHP", }, { id: "3", title: "SpareQL", }, { id: "4", title: "Paython", }, { id: "5", title: "BASIC", }, ], tributeOptions: { // symbol or string that starts the lookup trigger: "", // element to target for @mentions iframe: null, // class added in the flyout menu for active item selectClass: "highlight", // class added to the menu container containerClass: "tribute-container large", // class added to each list item itemClass: "my-tribute-class", // function called on select that returns the content to insert selectTemplate: function (item) { return item.original.value; // return "@" + item.original.value; }, // template for displaying item in menu menuItemTemplate: function (item) { return item.string; }, // template for when no match is found (optional), // If no template is provided, menu is hidden. noMatchTemplate: '<span class="no-result">مورد مشابهی ثبت نشده است.</span>', // specify an alternative parent container for the menu // container must be a positioned element for the menu to appear correctly ie. `position: relative;` // default container is the body menuContainer: document.body, // column to search against in the object (accepts function or string) lookup: "key", // column that contains the content to insert by default fillAttr: "value", // REQUIRED: array of objects to match or a function that returns data (see 'Loading remote data' for an example) values: [ { key: "سلام", value: "سلام", }, { key: "باسلام", value: "باسلام", }, { key: "علیک سلام", value: "علیک سلام", }, { key: "بی سلام", value: "بی سلام", }, { key: "صدتا سلام", value: "صدتا سلام", }, ], // values: ["سلام", "باسلام", "علیک سلام", "بی سلام", "صدتا سلام"], // values: (text, cb) => { // this.remoteSearch(text, (items) => cb(items)); // }, // When your values function is async, an optional loading template to show loadingItemTemplate: null, // specify whether a space is required before the trigger string requireLeadingSpace: true, // specify whether a space is allowed in the middle of mentions allowSpaces: true, // optionally specify a custom suffix for the replace text // (defaults to empty space if undefined) // replaceTextSuffix: "", // specify whether the menu should be positioned. Set to false and use in conjuction with menuContainer to create an inline menu // (defaults to true) positionMenu: true, // when the spacebar is hit, select the current match spaceSelectsMatch: false, // turn tribute into an autocomplete autocompleteMode: true, // Customize the elements used to wrap matched strings within the results list // defaults to <span></span> if undefined searchOpts: { pre: "<span>", post: "</span>", skip: false, // true will skip local search, useful if doing server-side search }, // Limits the number of items in the menu menuItemLimit: 25, // specify the minimum number of characters that must be typed before menu appears menuShowMinLength: 0, }, httpService: undefined, }; }, mounted() { this.httpService = new HttpService(import.meta.env.VITE_BASE_URL); }, methods: { limitText(count) { return `و ${count} کاربر دیگر`; }, noMatchFound(args) { }, textReplaced(args) { }, methodName(action, index = 0) { try { this[action](index); } catch (err) { this.$emit(action, index); } }, remoteSearch(input, callback) { return this.httpService .getRequest(apis.concept.annotations.read + "?ontology_id=" + input) .then((res) => { callback(res.data); }) .catch((e) => { callback([]); }) .finally(() => { this.fetchingData = false; }); }, }, }; </script> <!-- #region tribute --> <style scoped lang="scss"> .multiselect { font-size: 11px; -webkit-box-sizing: content-box; box-sizing: content-box; display: block; position: relative; width: 100%; min-height: 30px; text-align: left; color: #35495e; &.multiselect--active { background-color: #fff; z-index: 999999; } } .multiselect__content-wrapper { z-index: 9999; } .multiselect__select { position: absolute; width: 40px; height: 33px; right: 1px; top: 1px; padding: 4px 8px; text-align: center; -webkit-transition: -webkit-transform 0.2s ease; transition: -webkit-transform 0.2s ease; transition: transform 0.2s ease; transition: transform 0.2s ease, -webkit-transform 0.2s ease; &::before { position: relative; right: 0; top: unset; color: #999; margin-top: 0; border: none; background-size: contain; width: 2em; height: 2em; display: inline-block; background-repeat: no-repeat; background-image: url("../../assets/common/img/Component-25--1.svg"); } } .multiselect__tags { min-height: 30px; display: block; padding: 8px 40px 0 8px; border-radius: 5px; border: 1px solid #e8e8e8; background: #fff; font-size: 14px; border-color: transparent; background: transparent; } [dir="rtl"] .multiselect__tags { padding: 5px 5px 0 30px; } .multiselect__input, .multiselect__single { position: relative; display: inline-block; min-height: 20px; line-height: 20px; border: none; border-radius: 5px; background: transparent; padding: 0 0 0 5px; width: 100%; -webkit-transition: border 0.1s ease; transition: border 0.1s ease; -webkit-box-sizing: border-box; box-sizing: border-box; margin-bottom: 8px; vertical-align: top; } .form-group { &:hover { .ta-header, .ta-options { opacity: 1; visibility: visible; transition: opacity 300ms ease-in 0s; } } &.active, &:active { .ta-header, .ta-options { opacity: 1; visibility: visible; transition: opacity 300ms ease-in 0s; } } } </style> <!-- #endregion tribute --> <style lang="scss" scoped> .ta-header { position: absolute; top: 3px; right: 8px; left: 1px; display: flex; justify-content: space-between; opacity: 0; visibility: hidden; transition: opacity 300ms ease-in 0s; .ta-type-selection { // position: absolute; // top: 8px; // right: 8px; z-index: 1; color: rgba(55, 53, 47, 0.65); display: flex; align-items: center; justify-content: flex-end; opacity: 1; transition: opacity 300ms ease-in 0s; } } .ta-options { opacity: 0; visibility: hidden; // position: absolute; // top: 3px; // left: 1px; z-index: 1; color: rgba(55, 53, 47, 0.65); display: flex; align-items: center; justify-content: flex-end; height: 25px; font-size: 11.5px; transition: opacity 300ms ease-in 0s; .ta-options-item { user-select: none; transition: background 20ms ease-in 0s; cursor: pointer; display: inline-flex; align-items: center; white-space: nowrap; height: 25px; border-radius: 4px 0px 0px 4px; font-size: 11.5px; line-height: 1.2; padding: 4px 6px; color: rgb(55, 53, 47); background: rgb(234, 233, 229); font-weight: 400; svg { width: 16px; height: 16px; display: block; fill: inherit; flex-shrink: 0; padding-right: 4px; } } } .ta-footer { background: white; padding-left: 105px; .ta-footer-input { border-radius: unset; height: unset; max-width: 100%; width: 100%; white-space: pre-wrap; word-break: break-word; caret-color: rgb(55, 53, 47); font-size: 14px; line-height: 1.4; color: rgba(55, 53, 47, 0.65); padding-top: 6px; padding-bottom: 6px; padding-left: 2px; border-color: transparent !important; background-color: #fff; } } .form-control { flex-grow: 1; flex-shrink: 1; tab-size: 2; padding: 34px 16px 32px 32px; min-height: 1em; color: rgb(55, 53, 47); white-space: pre; border-radius: 4px; position: relative; background: rgb(247, 246, 243); min-width: 0px; width: 100%; resize: none; border-color: transparent; } .main-page__content .form-builder div input { border-color: transparent !important; } </style>