Vue.component('v_textarea', {
template: `
<div :class="css" class="xd-border v_textarea" :data-component="$options.name">
<div class="xd-container xd-gap print-hide" style="justify-content:right;">
<a :class="{'xd-strong': local_tab==-4}" class="xd-button xd-small " @click="local_tab= -4" v-if="readonly===false">{{$t('edit')}}</a>
<a :class="{'xd-strong': local_tab==-3}" v-if="readonly===false" class="xd-button xd-small " @click="renderPreview">{{$t('view')}}</a>
<a class="xd--target xd-button xd-small" v-if="readonly===false && advanced"
href="https://docs.github.com/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax" target="_blank"
data-ga-click="Markdown Toolbar, click, help" rel="noreferrer"><span role="tooltip" aria-label="Styling with Markdown is supported"
class="Tooltip__TooltipBase-sc-17tf59c-0 cXRxE tooltipped-nw"><svg aria-hidden="true" focusable="false" role="img" class="Octicon-sc-9kayk9-0 CmyWV" viewBox="0 0 16 16" width="16" height="16"
fill="currentColor" style="display: inline-block; user-select: none; vertical-align: text-bottom; overflow: visible;">
<path
d="M14.85 3c.63 0 1.15.52 1.14 1.15v7.7c0 .63-.51 1.15-1.15 1.15H1.15C.52 13 0 12.48 0 11.84V4.15C0 3.52.52 3 1.15 3ZM9 11V5H7L5.5 7 4 5H2v6h2V8l1.5 1.92L7 8v3Zm2.99.5L14.5 8H13V5h-2v3H9.5Z">
</path>
</svg></span></a>
<select tabindex="-1" v-model="selected_paste_mode" class="xd-input xd-small" v-if="readonly===false && advanced">
<option v-for="option in paste_mode_options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
</div>
<div style="clear:both"></div>
<div v-show="local_tab===-4">
<textarea tabindex="-1" class="xd-box" @blur="$emit('blur')" :class="css" @keydown.tab.prevent="tabber($event)" style="border:none;font-family: monospace ;" :required="required ? true : false"
:rows="rows" @paste="onPaste" ref="el" @input="update" :placeholder="$t(placeholder)">{{content}}</textarea>
<div class="xd-padding xd-hide-print">
<!--UPLOAD-->
<form enctype="multipart/form-data" novalidate v-if="isInitial || isSaving">
<input type="file" tabindex="-1" ref="iinput" multiple :name="files.uploadFieldName" :disabled="isSaving"
@change="filesChange($event.target.name, $event.target.files); files.fileCount = $event.target.files.length" class="xd-small">
<p v-if="isSaving">
Uploading {{ files.fileCount }} files...
</p>
</form>
<!--SUCCESS-->
<div v-if="isSuccess">
<h3>
Upload OK
<a href="javascript:void(0)" @click="reset()">click to Upload next file</a>
</h3>
<ul class="list-unstyled">
<li v-for="item in files.uploadedFiles">
<img :src="item.url" class="img-responsive img-thumbnail" :alt="item.originalName">
</li>
</ul>
</div>
<!--##################################### UPLOAD FAILED ##########################-->
<div v-if="isFailed">
<h3>Upload FAILED <a href="javascript:void(0)" @click="reset()">click to Try again</a></h3>
<pre>{{ files.uploadError }}</pre>
</div>
</div>
</div>
<div v-if="local_tab===-3" v-html="preview" class="xd-box" :class="css">
</div>
</div>`,
props: {
value: { type: String },
readonly: { type: Boolean, default: false },// hide edits
tab: { type: Number, default: -4 }, //-4 edit
advanced: { type: Boolean, default: true },
required: { type: Boolean, default: false },
valuetype: { type: String, default: '.md' },
css: { type: String, default: 'xd-white' },
placeholder: { type: String, default: 'comment' },
},
data() {
return {
local_tab: this.tab,
content: this.value, //initial value
maxwidth: 1200, //max width of a images 1200
selected_paste_mode: '',
paste_mode_options:
[{ text: 'Paste Text', value: '' },
{ text: 'Paste Word', value: '/api/core/system/officehtml' },
],
preview: 'Working ...',
files: {
uploadedFiles: [],
uploadError: null,
files: [],
fileCount: null,
uploadFieldName: 'upload',
cursorLocation: null //lokacja kursora gdzie wstawic
},
currentStatus: null
};
},
methods: {
insert(main_string, ins_string, pos) {
if (typeof (pos) === "undefined") {
pos = 0;
}
if (!ins_string) {
ins_string = '';
}
if (!main_string) {
main_string = '';
}
if (main_string === '' || main_string === null)
return ins_string;
else
return main_string.slice(0, pos) + '\n' + ins_string + main_string.slice(pos);
},
tabber(event) {
var text;
this.value ? text = this.value : text = "";
originalSelectionStart = event.target.selectionStart,
textStart = text.slice(0, originalSelectionStart),
textEnd = text.slice(originalSelectionStart);
var result = `${textStart}\t${textEnd}`
event.target.value = result // required to make the cursor stay in place.
event.target.selectionEnd = event.target.selectionStart = originalSelectionStart + 1
this.$emit('input', event.target.value);
},
onPaste(e) {
if (e.clipboardData.types.indexOf('text/html') !== -1 && this.selected_paste_mode.indexOf('/api') !== -1) {
e.preventDefault();
this.axpost(this.selected_paste_mode, { painput: e.clipboardData.getData('text/html') }, false, true).then((response) => {
e.target.value = this.insert(e.target.value, response.data.paoutput, e.target.selectionStart);
e.target.dispatchEvent(new Event('input'));
});
}
else if (e.clipboardData.files.length > 0) {
e.preventDefault();
this.$refs.iinput.files = e.clipboardData.files;
this.$refs.iinput.dispatchEvent(new Event('change'));
this.reset();
}
},
update(event) {
// this.content = 'f'; //event.target.value;
this.$emit('input', event.target.value);
// this.content = event.target.value; // pobranie z inputa
this.files.cursorLocation = event.target.selectionStart;
},
renderPreview() {
this.local_tab = -3;
if (this.value) {
this.axpost('/api/core/system/preview', { painput: this.value, patype: this.valuetype }, { skipNotification: true }).then((response) => {
this.preview = response.data.paoutput;
// this.$nextTick(function () {
// Prism.highlightAll();
// });
})
}
else {
this.preview = '-'
}
},
//FILE UPLOAD
reset() {
// reset form to initial state
this.currentStatus = STATUS_INITIAL;
this.uploadedFiles = [];
this.uploadError = null;
},
save(formData) {
// upload data to the server
this.currentStatus = STATUS_SAVING;
let link = this.$root.sys.api + '/api/core/files/';
const options = {
headers: {
"content-type": "multipart/form-data",
"accept": "*/*"
}
}
this.axpost(link, formData, options).then((response) => {
this.currentStatus = STATUS_SUCCESS;
//zamiana nazw
Object.entries(response.data.files).forEach(entry => {
const [k, v] = entry;
let oldv = '[Uploading... ' + k + ']';
let newv = ""
if (this.endsWithAny(this.images_arr(), v))
newv = '[' + k + '](' + link + v + '?w=' + this.maxwidth + ')';
else
newv = '[' + k + '](' + link + v + ')';
this.$refs.el.value = this.$refs.el.value.replace(oldv, newv);
this.content = this.$refs.el.value;
});
this.$emit('input', this.$refs.el.value);
}).catch((response) => {
this.currentStatus = STATUS_FAILED;
})
},
filesChange(fieldName, fileList) {
// handle file changes
const formData = new FormData();
if (!fileList.length) return;
// append the files to FormData
Array
.from(Array(fileList.length).keys())
.map((x) => {
formData.append(fieldName, fileList[x], fileList[x].name);
if (this.endsWithAny(this.images_arr(), fileList[x].name) || this.endsWithAny(this.video_arr(), fileList[x].name)) {
this.$refs.el.value = this.insert(this.$refs.el.value, '![Uploading... ' + fileList[x].name + ']\n', this.$refs.el.selectionStart);
}
else {
this.$refs.el.value = this.insert(this.$refs.el.value, '[Uploading... ' + fileList[x].name + ']\n', this.$refs.el.selectionStart);
}
});
// save it
this.save(formData);
}
},
computed: {
rows() { //number of rows to display
if (!this.value)
return 2;
x = this.value.split('\n').length
if (x < 5)
return 5;
else if (x > 25)
return 25;
else
return x + 1;
},
isInitial() {
return this.currentStatus === STATUS_INITIAL;
},
isSaving() {
return this.currentStatus === STATUS_SAVING;
},
isSuccess() {
return this.currentStatus === STATUS_SUCCESS;
},
isFailed() {
return this.currentStatus === STATUS_FAILED;
}
},
mounted() {
//jest text lub preview
if (this.value || this.local_tab == -3)
this.renderPreview();
else
this.preview = '';
this.reset();
},
});