Skip to content

Page break #17

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

Closed
ggirardi1 opened this issue Aug 5, 2022 · 10 comments
Closed

Page break #17

ggirardi1 opened this issue Aug 5, 2022 · 10 comments
Labels
acknowledged Acknowledged

Comments

@ggirardi1
Copy link
Contributor

Hello friends!

I need help.

I would like to use vue-document-editor to issue reports from my system. It has proven to be a great tool, but it has an issue in it that is giving me a headache, which is the page break.

When I generate my report, I don't know how long it will be, whether or not it will fit within a single page. So I would need the library to work on it automatically, separating what goes on one page or another.

Currently all the content is on one page in the view, and some things get messed up.

Does anyone know how to solve this problem?

Best Regards

@motla
Copy link
Owner

motla commented Aug 5, 2022

Hi!

I suppose your are using interactive .vue templates for your pages. In this case I cannot touch or change the content managed by Vue (i.e. separate it over several pages) because then Vue would be lost and the pages would be no more interactive.

So the only choice you have is not using Vue and writing your plain HTML in the content instead of using .vue templates.

You can however make JavaScript interactivity using HTML tags with attribute contenteditable="false" that will be clickable, for example inputting buttons and setting up your own JavaScript code when you click on it.

@ggirardi1
Copy link
Contributor Author

Actually I'm not rendering components anymore because I read this comment in issue #5 .

So I returned my code to a plain HTML.

However, the page break is still not done. The content looks weird.

image

The content should be broken into the red dashed, but it continues behind the second page.

@motla
Copy link
Owner

motla commented Aug 8, 2022

Can you send the HTML?

@ggirardi1
Copy link
Contributor Author

<template>
    <div class="main">
        <!-- Top bar -->
        <vue-file-toolbar-menu :content="menu" class="bar" />

        <!-- Document editor -->
        <vue-document-editor
            class="editor"
            ref="editor"
            v-model:content="content"
            :overlay="overlay"
            :display="display"
            :zoom="zoom"
            :page_margins="page_margins"
        />
    </div>
</template>

<script>
    import {ref} from 'vue';

    import VueDocumentEditor from 'vue-document-editor'
    import VueFileToolbarMenu from 'vue-file-toolbar-menu';

    //Mixins
    import CurrencyMixin from '../../Mixins/CurrencyMixin'

    //Aux
    import {maskCnpj, maskCpf} from "../../helpers";
    import moment from "moment";

    export default {
        name: "Print",

        data() {
            return {
				content: [``]
                display: `vertical`,
                page_margins: "45mm 10mm",
                zoom: 0.8,
                mounted: false,
            }
        },

        mixins: [
            CurrencyMixin
        ],

        props: ['order'],

		mounted() {
            this.content[0] = `
                <div contenteditable="false">
                    <h3 class="mt-4 mb-4 text-center uppercase">Orçamento</h3>
                    <table>
                        <thead>
                            <tr>
                                <td class="text-left bg-gray-100">DADOS DO CLIENTE</td>
                                <td class="text-right">OUTROS DADOS</td>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td class="bg-gray-100">
                                    <div><b>${this.order.customer.type === 'physical' ? 'Nome Completo' : 'Razão Social'}:</b> ${this.order.customer.type === 'physical' ? this.order.customer.name : this.order.brand}</div>
                                    <div><b>Endereço:</b> ${this.order.customer.address}, ${this.order.customer.number}</div>
                                    <div><b>Bairro/CEP:</b> ${this.order.customer.neighborhood}, ${this.order.customer.postal_code}</div>
                                    <div><b>Cidade:</b> ${this.order.customer.city.name}/${this.order.customer.city.state.acronym}</div>
                                    <div><b>E-mail:</b> ${this.order.customer.email}</div>
                                    <div><b>Telefone:</b> (XX) XXXX-XXXX</div>
                                </td>

                                <td style="min-width: 250px; text-align:right">
                                    <div><b>Lorem Ipsum is simply dummy:</b> ${this.order.distancia_instalacao_entrega}km</div>
                                </td>
                            </tr>
                        </tbody>
                    </table>

                    <section>
                        <h3 class="mt-4 text-center uppercase">Lorem Ipsum is simply dummy</h3>

                        <table>
                            <thead>
                                <tr>
                                    <td colspan="2" class="cabecalho">Lorem Ipsum is simply dummy</td>
                                </tr>
                                <tr>
                                    <td class="bg-gray-100">MEDIDAS</td>
                                    <td style="text-align:right">MATERIAIS</td>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td class="bg-gray-100">
                                        <div><b>Lorem Ipsum is simply dummy:</b> m²</div>
                                        <div>
                                            <b>Observações:</b><br>

                                        </div>
                                    </td>

                                    <td style="min-width: 250px; text-align:right">
                                        <div>Lorem Ipsum is simply dummy: <b>R$ 2.255.64</b></div>
                                        <div>Lorem Ipsum is simply dummy: <b>R$ 2.255.64</b></div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </section>

                    <section>
                       <h3 class="mt-4 text-center uppercase">Peças Simples</h3>

                        <table>
                            <thead>
                                <tr>
                                    <td colspan="2" class="cabecalho">Cozinha</td>
                                </tr>
                                <tr>
                                    <td class="bg-gray-100">MEDIDAS</td>
                                    <td style="text-align:right">MATERIAIS</td>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td class="bg-gray-100">
                                        <div><b>Lorem Ipsum is simply dummy:</b> m²</div>
                                        <div><b>Lorem Ipsum is simply dummy:</b> m</div>
                                        <div><b>Lorem Ipsum is simply dummy:</b> m</div>
                                        <div>
                                            <b>Observações:</b><br>

                                        </div>
                                    </td>

                                    <td style="min-width: 250px; text-align:right">
                                        <div>Lorem Ipsum is simply dummy: <b>R$ 2.255.64</b></div>
                                        <div>Lorem Ipsum is simply dummy: <b>R$ 2.255.64</b></div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </section>

                    <section>
                        <h3 class="mt-4 text-center uppercase">Lorem Ipsum is simply dummy</h3>

                        <table>
                            <thead>
                                <tr>
                                    <td colspan="2" class="cabecalho">Lorem Ipsum is simply dummy</td>
                                </tr>
                                <tr>
                                    <td class="bg-gray-100">Lorem </td>
                                    <td style="text-align:right">MATERIAIS</td>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td class="bg-gray-100">
                                        <div><b>Lorem Ipsum is simply dummy:</b></div>
                                        <div><b>Lorem Ipsum is simply dummy:</b></div>
                                        <div><b>Lorem Ipsum is simply dummy:</b></div>
                                        <div><b>Lorem Ipsum is simply dummy:</b></div>
                                        <div><b>Lorem Ipsum is simply dummy:</b></div>
                                        <div><b>Lorem Ipsum is simply dummy:</b></div>
                                        <div>
                                            <b>Observações:</b><br>

                                        </div>
                                    </td>

                                    <td style="min-width: 250px; text-align:right">
                                        <div>What is Lorem Ipsum? <b>R$ 2.255.64</b></div>
                                        <div>What is Lorem Ipsum? <b>R$ 2.255.64</b></div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </section>

                    <section>
                        <h3 class="mt-3 text-center uppercase">DESCRIMINAÇÃO DA NEGOCIAÇÃO</h3>

                        <ul>
                            <li>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum;</li>
                            <li>There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable;</li>
                            <li>Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old;</li>
                            <li>It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English;</li>
                            <li>The standard Lorem Ipsum passage, used since the 1500s;</li>
                            <li>But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?</li>
                        </ul>
                    </section>
                </div>
            </div>
            `;
        },
		
        computed: {
            menu () {
                return [
                    {
                        text: "Imprimir",
                        title: "Imprimir",
                        icon: "print",
                        click: () => window.print()
                    }
                ];
            }
        },

        methods: {
            overlay (page, total) {
                return `
                    <div style="position: absolute; bottom: 8mm; right: 10mm">Pág. ${page} de ${total}</div>

                    <div style="position: absolute; display: flex; align-items: center; justify-content: space-between; text-align: center; left: 0; top: 0; right: 0; padding: 10mm 15mm">
                        <div>
                            <img src="${this.$page.props.user.subscriber.logo}" style="width: 200px" alt="">
                        </div>

                        <div>
                            <span><b>${this.$page.props.user.subscriber.brand}</b></span><br>
                            <span>${this.$page.props.user.subscriber.name}</span><br>
                            <span>${this.$page.props.user.subscriber.type === 'legal' ? maskCnpj(this.$page.props.user.subscriber.document) : maskCpf(this.$page.props.user.subscriber.document)}</span><br>
                            <span>${this.$page.props.user.subscriber.email}</span><br>

                            <span>(XX) XXXX-XXXX</span>
                        </div>

                        <div class="flex flex-col justify-between self-stretch">
                            <h3>N° XXX</h3>

                            <span><b>Data:</b> ${moment(this.order.created_at).format('DD/MM/YYYY')}</span>

                            <span><b>Previsão Finalização:</b> ${this.order.expected_closing_date ?? ''}</span>
                        </div>
                    </div>
                `;
            }
        },

        async mounted() {
            this.mounted = true;
        },

        created() {
            // Initialize gesture flags
            let start_zoom_gesture = false;
            let start_dist_touch = false;
            let start_zoom_touch = false;

            // Manage ctrl+scroll zoom (or trackpad pinch)
            window.addEventListener("wheel", (e) => {
                if (e.ctrlKey) {
                    e.preventDefault();
                    this.zoom = Math.min(Math.max(this.zoom - e.deltaY * 0.01, this.zoom_min), this.zoom_max);
                }
            }, {passive: false});

            // Manage trackpad pinch on Safari
            window.addEventListener("gesturestart", (e) => {
                e.preventDefault();
                start_zoom_gesture = this.zoom;
            });
            window.addEventListener("gesturechange", (e) => {
                e.preventDefault();
                if (!start_zoom_touch) {
                    this.zoom = Math.min(Math.max(start_zoom_gesture * e.scale, this.zoom_min), this.zoom_max);
                }
            });
            window.addEventListener("gestureend", () => {
                start_zoom_gesture = false;
            });

            // Manage pinch to zoom for touch devices
            window.addEventListener("touchstart", (e) => {
                if (e.touches.length == 2) {
                    e.preventDefault();
                    start_dist_touch = Math.hypot(
                        e.touches[0].pageX - e.touches[1].pageX,
                        e.touches[0].pageY - e.touches[1].pageY
                    );
                    start_zoom_touch = this.zoom;
                }
            }, {passive: false});
            window.addEventListener("touchmove", (e) => {
                if (start_dist_touch && start_zoom_touch) {
                    e.preventDefault();
                    let zoom = start_zoom_touch * Math.hypot(
                        e.touches[0].pageX - e.touches[1].pageX,
                        e.touches[0].pageY - e.touches[1].pageY
                    ) / start_dist_touch;
                    this.zoom = Math.min(Math.max(zoom, this.zoom_min), this.zoom_max);
                }
            }, {passive: false});
            window.addEventListener("touchend", () => {
                start_dist_touch = false;
                start_zoom_touch = false;
            }, {passive: false});

            // Manage history undo/redo events
            const manage_undo_redo = (e) => {
                switch (e && e.inputType) {
                    case "historyUndo":
                        e.preventDefault();
                        e.stopPropagation();
                        this.undo();
                        break;
                    case "historyRedo":
                        e.preventDefault();
                        e.stopPropagation();
                        this.redo();
                        break;
                }
            }
            window.addEventListener("beforeinput", manage_undo_redo);
            window.addEventListener("input", manage_undo_redo); // in case of beforeinput event is not implemented (Firefox)

            // If your component is susceptible to be destroyed, don't forget to
            // use window.removeEventListener in the Vue.js beforeUnmount handler
        },

        components: {
            VueDocumentEditor,
            VueFileToolbarMenu
        }
    }
</script>

<style>
    html {
        height: 100%;
    }

    body {
        margin: 0;
        /*font-family: Avenir, Helvetica, Arial, sans-serif;*/
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        color: black;
        background: rgb(248, 249, 250);
    }

    ::-webkit-scrollbar {
        width: 16px;
        height: 16px;
    }

    ::-webkit-scrollbar-track, ::-webkit-scrollbar-corner {
        display: none;
    }

    ::-webkit-scrollbar-thumb {
        background-color: rgba(0, 0, 0, 0.5);
        border: 5px solid transparent;
        border-radius: 16px;
        background-clip: content-box;
    }

    ::-webkit-scrollbar-thumb:hover {
        background-color: rgba(0, 0, 0, 0.8);
    }

    table {
        width: 100%;
        border-spacing: 0;
    }

    table td {
        position: relative;
        padding: 6px;
        vertical-align: top;
    }

    table.order-table td {
        vertical-align: middle;
    }

    table thead td {
        font-weight: bold;
    }

    .cabecalho {
        border-bottom: 1px solid #CCC;
        text-align: center;
        text-transform: uppercase;
    }

    table tbody td {
        border-top: solid 1px #CCC;
    }

    input[type=number] {
        border: none;
        font-family: inherit;
        font-size: inherit;
        color: inherit;
        background: rgba(200, 250, 230, 0.4);
        padding: 6px;
    }

    @media print {
        .hide-in-print {
            display: none;
        }

        input::-webkit-outer-spin-button,
        input::-webkit-inner-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }

        input[type=number] {
            -moz-appearance: textfield;
            background: none;
        }
    }

    .order {
        display: flex;
        justify-content: space-between;
        margin-bottom: 10px;
    }

    .left-btn {
        position: absolute;
        left: -40px;
        top: 2px;
    }

    .left-btn:hover {
        opacity: 0.6;
    }

    section {
        margin-top: 15px;
    }

    h1, h2, h3, h4, h5, h6 {
        font-size: revert;
        font-weight: revert;
    }
</style>

<style scoped>
    .main {
        width: fit-content;
        min-width: 100%;
    }

    .bar {
        position: sticky;
        left: 0;
        top: 0;
        font-family: inherit;
        width: calc(100vw - 16px);
        z-index: 1000;
        background: rgba(248, 249, 250, 0.8);
        border-bottom: solid 1px rgb(248, 249, 250);
        backdrop-filter: blur(10px);
        --bar-button-active-color: #188038;
        --bar-button-open-color: #188038;
        --bar-button-active-bkg: #e6f4ea;
        --bar-button-open-bkg: #e6f4ea;
    }
</style>

@motla
Copy link
Owner

motla commented Aug 10, 2022

I can't run your example because I don't have your dependencies.
Even though I replaced your expressions by dummy texts and tried, that's what I obtain on Chrome Firefox and Safari Mac:
localhost_5173_
I don't see the bug you mentioned. Please provide a minimal example which shows exactly the bug you encounter.

@ggirardi1
Copy link
Contributor Author

That's weird.

I will do some more tests and report here.

@ggirardi1
Copy link
Contributor Author

ggirardi1 commented Sep 9, 2022

I removed the dependencies and tested again. The problem continues.

I noticed this time that an error pops up in the Dev Console:
image

Maybe it has something to do with it...

My version: latest (2.0.4)

My code:

<template>
    <div class="main">
        <!-- Top bar -->
        <vue-file-toolbar-menu :content="menu" class="bar"/>

        <!-- Document editor -->
        <vue-document-editor class="editor" ref="editor" v-model:content="content" :overlay="overlay" :display="display" :zoom="zoom" :page_margins="page_margins"/>
    </div>
</template>

<script>
    import VueDocumentEditor from 'vue-document-editor'
    import VueFileToolbarMenu from 'vue-file-toolbar-menu';

    export default {
        name: "Print",

        data() {
            return {
                content: [``],
                display: `vertical`,
                page_margins: "45mm 10mm",
                zoom: 0.8,
                mounted: false,
            }
        },

        mounted() {
            this.content[0] = `
                    <div contenteditable="false">
                        <h3 class="mt-4 mb-4 text-center uppercase">Orçamento</h3>
                        <table>
                            <thead>
                                <tr>
                                    <td class="text-left bg-gray-100">DADOS DO CLIENTE</td>
                                    <td class="text-right">OUTROS DADOS</td>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td class="bg-gray-100">
                                        <div><b>XXXX:</b> XXXX</div>
                                        <div><b>Endereço:</b> XXXX</div>
                                        <div><b>Bairro/CEP:</b> XXXX</div>
                                        <div><b>Cidade:</b> XXXX</div>
                                        <div><b>E-mail:</b> XXXX</div>
                                        <div><b>Telefone:</b> (XX) XXXX-XXXX</div>
                                    </td>

                                    <td style="min-width: 250px; text-align:right">
                                        <div><b>Lorem Ipsum is simply dummy:</b> XXXXkm</div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>

                        <section>
                            <h3 class="mt-4 text-center uppercase">Lorem Ipsum is simply dummy</h3>

                            <table>
                                <thead>
                                    <tr>
                                        <td colspan="2" class="cabecalho">Lorem Ipsum is simply dummy</td>
                                    </tr>
                                    <tr>
                                        <td class="bg-gray-100">MEDIDAS</td>
                                        <td style="text-align:right">MATERIAIS</td>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td class="bg-gray-100">
                                            <div><b>Lorem Ipsum is simply dummy:</b> m²</div>
                                            <div>
                                                <b>Observações:</b><br>

                                            </div>
                                        </td>

                                        <td style="min-width: 250px; text-align:right">
                                            <div>Lorem Ipsum is simply dummy: <b>R$ 2.255.64</b></div>
                                            <div>Lorem Ipsum is simply dummy: <b>R$ 2.255.64</b></div>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                        </section>

                        <section>
                           <h3 class="mt-4 text-center uppercase">Peças Simples</h3>

                            <table>
                                <thead>
                                    <tr>
                                        <td colspan="2" class="cabecalho">Cozinha</td>
                                    </tr>
                                    <tr>
                                        <td class="bg-gray-100">MEDIDAS</td>
                                        <td style="text-align:right">MATERIAIS</td>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td class="bg-gray-100">
                                            <div><b>Lorem Ipsum is simply dummy:</b> m²</div>
                                            <div><b>Lorem Ipsum is simply dummy:</b> m</div>
                                            <div><b>Lorem Ipsum is simply dummy:</b> m</div>
                                            <div>
                                                <b>Observações:</b><br>

                                            </div>
                                        </td>

                                        <td style="min-width: 250px; text-align:right">
                                            <div>Lorem Ipsum is simply dummy: <b>R$ 2.255.64</b></div>
                                            <div>Lorem Ipsum is simply dummy: <b>R$ 2.255.64</b></div>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                        </section>

                        <section>
                            <h3 class="mt-4 text-center uppercase">Lorem Ipsum is simply dummy</h3>

                            <table>
                                <thead>
                                    <tr>
                                        <td colspan="2" class="cabecalho">Lorem Ipsum is simply dummy</td>
                                    </tr>
                                    <tr>
                                        <td class="bg-gray-100">Lorem </td>
                                        <td style="text-align:right">MATERIAIS</td>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td class="bg-gray-100">
                                            <div><b>Lorem Ipsum is simply dummy:</b></div>
                                            <div><b>Lorem Ipsum is simply dummy:</b></div>
                                            <div><b>Lorem Ipsum is simply dummy:</b></div>
                                            <div><b>Lorem Ipsum is simply dummy:</b></div>
                                            <div><b>Lorem Ipsum is simply dummy:</b></div>
                                            <div><b>Lorem Ipsum is simply dummy:</b></div>
                                            <div>
                                                <b>Observações:</b><br>

                                            </div>
                                        </td>

                                        <td style="min-width: 250px; text-align:right">
                                            <div>What is Lorem Ipsum? <b>R$ 2.255.64</b></div>
                                            <div>What is Lorem Ipsum? <b>R$ 2.255.64</b></div>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                        </section>

                        <section>
                            <h3 class="mt-3 text-center uppercase">DESCRIMINAÇÃO DA NEGOCIAÇÃO</h3>

                            <ul>
                                <li>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum;</li>
                                <li>There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable;</li>
                                <li>Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old;</li>
                                <li>It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English;</li>
                                <li>The standard Lorem Ipsum passage, used since the 1500s;</li>
                                <li>But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?</li>
                            </ul>
                        </section>
                    </div>
                </div>
                `;
            this.mounted = true;
        },

        computed: {
            menu() {
                return [
                    {
                        text: "Imprimir",
                        title: "Imprimir",
                        icon: "print",
                        click: () => window.print()
                    }
                ];
            }
        },

        methods: {
            overlay(page, total) {
                return `
                        <div style="position: absolute; bottom: 8mm; right: 10mm">Pág. ${page} de ${total}</div>

                        <div style="position: absolute; display: flex; align-items: center; justify-content: space-between; text-align: center; left: 0; top: 0; right: 0; padding: 10mm 15mm">
                            <div>
                                XXXX
                            </div>

                            <div>
                                <span><b>XXXX</b></span><br>
                                <span>XXXX</span><br>
                                <span>XXXX</span><br>
                                <span>XXXX</span><br>

                                <span>(XX) XXXX-XXXX</span>
                            </div>

                            <div class="flex flex-col justify-between self-stretch">
                                <h3>N° XXX</h3>

                                <span><b>Data:</b> XXXX</span>

                                <span><b>Previsão Finalização:</b> XXXX</span>
                            </div>
                        </div>
                    `;
            }
        },

        created() {
            // Initialize gesture flags
            let start_zoom_gesture = false;
            let start_dist_touch = false;
            let start_zoom_touch = false;

            // Manage ctrl+scroll zoom (or trackpad pinch)
            window.addEventListener("wheel", (e) => {
                if (e.ctrlKey) {
                    e.preventDefault();
                    this.zoom = Math.min(Math.max(this.zoom - e.deltaY * 0.01, this.zoom_min), this.zoom_max);
                }
            }, {passive: false});

            // Manage trackpad pinch on Safari
            window.addEventListener("gesturestart", (e) => {
                e.preventDefault();
                start_zoom_gesture = this.zoom;
            });
            window.addEventListener("gesturechange", (e) => {
                e.preventDefault();
                if (!start_zoom_touch) {
                    this.zoom = Math.min(Math.max(start_zoom_gesture * e.scale, this.zoom_min), this.zoom_max);
                }
            });
            window.addEventListener("gestureend", () => {
                start_zoom_gesture = false;
            });

            // Manage pinch to zoom for touch devices
            window.addEventListener("touchstart", (e) => {
                if (e.touches.length == 2) {
                    e.preventDefault();
                    start_dist_touch = Math.hypot(
                        e.touches[0].pageX - e.touches[1].pageX,
                        e.touches[0].pageY - e.touches[1].pageY
                    );
                    start_zoom_touch = this.zoom;
                }
            }, {passive: false});
            window.addEventListener("touchmove", (e) => {
                if (start_dist_touch && start_zoom_touch) {
                    e.preventDefault();
                    let zoom = start_zoom_touch * Math.hypot(
                        e.touches[0].pageX - e.touches[1].pageX,
                        e.touches[0].pageY - e.touches[1].pageY
                    ) / start_dist_touch;
                    this.zoom = Math.min(Math.max(zoom, this.zoom_min), this.zoom_max);
                }
            }, {passive: false});
            window.addEventListener("touchend", () => {
                start_dist_touch = false;
                start_zoom_touch = false;
            }, {passive: false});

            // Manage history undo/redo events
            const manage_undo_redo = (e) => {
                switch (e && e.inputType) {
                    case "historyUndo":
                        e.preventDefault();
                        e.stopPropagation();
                        this.undo();
                        break;
                    case "historyRedo":
                        e.preventDefault();
                        e.stopPropagation();
                        this.redo();
                        break;
                }
            }
            window.addEventListener("beforeinput", manage_undo_redo);
            window.addEventListener("input", manage_undo_redo); // in case of beforeinput event is not implemented (Firefox)

            // If your component is susceptible to be destroyed, don't forget to
            // use window.removeEventListener in the Vue.js beforeUnmount handler
        },

        components: {
            VueDocumentEditor,
            VueFileToolbarMenu
        }
    }
</script>

<style>
    html {
        height: 100%;
    }

    body {
        margin: 0;
        /*font-family: Avenir, Helvetica, Arial, sans-serif;*/
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        color: black;
        background: rgb(248, 249, 250);
    }

    ::-webkit-scrollbar {
        width: 16px;
        height: 16px;
    }

    ::-webkit-scrollbar-track, ::-webkit-scrollbar-corner {
        display: none;
    }

    ::-webkit-scrollbar-thumb {
        background-color: rgba(0, 0, 0, 0.5);
        border: 5px solid transparent;
        border-radius: 16px;
        background-clip: content-box;
    }

    ::-webkit-scrollbar-thumb:hover {
        background-color: rgba(0, 0, 0, 0.8);
    }

    table {
        width: 100%;
        border-spacing: 0;
    }

    table td {
        position: relative;
        padding: 6px;
        vertical-align: top;
    }

    table.order-table td {
        vertical-align: middle;
    }

    table thead td {
        font-weight: bold;
    }

    .cabecalho {
        border-bottom: 1px solid #CCC;
        text-align: center;
        text-transform: uppercase;
    }

    table tbody td {
        border-top: solid 1px #CCC;
    }

    input[type=number] {
        border: none;
        font-family: inherit;
        font-size: inherit;
        color: inherit;
        background: rgba(200, 250, 230, 0.4);
        padding: 6px;
    }

    @media print {
        .hide-in-print {
            display: none;
        }

        input::-webkit-outer-spin-button,
        input::-webkit-inner-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }

        input[type=number] {
            -moz-appearance: textfield;
            background: none;
        }
    }

    .order {
        display: flex;
        justify-content: space-between;
        margin-bottom: 10px;
    }

    .left-btn {
        position: absolute;
        left: -40px;
        top: 2px;
    }

    .left-btn:hover {
        opacity: 0.6;
    }

    section {
        margin-top: 15px;
    }

    h1, h2, h3, h4, h5, h6 {
        font-size: revert;
        font-weight: revert;
    }
    </style>

    <style scoped>
    .main {
        width: fit-content;
        min-width: 100%;
    }

    .bar {
        position: sticky;
        left: 0;
        top: 0;
        font-family: inherit;
        width: calc(100vw - 16px);
        z-index: 1000;
        background: rgba(248, 249, 250, 0.8);
        border-bottom: solid 1px rgb(248, 249, 250);
        backdrop-filter: blur(10px);
        --bar-button-active-color: #188038;
        --bar-button-open-color: #188038;
        --bar-button-active-bkg: #e6f4ea;
        --bar-button-open-bkg: #e6f4ea;
    }
</style>

@motla motla added the acknowledged Acknowledged label Sep 11, 2022
@ggirardi1
Copy link
Contributor Author

Hello @motla !
Any progress on this?

@motla
Copy link
Owner

motla commented Oct 14, 2022

Hi @guilhermeagirardi

Yes! It took me some time to understand what was going on... It was specific to Vue3.
I wanted to make a common patch correcting the other issues as well, but it appears it needs more time.
So I just released a patch for your issue.
Can you test 2.0.5 and give me a feedback?

PS: I just noticed you simply had to write content: [], instead of content: [``], in the data(), it worked as a workaround!

@motla motla closed this as completed Oct 14, 2022
@ggirardi1
Copy link
Contributor Author

Hi @guilhermeagirardi

Yes! It took me some time to understand what was going on... It was specific to Vue3. I wanted to make a common patch correcting the other issues as well, but it appears it needs more time. So I just released a patch for your issue. Can you test 2.0.5 and give me a feedback?

PS: I just noticed you simply had to write content: [], instead of content: [], `` in the data(), it worked as a workaround!

Hi @motla

Thanks, it worked for me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
acknowledged Acknowledged
Projects
None yet
Development

No branches or pull requests

2 participants