Skip to content

Upload image Functionality #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Demo/Demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import VueDocumentEditor from '../DocumentEditor/DocumentEditor.vue'; // set fro
import InvoiceTemplate from './InvoiceTemplate.ce.vue';
import { markRaw } from 'vue';
import useDocument from "@/composables/useDocument.ts";
import useImageUpload from "@/composables/useImageUpload";


export default {
components: { VueDocumentEditor, VueFileToolbarMenu },
Expand Down Expand Up @@ -127,6 +129,7 @@ export default {
// Main commands
{ text: "New", title: "New", icon: "description", click: () => { if(confirm("This will create an empty document. Are you sure?")){ this.content = [""]; this.resetContentHistory(); } } },
{ text: "Print", title: "Print", icon: "print", click: () => window.print() },
{ text: "Insert Image", icon: "image", disabled: !this.current_text_style, title: "Insert Image", click: () => this.addImage() },

{ is: "spacer" },

Expand Down Expand Up @@ -384,9 +387,13 @@ export default {
canUndo,
} = useDocument();

const {
addImage,
} = useImageUpload();

return {
content,
addImage,
undo,
redo,
canRedo,
Expand Down
48 changes: 48 additions & 0 deletions src/composables/useImageUpload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {insertHtmlAtCursor} from "@/utils/insertHTMLStCursor";


interface UseImageUploadComposable {
addImage: () => void;
}

export default (): UseImageUploadComposable => {
// Create a hidden file input element
const addImage = () => {
let fileInput = document.getElementById('fileInput') as HTMLInputElement;

if (!fileInput) {
fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = 'image/*';
fileInput.id = 'fileInput';
fileInput.style.display = 'none';
document.body.appendChild(fileInput);
}

// Trigger the click event on the file input element
fileInput.click();

// When file input changes (user has selected a file),
// read the image file and convert to a base64 string
fileInput.onchange = (event: Event) => {
const file = (event.target as HTMLInputElement).files?.[0]; // Get the selected file
const reader = new FileReader();

reader.onloadend = () => {
const base64String = reader.result as string;
// Assume index is the location where the image tag is to be added
let index = 0;

// Check if there is an element at this index
insertHtmlAtCursor(`<img class="resizable-image" src="${base64String}" alt="User image" width="200px" height="200px">`);
};

if (file) {
reader.readAsDataURL(file);
}
}
}
return {
addImage,
};
}
47 changes: 47 additions & 0 deletions src/utils/insertHTMLStCursor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
export function insertHtmlAtCursor(html: string) {
let sel: Selection | null, range: Range;

// Check if browser supports window.getSelection()
if (window.getSelection) {
sel = window.getSelection();

if (!sel) {
return
}

// If some text is already selected or cursor is somewhere in the document
if (sel.getRangeAt && sel.rangeCount) {
// Get the first range of the selection
range = sel.getRangeAt(0);

// Delete any selected text
range.deleteContents();

// Create a new div element and set its inner HTML to the passed HTML string
let el: HTMLDivElement = document.createElement("div");
el.innerHTML = html;

// Create an empty DocumentFragment that will hold the nodes for insertion
let frag: DocumentFragment = document.createDocumentFragment(), node: ChildNode | null, lastNode: ChildNode | null = null;

// Move all child nodes of the div element to the DocumentFragment
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node);
}

// Insert the DocumentFragment at the current cursor position (i.e., where the range starts)
range.insertNode(frag);

// If there is a last node after inserting the fragment, move the cursor after the last inserted node
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);

// Clear all ranges from the selection and add the new range
sel.removeAllRanges();
sel.addRange(range);
}
}
}
}