KoctrX

Untitled

Jul 11th, 2023
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. let debug_mode = false;
  2. let container = $('#pdf_editor_pages');
  3.  
  4.  
  5. class DeftMobileEditor {
  6.     constructor(base64 = "") {
  7.         this.base64 = base64;
  8.         this.data = false;
  9.         this.fonts = ["Arial", "Helvetica", "HelveticaNeue", "Times-Roman", "serif", "sans-serif"];
  10.         this.initialScreenSize = $(document).height();
  11.         this.bind();
  12.     }
  13.  
  14.     scrollToPage(page = 1) {
  15.         //      let parent_offset = $("#pdf_editor_pages").offset().top,
  16.         //          page_offset = $(`#page_outer_${page}`).offset().top;
  17.  
  18.         //      let parent_offset = $("#pdf_editor_pages")[0].scrollTop,
  19.         //          page_offset = $(`#page_outer_${page}`).offset().top;
  20.  
  21.  
  22.         $(`#page_outer_${page}`)[0].scrollIntoView()
  23.  
  24.         //alert("scroll to page?" + (parent_offset-page_offset));
  25.         //scroller.mCustomScrollbar("scrollTo",parent_offset-page_offset);
  26.     }
  27.  
  28.     selectPage(page, isScrolling = true) {
  29.         if (this.page == page) return false;
  30.         this.page = parseInt(page);
  31.  
  32.         console.log(`event:select_page: ${this.page}`);
  33.         viewer.current_page = parseInt(page);
  34.  
  35.         try {
  36.             if (isScrolling) {
  37.                 this.scrollToPage(this.page);
  38.                 //document.getElementById(`page_outer_${this.page}`).scrollIntoView();
  39.             }
  40.         } catch (err) {
  41.             console.error(err);
  42.         }
  43.  
  44.         const currentPage = document.getElementById('page_outer_' + page);
  45.         if (currentPage) {
  46.             currentPage.classList.remove('hidden');
  47.  
  48.             document.querySelector('.fix_pages').classList.remove('disable_events');
  49.             $(document).trigger("before_pages_render", [viewer.total_pages]);
  50.             TextEditor.showMobileMenu();
  51.         }
  52.     }
  53.  
  54.     addFilePart(part = "") {
  55.         this.base64 += part;
  56.     }
  57.  
  58.     showPage(page = 1) {
  59.         viewer.document_loaded = true;
  60.         //viewer.pages = {};
  61.         // viewer.fonts = {};
  62.         viewer.init(false, this.data, page);
  63.     }
  64.  
  65.     bind() {
  66.         $(document).on("click", ".add_new_text", this.addText);
  67.         $(document).on("click", ".delete_text", this.removeObject);
  68.         $(document).on("click", ".text_styles", this.showTextStyles);
  69.  
  70.         $(document).on("click", ".text_styles", function (e) {
  71.             e.preventDefault();
  72.             $(".text_styles").addClass("active");
  73.             $(".editor_bottom_menu").removeClass("hidden");
  74.         });
  75.  
  76.         $(document).on("click", ".close_text_styles", function (e) {
  77.             $(".text_styles").removeClass("active");
  78.             $(".editor_bottom_menu").addClass("hidden");
  79.         });
  80.  
  81.         $(document).on("click", `.set_bold`, TextEditor.changeBold);
  82.         $(document).on("click", `.set_italic`, TextEditor.changeItalic);
  83.         $(document).on("click", `.set_underline`, TextEditor.changeUnderline);
  84.         $(document).on("click", `.set_stroke`, TextEditor.changeLinethrough);
  85.         $(document).on("change", `.set_font_size`, TextEditor.changeFontSize);
  86.         $(document).on("change", `.set_font_family`, TextEditor.changeFont);
  87.         $(document).on("change", `.set_text_color`, TextEditor.changeFontColor);
  88.         $(document).on("click", ".text_copy", function () {
  89.             let obj = viewer.pages[mobileEditor.page].fcanvas.getActiveObject();
  90.             obj.clone(function (cloned) {
  91.                 cloned.top += 50;
  92.                 cloned.positions = obj.positions;
  93.                 cloned.customLineHeights = obj.customLineHeights;
  94.                 cloned.from_pdf = obj.from_pdf;
  95.                 viewer.pages[mobileEditor.page].fcanvas.add(cloned);
  96.             });
  97.         });
  98.     }
  99.  
  100.     async createDocument() {
  101.         let createPDF = new CreatePDF();
  102.         let result = await createPDF.createDoc();
  103.  
  104.         return result;
  105.     }
  106.  
  107.     removeObject() {
  108.         let obj = viewer.pages[mobileEditor.page].fcanvas.getActiveObject();
  109.         if (obj) {
  110.             viewer.pages[mobileEditor.page].fcanvas.remove(obj);
  111.         }
  112.     }
  113.  
  114.     addText(text = false, center = false, options = {}) {
  115.         let first_page_canvas = viewer.pages[mobileEditor.page].fcanvas;
  116.         let point = { x: (first_page_canvas.width / 2) - (62 / 2), y: first_page_canvas.height / 4 };
  117.         let obj = TextEditor.addText(first_page_canvas, point, text, options);
  118.  
  119.         setTimeout(() => {
  120.             obj.initHiddenTextarea();
  121.             obj.hiddenTextarea.focus();
  122.         }, 100);
  123.  
  124.         if (window.mp) window.mp.editedCheck();
  125.         return obj;
  126.     }
  127.  
  128.     elementSelected(e) {
  129.         let obj = e.target, text_selected_menu = $(".text_selected"), text_not_selected_menu = $(".text_not_selected"), bottom_menu = $(".editor_bottom_menu");
  130.         TextEditor.obj = obj;
  131.         mobileEditor.updateSelectionRange();
  132.  
  133.         if (!obj) {
  134.             text_selected_menu.addClass("hidden");
  135.             text_not_selected_menu.removeClass("hidden");
  136.             bottom_menu.addClass("hidden");
  137.             $(".text_styles").removeClass("active");
  138.             $(".editor_bottom_menu").addClass("hidden");
  139.  
  140.             return;
  141.         } else {
  142.             e.target.canvas.setActiveObject(e.target).renderAll();
  143.         }
  144.  
  145.         text_selected_menu.removeClass("hidden");
  146.         text_not_selected_menu.addClass("hidden");
  147.         if (['i-text', 'textbox'].includes(obj.type)) {
  148.             let parsed_styles = mobileEditor.parseStyles();
  149.             let ff_select = $(".set_font_family");
  150.             ff_select.html("");
  151.  
  152.             let fontF = (obj.getSelectionStyles(0, obj.text.length))[0].fontFamily;
  153.             if (!fontF) fontF = obj.fontFamily;
  154.             let current_fonts = fontF.split(", ");
  155.             current_fonts = [...new Set(current_fonts)].join(",");
  156.             ff_select.find("option[data-embeded-font=1]").remove();
  157.             let font_name = current_fonts;
  158.  
  159.             try {
  160.                 font_name = current_fonts.replace(/(g_d.*?)\,/, "").split(",")[0];
  161.             } catch (e) {
  162.                 console.warn("cath on font split");
  163.             }
  164.  
  165.             ff_select.prepend(`<option data-embeded-font=1 value='${current_fonts}'>${font_name}</option>`);
  166.             let fonts = mobileEditor.fonts.filter((f) => { return f == current_fonts ? false : true });
  167.             fonts.forEach((font) => {
  168.                 let font_name = font;
  169.                 ff_select.append(`<option value="${font}">${font_name}</option>`);
  170.             });
  171.  
  172.             if (parsed_styles.bold) {
  173.                 $(".set_bold").addClass("active");
  174.             } else {
  175.                 $(".set_bold").removeClass("active");
  176.             }
  177.  
  178.             if (parsed_styles.italic) {
  179.                 $(".set_italic").addClass("active");
  180.             } else {
  181.                 $(".set_italic").removeClass("active");
  182.             }
  183.  
  184.             if (parsed_styles.underline) {
  185.                 $(".set_underline").addClass("active");
  186.             } else {
  187.                 $(".set_underline").removeClass("active");
  188.             }
  189.  
  190.             if (parsed_styles.stroke) {
  191.                 $(".set_stroke").addClass("active");
  192.             } else {
  193.                 $(".set_stroke").removeClass("active");
  194.             }
  195.  
  196.             const setFontSize = fontSize => {
  197.                 if (window.mp) {
  198.                     window.mp.rangesElements.fontSize.update({ from: fontSize });
  199.                 }
  200.             };
  201.  
  202.             window.mp.rangesElements.opacity.update({ from: parsed_styles.opacity });
  203.             window.mp.rangesElements.angle.update({ from: parsed_styles.angle });
  204.             if (parsed_styles.fontSize) {
  205.                 setFontSize(parsed_styles.fontSize);
  206.                 $(".set_font_size").val(parsed_styles.fontSize);//find(`option[value=${parsed_styles.fontSize}]`).;
  207.             } else {
  208.                 setFontSize(8);
  209.                 $(".set_font_size").val(8);
  210.             }
  211.  
  212.             if (parsed_styles.color) {
  213.                 if (window.mp) {
  214.                     window._lockColorChanges = true;
  215.                     window.mp.colorPicker.fontColor.setColor(parsed_styles.color);
  216.                 }
  217.  
  218.                 $(".pdf-mobile-colorpicker .set_text_color_text_color").css("background", parsed_styles.color);
  219.                 $(".pdf-mobile-colorpicker .set_text_color_text").text(parsed_styles.color);
  220.             }
  221.         } else if (['rect', 'circle'].includes(obj.type)) {
  222.             if (window.mp) {
  223.                 window._lockColorChanges = true;
  224.                 window.mp.colorPicker.borderColorShape.setColor(obj.stroke);
  225.                 window._lockColorChanges = true;
  226.                 window.mp.colorPicker.fillShapeColor.setColor(obj.fill);
  227.                 window.mp.rangesElements.borderShape.update({ from: obj.strokeWidth });
  228.             }
  229.         }
  230.  
  231.         return false;
  232.     }
  233.  
  234.     parseStyles() {
  235.         let range = this.updateSelectionRange();
  236.         let ret = {
  237.             bold: false,
  238.             italic: false,
  239.             underline: false,
  240.             stroke: false,
  241.             fontSize: 8,
  242.             fontFamily: "Arial",
  243.             color: "rgb(0,0,0)",
  244.             opacity: TextEditor.obj && TextEditor.obj.opacity ? TextEditor.obj.opacity : 1,
  245.             angle: TextEditor.obj && TextEditor.obj.angle ? TextEditor.obj.angle : 0,
  246.         };
  247.  
  248.         if (range && range[0] == range[1]) {
  249.             range[1] += 1;
  250.         }
  251.  
  252.         if (range) {
  253.             let selection_styles = TextEditor.obj.getSelectionStyles(range[0], range[1], true);
  254.             let bold_styles = [],
  255.                 italic_styles = [],
  256.                 underline_styles = [],
  257.                 stroke_styles = [],
  258.                 font_sizes = [],
  259.                 font_families = [],
  260.                 colors = [];
  261.  
  262.             selection_styles.forEach((char_style) => {
  263.                 if (char_style.fontWeight) {
  264.                     bold_styles.push(char_style.fontWeight);
  265.                 }
  266.  
  267.                 if (char_style.fontStyle) {
  268.                     italic_styles.push(char_style.fontStyle);
  269.                 }
  270.  
  271.                 if (typeof char_style.underline != 'undefined') {
  272.                     underline_styles.push(char_style.underline ? "underline" : "normal");
  273.                 }
  274.  
  275.                 font_sizes.push(char_style.fontSize);
  276.                 colors.push(char_style.fill ? char_style.fill : "rgb(0,0,0)");
  277.                 font_families.push(...char_style.fontFamily.split(",").map((f) => { return f.trim() }));
  278.             });
  279.  
  280.             let bold_set = [...new Set(bold_styles)],
  281.                 italic_set = [...new Set(italic_styles)],
  282.                 underline_set = [...new Set(underline_styles)],
  283.                 stroke_set = [],
  284.                 fontsize_set = [...new Set(font_sizes)],
  285.                 fontfamily_set = [...new Set(font_families)],
  286.                 colors_set = [...new Set(colors)];
  287.             ret.fontFamily = fontfamily_set.join(",");
  288.  
  289.             if (colors_set.length > 1) {
  290.                 ret.color = "rgb(0,0,0)";
  291.             } else {
  292.                 ret.color = colors_set[0];
  293.             }
  294.  
  295.             if (fontsize_set.length) {
  296.                 if (fontsize_set.length > 1) {
  297.                     ret.fontSize = TextEditor.obj.fontSize || "";
  298.                 } else if (fontsize_set.length == 1) {
  299.                     let scale = 1;
  300.                     if (viewer.pages[mobileEditor.page]) {
  301.                         scale = viewer.pages[mobileEditor.page].scale;
  302.                     }
  303.  
  304.                     ret.fontSize = Math.ceil(fontsize_set[0] / scale);
  305.                 } else {
  306.                     ret.fontSize = TextEditor.obj.fontSize || "";
  307.                 }
  308.             } else {
  309.                 ret.fontSize = 8;
  310.             }
  311.  
  312.             if (underline_set.length) {
  313.                 if (underline_set.length > 1) {
  314.                     ret.underline = false;
  315.                 } else if (underline_set[0] == 'underline' && underline_set.length == 1) {
  316.                     ret.underline = true;
  317.                 } else {
  318.                     ret.underline = false;
  319.                 }
  320.             } else {
  321.                 ret.underline = false;
  322.             }
  323.  
  324.             if (italic_set.length) {
  325.                 if (italic_set.length > 1) {
  326.                     ret.italic = false;
  327.                 } else if (italic_set[0] == 'italic' && italic_set.length == 1) {
  328.                     ret.italic = true;
  329.                 } else {
  330.                     ret.italic = false;
  331.                 }
  332.             } else {
  333.                 ret.italic = false;
  334.             }
  335.  
  336.             if (bold_set.length) {
  337.                 if (bold_set.length > 1) {
  338.                     ret.bold = false;
  339.                 } else if (bold_set[0] == 'bold' && bold_set.length) {
  340.                     ret.bold = true;
  341.                 } else {
  342.                     ret.bold = false;
  343.                 }
  344.             } else {
  345.                 ret.bold = false;
  346.             }
  347.  
  348.             return ret;
  349.         }
  350.  
  351.         return ret;
  352.     }
  353.  
  354.     updateSelectionRange() {
  355.         if (TextEditor.obj && ['textbox', 'i-text', 'text'].includes(TextEditor.obj.type)) {
  356.             if (TextEditor.obj && TextEditor.obj.isEditing) {
  357.                 TextEditor.start = TextEditor.obj.selectionStart ? TextEditor.obj.selectionStart : 0;
  358.                 TextEditor.end = TextEditor.obj.selectionEnd ? (TextEditor.obj.selectionEnd) : TextEditor.obj.text.length;
  359.  
  360.                 return [TextEditor.start, TextEditor.end];
  361.             } else if (TextEditor.obj && !TextEditor.obj.isEditing) {
  362.                 TextEditor.start = 0;
  363.                 TextEditor.end = TextEditor.obj.text.length;
  364.  
  365.                 return [TextEditor.start, TextEditor.end];
  366.             } else {
  367.                 TextEditor.start = 0;
  368.                 TextEditor.end = 0;
  369.  
  370.                 return false;
  371.             }
  372.         }
  373.  
  374.         return false;
  375.     }
  376.  
  377.     selectionUpdate(e) {
  378.         mobileEditor.updateSelectionRange();
  379.     }
  380.  
  381.     showTextStyles() {
  382.  
  383.     }
  384. }
  385.  
  386. let mobileEditor = new DeftMobileEditor("");
  387. async function savePDF() {
  388.     try {
  389.         let pages = [];
  390.         Object.entries(viewer.pages).forEach(([pn, page], i) => {
  391.             if (page && page.modified) pages.push([pages.length + 1, pn]);
  392.         });
  393.  
  394.         if (!pages || !pages.length) pages = [mobileEditor.page, mobileEditor.page];
  395.  
  396.         const blob = await mobileEditor.createDocument();
  397.         const url = URL.createObjectURL(blob) + `#pages=${JSON.stringify(pages)}`;
  398.  
  399.         if (debug_mode) {
  400.             window.open(url);
  401.         } else {
  402.             window.location = url;
  403.         }
  404.     } catch (e) {
  405.         console.error(e);
  406.         alert("Error...");
  407.     }
  408. }
  409.  
  410. async function addPagePart(data = "") {
  411.     mobileEditor.addFilePart(data);
  412. }
  413.  
  414. $(document).on('before_pages_render', (e, countPages) => {
  415.     const page = mobileEditor.page;
  416.  
  417.     Array.from(document.querySelectorAll('.btn_p')).forEach(el => el.classList.remove('disabled'));
  418.     if (page == countPages) document.querySelector('.next_page_btn').classList.add('disabled');
  419.     if (page <= 1) document.querySelector('.prev_page_btn').classList.add('disabled');
  420.     document.querySelector('.title_page').innerHTML = `${page} / ${countPages}`;
  421. });
  422.  
  423. async function mobileInit(page = 1, editorChange = false) {
  424.     try {
  425.         document.querySelector('.fix_pages').classList.add('disable_events');
  426.         mobileEditor.page = page;
  427.         if (!viewer.document_loaded) {
  428.             let b1 = await fetch(mobileEditor.base64).then(res => res.blob());
  429.             let data = await viewer.getBlob(b1);
  430.             mobileEditor.data = data;
  431.         }
  432.  
  433.         // Object.keys(viewer.pages).forEach((p) => {
  434.         //  viewer.pages[p].fcanvas.dispose();
  435.         //  delete viewer.pages[p];
  436.         // });
  437.  
  438.         if (!editorChange) $("#pdf_editor_pages").html("");
  439.         Array.from(document.querySelectorAll('.page-main-part'))
  440.             .forEach(el => el.classList.add('hidden'));
  441.  
  442.         const currentPage = document.getElementById('page_outer_' + page);
  443.         if (currentPage) {
  444.             currentPage.classList.remove('hidden');
  445.  
  446.             document.querySelector('.fix_pages').classList.remove('disable_events');
  447.             $(document).trigger("before_pages_render", [viewer.total_pages]);
  448.             TextEditor.showMobileMenu();
  449.         } else {
  450.             mobileEditor.showPage(page);
  451.         }
  452.  
  453.     } catch (e) {
  454.         alert("error: " + e.message);
  455.     }
  456. }
  457.  
  458. const mp = new class {
  459.     constructor() {
  460.         this.draw_enabled = false;
  461.         this.texts_active = false;
  462.         this.images_active = false;
  463.         this.image_is_watermark = false;
  464.         this.now_scrolling = false;
  465.         this.rangesElements = {
  466.             fontSize: false,
  467.         };
  468.  
  469.  
  470.         this.text_menu_opened = false;
  471.         this.images_menu_opened = false;
  472.  
  473.         this.last_touched_page = false;
  474.  
  475.         this.touch = {
  476.             events: [],
  477.             use_scroll: true,
  478.             use_fabric: false,
  479.         };
  480.  
  481.         this.colorPicker = {
  482.             fontColor: false
  483.         };
  484.  
  485.         this.annotationElements = {
  486.             add: document.getElementById('add_annotation'),
  487.             delete: document.getElementById('delete_annotation'),
  488.             title: document.querySelector('[name="title_annotation"]'),
  489.             message: document.querySelector('[name="title_message"]')
  490.         };
  491.  
  492.         this.elements = {
  493.             tools: {
  494.                 textEdit: document.querySelector('[data-button="text_edit"]'),
  495.                 text: document.querySelector('[data-button="text"]'),
  496.                 delete: document.querySelector('[data-button="delete"]'),
  497.                 annotations: document.querySelector('[data-button="annotations"]'),
  498.                 setting: document.querySelector('[data-button="setting"]'),
  499.                 watermark: document.querySelector('[data-button="watermark"]'),
  500.                 setting_dropdown: document.querySelector('[data-button="setting_dropdown"]'),
  501.                 deselect_dropdown: document.querySelector('[data-button="deselect_dropdown"]'),
  502.             },
  503.  
  504.             mfp: document.querySelector('.mobile-footer--pdf'),
  505.             footer: {
  506.                 text: document.querySelector('[data-footer="add_text"]'),
  507.                 watermark: document.querySelector('[data-footer="add_watermark"]'),
  508.                 form: document.querySelector('[data-footer="add_form"]'),
  509.                 image: document.querySelector('[data-footer="add_image"]'),
  510.                 shape: document.querySelector('[data-footer="add_shape"]'),
  511.                 whiteout: document.querySelector('[data-footer="add_shiteout"]'),
  512.                 freestyle: document.querySelector('[data-footer="add_freestyle"]'),
  513.             },
  514.  
  515.             f_footer: {
  516.                 check_on: document.querySelector('[data-fk="check_on"]'),
  517.                 check_off: document.querySelector('[data-fk="check_off"]'),
  518.                 radio: document.querySelector('[data-fk="radio"]'),
  519.                 input: document.querySelector('[data-fk="input"]'),
  520.  
  521.                 textarea: document.querySelector('[data-fk="textarea"]'),
  522.                 checkbox: document.querySelector('[data-fk="checkbox"]'),
  523.                 dropdown: document.querySelector('[data-fk="dropdown"]'),
  524.             },
  525.  
  526.             s_footer: {
  527.                 circle: document.querySelector('[data-fk="circle"]'),
  528.                 rect: document.querySelector('[data-fk="rect"]'),
  529.             },
  530.  
  531.             freestyle: {
  532.                 colorChecks: document.querySelector('[data-tab="color_checks"]'),
  533.                 brushType: document.querySelector('[data-tab="brush_type"]'),
  534.                 applyDrawing: document.querySelector('[data-tab="applyDrawing"]'),
  535.             },
  536.             watermark: {
  537.                 settings: document.querySelector('[data-tab="watermark_settings"]'),
  538.                 types: document.querySelector('[data-tab="watermark_type"]'),
  539.             },
  540.             texts: {
  541.                 modify_text: document.querySelector('[data-tab="text_tools"] [data-type="modify_text"]'),
  542.                 add_text: document.querySelector('[data-tab="text_tools"] [data-type="add_text"]'),
  543.             },
  544.  
  545.             images: {
  546.                 modify_images: document.querySelector('[data-tab="images_tools"] [data-type="modify_images"]'),
  547.                 add_image: document.querySelector('[data-tab="images_tools"] [data-type="add_image"]'),
  548.             },
  549.  
  550.             closeFooter: document.querySelectorAll('[data-tab="closeFooterMenu"]'),
  551.  
  552.             modals: {
  553.                 shapeStyle: document.getElementById('mobile-settings-style'),
  554.                 textStyle: document.getElementById('mobile-text-style'),
  555.                 watermarkSetting: document.getElementById('mobile-watermark-setting'),
  556.                 selectSetting: document.getElementById('mobile-select-setting'),
  557.                 annotations: document.getElementById('mobile-annotation'),
  558.             }
  559.         };
  560.  
  561.         this.annotationElements.add.addEventListener('click', () => this.addAnnotation({}));
  562.         this.annotationElements.delete.addEventListener('click', () => this.deleteAnnotation());
  563.  
  564.         this.initFooterEvents();
  565.         this.initToolsEvents();
  566.         this.initRangesElements();
  567.     }
  568.  
  569.  
  570.  
  571.     // disableScroll() {
  572.  
  573.     //  this.scroll_enabled = false;
  574.     //  container.css({ overflow: "hidden" })
  575.     //  //scroller.mCustomScrollbar("disable");
  576.     // }
  577.  
  578.     // enableScroll() {
  579.     //  this.scroll_enabled = true;
  580.  
  581.     //  if (mp.last_touched_page && viewer.pages[mp.last_touched_page] && viewer.pages[mp.last_touched_page].fcanvas) {
  582.     //      viewer.pages[mp.last_touched_page].fcanvas.renderAll();
  583.     //  }
  584.  
  585.     //  container.css({
  586.     //      "overflow": "scroll",
  587.     //  });
  588.     // }
  589.  
  590.     disableScroll() {
  591.         this.scroll_enabled = false;
  592.         container.css({ overflow: "hidden", 'touch-action': 'pinch-zoom' });
  593.         //scroller.mCustomScrollbar("disable");
  594.     }
  595.  
  596.     enableScroll() {
  597.         this.scroll_enabled = true;
  598.  
  599.         if (mp.last_touched_page && viewer.pages[mp.last_touched_page] && viewer.pages[mp.last_touched_page].fcanvas) {
  600.             viewer.pages[mp.last_touched_page].fcanvas.renderAll();
  601.         }
  602.  
  603.         container.css({
  604.             "overflow": "scroll",
  605.             'touch-action': 'auto'
  606.         });
  607.     }
  608.  
  609.     clearStylesFooter(type = false) {
  610.         if (type != 'text') {
  611.             this.text_menu_opened = false;
  612.         }
  613.  
  614.         this.elements.mfp.classList.remove('mobmenu--active');
  615.         Array.from(document.querySelectorAll('.mobile-list-control'))
  616.             .forEach(el => el.classList.remove('mobile-list-control--active'));
  617.  
  618.  
  619.         if (viewer.pages[mobileEditor.page]) {
  620.             let canvas = viewer.pages[mobileEditor.page].fcanvas;
  621.             canvas.isDrawingMode = false;
  622.         }
  623.     }
  624.  
  625.     openTextStylesMenu() {
  626.         if (!TextEditor.obj) {
  627.             TextEditor.obj = viewer.pages[mobileEditor.page].fcanvas.getActiveObject();
  628.             mobileEditor.elementSelected({ target: TextEditor.obj });
  629.             mobileEditor.parseStyles();
  630.         }
  631.  
  632.         if (TextEditor.obj && TextEditor.obj.is_watermark) {
  633.             document.querySelectorAll(".only_for_watermark").forEach(function (el) {
  634.                 el.classList.remove('hidden')
  635.             });
  636.         } else {
  637.             document.querySelectorAll(".only_for_watermark").forEach(function (el) {
  638.                 el.classList.add('hidden')
  639.             });
  640.         }
  641.  
  642.         this.showModal('textStyle', true);
  643.     }
  644.  
  645.     renderWatermarkTextPage(page) {
  646.         const canvas = page.fcanvas;
  647.         if (!canvas) return false;
  648.         const padding = 10;
  649.         const tx = 'сreаtеd by DеftPDF';
  650.         //canvas.getObjects().forEach(obj => obj.subtype == 'watermark_deft' ? canvas.remove(obj) : '');
  651.         canvas.getObjects().forEach(obj => (obj.text == tx || obj.unicode_string == tx) ? canvas.remove(obj) : '');
  652.         if (!this.isEnabledWaterText) return;
  653.  
  654.         const text = new fabric.IText(tx, { fontSize: 14 });
  655.         text.set({
  656.             left: canvas.width - text.width - padding,
  657.             top: canvas.height - text.height - padding,
  658.             subtype: 'watermark_deft',
  659.             selectable: false,
  660.             evented: false,
  661.             lockMovementX: true,
  662.             lockMovementY: true
  663.         });
  664.  
  665.         canvas.add(text);
  666.     }
  667.  
  668.     mobileUI(key, data) {
  669.         switch (key) {
  670.             case 'watermark_deft': {
  671.                 if (data) this.isEnabledWaterText = data.isEnabled;
  672.                 // data.isEnabled
  673.                 Object.values(viewer.pages).forEach(page => this.renderWatermarkTextPage(page));
  674.                 break;
  675.             }
  676.  
  677.             case 'discard_active': {
  678.                 try {
  679.                     const canvas = viewer.pages[mobileEditor.page].fcanvas;
  680.                     const active = canvas.getActiveObject();
  681.                     canvas.discardActiveObject();
  682.                     active.moveTo(active.zIndex || 0);
  683.                 } catch (e) {
  684.                     console.error(e);
  685.                 }
  686.  
  687.                 break;
  688.             }
  689.  
  690.             case 'modify_text': {
  691.                 enableAllTexts();
  692.                 this.texts_active = true;
  693.                 // if (this.texts_active) {
  694.                 //  this.deactivateTexts();
  695.                 //  this.enableScroll();
  696.                 //  this.texts_active = false;
  697.                 // } else {
  698.                 //  enableAllTexts();
  699.                 //  this.texts_active = true;
  700.                 //  this.disableScroll();
  701.                 // }
  702.  
  703.                 break;
  704.             }
  705.  
  706.             case 'disable_text':
  707.                 this.deactivateTexts();
  708.                 //this.enableScroll();
  709.                 this.texts_active = false;
  710.                 break;
  711.  
  712.             case 'add_text':
  713.                 mobileEditor.addText();
  714.                 this.texts_active = true;
  715.                 break;
  716.  
  717.             case 'watermark': // fix
  718.                 // this.addWatermarkOnPage();
  719.                 this.elements.mfp.classList.add('mobmenu--active');
  720.                 this.elements.footer['watermark'].classList.add('mobile-list-control--active');
  721.                 break;
  722.  
  723.             case 'check_on':
  724.             case 'check_off':
  725.             case 'radio':
  726.             case 'input':
  727.             case 'textarea':
  728.             case 'checkbox':
  729.             case 'dropdown':
  730.                 return this.addFormItem(key);
  731.  
  732.             case 'modify_images': {
  733.                 // if (this.images_active) {
  734.                 //  dissableAllImages();
  735.                 //  this.enableScroll();
  736.  
  737.                 //  this.images_active = false;
  738.                 // } else {
  739.                 //  enableAllImages();
  740.                 //  //this.elements.images.modify_images.classList.add("active");
  741.                 //  this.images_active = true;
  742.                 //  this.disableScroll();
  743.                 // }
  744.                 enableAllImages();
  745.                 this.images_active = true;
  746.  
  747.                 break;
  748.             }
  749.  
  750.             case 'add_image':
  751.                 document.querySelector('.ts').click();
  752.                 break;
  753.  
  754.             case 'circle':
  755.             case 'rect':
  756.             case 'whiteout':
  757.                 return this.addShape(key);
  758.  
  759.             case 'enable_draw':
  760.                 return this.enableDraw(data); // { brush, color }
  761.  
  762.             case 'disable_draw':
  763.                 return this.disableDraw(); // { brush, color }
  764.  
  765.  
  766.             case 'next_page': {
  767.                 if (mobileEditor.page >= viewer.total_pages) return;
  768.                 mobileEditor.selectPage(mobileEditor.page + 1);
  769.                 break;
  770.             }
  771.  
  772.             case 'prev_page': {
  773.                 if (mobileEditor.page <= 1) return;
  774.                 mobileEditor.selectPage(mobileEditor.page - 1);
  775.                 break;
  776.             }
  777.  
  778.             case 'open_page': {
  779.                 if (data && data.page && data.page >= 1 && data.page <= viewer.total_pages) {
  780.                     mobileEditor.selectPage(data.page);
  781.                 }
  782.  
  783.                 break;
  784.             }
  785.         }
  786.     }
  787.  
  788.     addWatermarkOnPage() {
  789.         const canvas = viewer.pages[mobileEditor.page].fcanvas;
  790.         const active = canvas.getActiveObject();
  791.         if (active && active.is_watermark) {
  792.             mp.rangesElements.angle_watermark.update({ from: active.angle });
  793.             mp.rangesElements.opacity_watermark.update({ from: active.opacity });
  794.         }
  795.  
  796.         this.showModal('watermarkSetting', true);
  797.     }
  798.  
  799.     initToolsEvents() {
  800.         document.querySelector("#apply_select_modal").addEventListener("click", (e) => {
  801.             e.preventDefault();
  802.             const options = document.querySelector('[name="textarea_select"]').value.split('\n').filter(q => q);
  803.             if (options && options.length) {
  804.                 const canvas = viewer.pages[mobileEditor.page].fcanvas;
  805.                 const active = canvas.getActiveObject();
  806.                 active.set({ options }).canvas.renderAll();
  807.  
  808.  
  809.                 if (formElements) formElements.renderOptions(active);
  810.             }
  811.  
  812.             e.target.closest('.modal--mobile').classList.remove('modal--show--mobile');
  813.         });
  814.  
  815.         ////        document.querySelector('[name="textarea_select"]').addEventListener('input', e => {
  816.         ////            const options = e.target.value.split('\n').filter(q => q);
  817.         ////            if (options && options.length) {
  818.         ////                const canvas = viewer.pages[mobileEditor.page].fcanvas;
  819.         ////                const active = canvas.getActiveObject();
  820.         ////                active.set({ options }).canvas.renderAll();
  821.  
  822.         ////                if (formElements) formElements.renderOptions(active);
  823.         ////            }
  824.         ////        });
  825.  
  826.         this.elements.tools.annotations.addEventListener('click', e => this.openAnnotationsPopup());
  827.         this.elements.tools.delete.addEventListener('click', e => this.removeObject());
  828.         this.elements.tools.setting.addEventListener('click', e => this.showModal('shapeStyle', true));
  829.  
  830.         this.elements.texts.modify_text.addEventListener("click", (e) => {
  831.             e.preventDefault();
  832.             if (this.texts_active) {
  833.                 this.deactivateTexts();
  834.                 this.enableScroll();
  835.                 this.texts_active = false;
  836.             } else {
  837.                 enableAllTexts();
  838.                 this.elements.texts.modify_text.classList.add("active");
  839.                 this.texts_active = true;
  840.                 this.disableScroll();
  841.                 //this.disableScroll();
  842.             }
  843.         });
  844.  
  845.         this.elements.texts.add_text.addEventListener("click", (e) => {
  846.             e.preventDefault();
  847.             mobileEditor.addText();
  848.         });
  849.  
  850.         this.elements.images.modify_images.addEventListener("click", (e) => {
  851.             e.preventDefault();
  852.             //alert(this.images_active);
  853.             if (this.images_active) {
  854.                 dissableAllImages();
  855.                 this.enableScroll();
  856.                 this.images_active = false;
  857.             } else {
  858.                 enableAllImages();
  859.                 this.elements.images.modify_images.classList.add("active");
  860.                 this.images_active = true;
  861.                 this.disableScroll();
  862.             }
  863.         });
  864.  
  865.         this.elements.images.add_image.addEventListener("click", (e) => {
  866.             const ts = document.querySelector('.ts');
  867.             ts.click();
  868.         });
  869.  
  870.         this.elements.tools.watermark.addEventListener('click', e => this.addWatermarkOnPage());
  871.         this.elements.tools.setting_dropdown.addEventListener('click', e => {
  872.             const active = viewer.pages[mobileEditor.page].fcanvas.getActiveObject();
  873.             if (active) {
  874.                 const options = active.options;
  875.                 document.querySelector('[name="textarea_select"]').value = options.join('\n');
  876.                 this.showModal('selectSetting', true);
  877.             }
  878.         });
  879.  
  880.         this.elements.tools.deselect_dropdown.addEventListener('click', e => {
  881.             this.mobileUI('discard_active');
  882.         });
  883.  
  884.         this.elements.tools.text.addEventListener('click', e => this.openTextStylesMenu());
  885.         this.elements.tools.textEdit.addEventListener('click', e => {
  886.             const active = this.getActiveObject();
  887.             if (active) active.enterEditing();
  888.         });
  889.     }
  890.  
  891.  
  892.     deactivateTexts() {
  893.         if (this.texts_active) {
  894.             dissableAllTexts();
  895.             this.texts_active = false;
  896.         }
  897.         this.elements.texts.modify_text.classList.remove("active");
  898.         //this.enableScroll();
  899.         //scroller.mCustomScrollbar("update");
  900.     }
  901.  
  902.  
  903.     toggleTextsMenu(key, e) {
  904.         if (this.text_menu_opened) {
  905.             this.text_menu_opened = false;
  906.             //this.enableScroll();
  907.             this.closeMenu(key);
  908.             //this.texts_active = false;
  909.         } else {
  910.             this.text_menu_opened = true;
  911.             //this.disableScroll();
  912.             this.texts_active = true;
  913.             this.openMenu(key);
  914.             enableAllTexts();
  915.             this.elements.texts.modify_text.classList.add("active");
  916.         }
  917.     }
  918.  
  919.     openMenu(key) {
  920.         this.elements.mfp.classList.add('mobmenu--active');
  921.         this.elements.footer[key].classList.add('mobile-list-control--active');
  922.     }
  923.     closeMenu(key) {
  924.         this.elements.mfp.classList.remove("mobmenu--active");
  925.         this.elements.footer[key].classList.remove('mobile-list-control--active');
  926.     }
  927.  
  928.     openPopupMenu(key) {
  929.         this.elements.mfp.classList.add('mobmenu--active-popup');
  930.         this.elements.footer[key].classList.add('mobile-list-control--active');
  931.     }
  932.  
  933.     defaultEventListener(e) {
  934.         e.preventDefault();
  935.         e.stopPropagation();
  936.         this.disableDraw();
  937.         //document.getElementById(`page_outer_${mobileEditor.page}`).scrollIntoView();
  938.     }
  939.  
  940.     initFooterEvents() {
  941.  
  942.         this.clearStylesFooter();
  943.         const addElement = (type = false, e = false) => {
  944.             this.closePopupButtons();
  945.             this.deactivateTexts();
  946.             dissableAllImages();
  947.  
  948.             if (type == 'text') {
  949.  
  950.             } else {
  951.             }
  952.             this.clearStylesFooter(type);
  953.  
  954.             switch (type) {
  955.                 //case 'text': return mobileEditor.addText();
  956.                 case 'text': return this.toggleTextsMenu('text', e);
  957.                 case 'watermark': return this.openPopupMenu('watermark');
  958.                 case 'image': return this.openImage('image', e);
  959.                 case 'whiteout': return this.addShape('whiteout');
  960.                 case 'form': return this.openMenu('form');
  961.                 case 'shape': return this.openMenu('shape');
  962.                 case 'freestyle': return this.openFreeStyle('freestyle');
  963.             }
  964.         };
  965.  
  966.         for (const key in this.elements.footer) {
  967.             this.elements.footer[key].querySelector('.btn--link').addEventListener('click', (e) => {
  968.                 this.defaultEventListener(e);
  969.                 addElement(key, e);
  970.             });
  971.         }
  972.  
  973.         for (const key in this.elements.f_footer) {
  974.             this.elements.f_footer[key].addEventListener('click', e => {
  975.                 this.defaultEventListener(e);
  976.                 this.clearStylesFooter();
  977.                 this.addFormItem(key);
  978.             });
  979.         }
  980.  
  981.         for (const key in this.elements.s_footer) {
  982.             this.elements.s_footer[key].addEventListener('click', e => {
  983.                 this.defaultEventListener(e);
  984.                 this.clearStylesFooter();
  985.                 this.addShape(key);
  986.             });
  987.         }
  988.  
  989.         const ch = this.elements.freestyle.colorChecks;
  990.         Array.from(ch.querySelectorAll('.element-mob')).forEach((el, i, arr) => {
  991.             el.addEventListener('click', e => {
  992.                 this.defaultEventListener(e);
  993.                 arr.forEach(element => element.classList.remove('active-menu-box'));
  994.                 el.classList.add('active-menu-box');
  995.                 this.enableDraw();
  996.             });
  997.         });
  998.  
  999.         if (true) {
  1000.             let w_types = this.elements.watermark.types;
  1001.             Array.from(w_types.querySelectorAll('.element-mob')).forEach((el, i, arr) => {
  1002.                 el.addEventListener('click', e => {
  1003.                     this.defaultEventListener(e);
  1004.  
  1005.                     e.preventDefault();
  1006.                     let wattermark_type = e.target.dataset.type;
  1007.                     this.addWatermark(wattermark_type);
  1008.                 });
  1009.             });
  1010.         }
  1011.  
  1012.         const bt = this.elements.freestyle.brushType;
  1013.         Array.from(bt.querySelectorAll('.element-mob')).forEach((el, i, arr) => {
  1014.             el.addEventListener('click', e => {
  1015.                 this.defaultEventListener(e);
  1016.                 arr.forEach(element => element.classList.remove('active-brush'));
  1017.                 el.classList.add('active-brush');
  1018.                 this.enableDraw();
  1019.             });
  1020.         });
  1021.  
  1022.         this.elements.freestyle.applyDrawing.addEventListener('click', e => {
  1023.             e.preventDefault();
  1024.             this.applyDraw();
  1025.         });
  1026.  
  1027.         Array.from(this.elements.closeFooter).forEach(el => {
  1028.             el.addEventListener('click', (e) => {
  1029.                 this.applyDraw(e);
  1030.                 //this.clearStylesFooter()
  1031.             });
  1032.         });
  1033.     }
  1034.  
  1035.     applyDraw() {
  1036.         //      let pages = allViewedPages();
  1037.         //      pages.forEach((page)=>{
  1038.         //          let canvas = viewer.pages[page].fcanvas;
  1039.         //          canvas.isDrawingMode = false;
  1040.         //      });
  1041.         //      this.draw_enabled = false;
  1042.         //      this.enableScroll();
  1043.         this.disableDraw();
  1044.         this.clearStylesFooter();
  1045.     }
  1046.  
  1047.  
  1048.     openFreeStyle(key) {
  1049.         this.openMenu('freestyle');
  1050.         this.enableDraw();
  1051.     }
  1052.  
  1053.     watermarksRemove() {
  1054.         let watermaks = this.getWatermarks(),
  1055.             canvas = this.getCanvas();
  1056.  
  1057.         watermaks.forEach((obj) => {
  1058.             canvas.remove(obj);
  1059.         });
  1060.  
  1061.         canvas.renderAll();
  1062.     }
  1063.  
  1064.     getWatermarks() {
  1065.         let watermarks = [];
  1066.         let canvas = this.getCanvas();
  1067.         canvas.getObjects().forEach((obj) => {
  1068.             if (obj.is_watermark) {
  1069.                 watermarks.push(obj);
  1070.             }
  1071.         });
  1072.         return watermarks;
  1073.     }
  1074.  
  1075.     closePopupButtons() {
  1076.         this.elements.mfp.classList.remove('mobmenu--active-popup');
  1077.         this.elements.footer.watermark.classList.remove('mobile-list-control--active');
  1078.     }
  1079.  
  1080.     addWatermark(type = "", x = 0, y = 0, angle = 45) {
  1081.         this.closePopupButtons();
  1082.         let obj = false;
  1083.         let canvas = this.getCanvas();
  1084.  
  1085.         switch (type) {
  1086.             case 'text':
  1087.                 let font_size = viewer.pages[mobileEditor.page].height / 10;
  1088.                 if (font_size > 72) font_size = 72;
  1089.  
  1090.                 obj = mobileEditor.addText("Watermark...", true, { subtype: 'text_watermark', is_watermark: true });
  1091.                 obj.is_watermark = true;
  1092.                 obj.setSelectionStyles({ fontSize: font_size }, 0, 999);
  1093.                 obj.fontSize = font_size;
  1094.                 obj.originX = "center";
  1095.                 obj.originY = "center";
  1096.                 obj.angle = angle;
  1097.                 obj.opacity = 0.5;
  1098.                 obj.left = canvas.width / 2;
  1099.                 obj.top = (canvas.height / 2) + (obj.height / 2);
  1100.  
  1101.                 //              obj.setControlsVisibility({
  1102.                 //                  mtr: true
  1103.                 //              });
  1104.  
  1105.  
  1106.                 break;
  1107.             case 'image':
  1108.                 const ts = document.querySelector('.ts');
  1109.                 this.image_is_watermark = true;
  1110.                 ts.click();
  1111.                 break;
  1112.         }
  1113.         canvas.renderAll();
  1114.     }
  1115.  
  1116.     getCanvas() {
  1117.         return viewer.pages[mobileEditor.page].fcanvas;;
  1118.     }
  1119.  
  1120.  
  1121.     disableDraw() {
  1122.         this.draw_enabled = false;
  1123.         this.enableScroll();
  1124.  
  1125.         //let viewed_pages = allViewedPages();
  1126.         let pages = Object.keys(viewer.pages);
  1127.  
  1128.         for (let i = 0; i < pages.length; i++) {
  1129.             let page = pages[i]
  1130.             //viewed_pages.forEach((page)=>{
  1131.             let canvas = viewer.pages[page].fcanvas;
  1132.             if (canvas) {
  1133.                 canvas.isDrawingMode = false;
  1134.                 canvas.discardActiveObject();
  1135.                 canvas.renderAll();
  1136.             }
  1137.         }
  1138.     }
  1139.  
  1140.     enableDraw(data = false) {
  1141.         this.draw_enabled = true;
  1142.         this.disableScroll();
  1143.         const colorElement = document.querySelector('.active-menu-box');
  1144.         const brushelement = document.querySelector('.active-brush');
  1145.  
  1146.         let color = colorElement ? colorElement.dataset.color : '#f03b3d';
  1147.         let brush = brushelement ? brushelement.dataset.type : 'pencil';
  1148.  
  1149.         //this.clearStylesFooter();
  1150.         if (data) {
  1151.             if (data.color) color = data.color;
  1152.             if (data.brush) brush = data.brush;
  1153.         }
  1154.  
  1155.         this.enableDrawingMode({ color, width: brush == 'pencil' ? 5 : 1 });
  1156.     }
  1157.  
  1158.     openImage(key, e) {
  1159.         if (this.images_menu_opened) {
  1160.             this.images_menu_opened = false;
  1161.             this.closeMenu(key);
  1162.             dissableAllImages();
  1163.         } else {
  1164.             this.images_menu_opened = true;
  1165.             this.images_active = true;
  1166.             this.openMenu(key);
  1167.             enableAllImages();
  1168.             //alert("enable images?");
  1169.  
  1170.             //enableAllTexts();
  1171.             this.elements.images.modify_images.classList.add("active");
  1172.         }
  1173.         //toggleTextsMenu
  1174.         //      const ts = document.querySelector('.ts');
  1175.         //      ts.click();
  1176.     }
  1177.  
  1178.     getActiveObject() {
  1179.         let canvas = viewer.pages[mobileEditor.page].fcanvas;
  1180.  
  1181.         return canvas.getActiveObject();
  1182.     }
  1183.  
  1184.     deleteAnnotation() {
  1185.         const active = this.getActiveObject();
  1186.         if (!active) return false;
  1187.  
  1188.         active.annotation = false;
  1189.         this.showModal('annotations', false);
  1190.     }
  1191.  
  1192.     addAnnotation() {
  1193.         const active = this.getActiveObject();
  1194.         if (!active) return false;
  1195.  
  1196.         active.annotation = {
  1197.             title: this.annotationElements.title.value,
  1198.             message: this.annotationElements.message.value
  1199.         };
  1200.  
  1201.         this.showModal('annotations', false);
  1202.     }
  1203.  
  1204.     showModal(k, isShow = false) {
  1205.         if (!k) return;
  1206.  
  1207.         let key = !isShow ? 'remove' : 'add';
  1208.         this.elements.modals[k].classList[key]('modal--show--mobile');
  1209.     }
  1210.  
  1211.     editedCheck() {
  1212.         if (viewer.pages[mobileEditor.page]) {
  1213.             viewer.pages[mobileEditor.page].modified = true;
  1214.         }
  1215.     }
  1216.  
  1217.     openAnnotationsPopup() {
  1218.         const ae = this.getActiveObject();
  1219.         if (!ae) return false;
  1220.  
  1221.         const title = ae && ae.annotation && ae.annotation.title ? ae.annotation.title : '';
  1222.         const message = ae && ae.annotation && ae.annotation.message ? ae.annotation.message : '';
  1223.  
  1224.         this.annotationElements.title.value = title;
  1225.         this.annotationElements.message.value = message;
  1226.         this.showModal('annotations', true);
  1227.     }
  1228.  
  1229.     selectedEventCanvas(event, key) {
  1230.  
  1231.         if (key == 'object:added' && (event.target.subtype == 'image_group' || event.target.subtype == 'image')) {
  1232.             this.addElementBase(event.target);
  1233.         }
  1234.  
  1235.         if (['selection:cleared', 'selection:created', 'selection:updated'].includes(key)) {
  1236.             if (formElements) formElements.selectedUpdate(event);
  1237.         }
  1238.  
  1239.         if (key == 'selection:cleared') return this.renderPosition(false);
  1240.         if (key == 'path:created') return this.addDrawingPath(event.path);
  1241.  
  1242.         if (['object:removed'].includes(key)) {
  1243.             this.editedCheck();
  1244.  
  1245.             return;
  1246.         }
  1247.  
  1248.         this.renderPosition(event.target);
  1249.     }
  1250.  
  1251.     removeObject(target = false) {
  1252.         let canvas = viewer.pages[mobileEditor.page].fcanvas;
  1253.         const dis = () => {
  1254.             canvas.discardActiveObject();
  1255.             canvas.renderAll();
  1256.         };
  1257.  
  1258.         if (!target) target = canvas.getActiveObject();
  1259.         if (!target) return dis();
  1260.         const element = document.querySelector(`[data-element="${target.id}"]`);
  1261.         if (element) { element.remove(); }
  1262.  
  1263.         canvas.remove(target);
  1264.         dis();
  1265.     }
  1266.  
  1267.     enableDrawingMode(options = {}) {
  1268.         let viewed_pages = allViewedPages();
  1269.  
  1270.         viewed_pages.forEach((page) => {
  1271.             let canvas = viewer.pages[page].fcanvas;
  1272.             const brush = new fabric.PencilBrush(canvas);
  1273.  
  1274.             for (const key in options) brush[key] = options[key];
  1275.             canvas.freeDrawingBrush = brush;
  1276.             canvas.isDrawingMode = true;
  1277.         })
  1278.     }
  1279.  
  1280.     addDrawingPath(path) {
  1281.         let canvas = path.canvas || viewer.pages[mobileEditor.page].fcanvas;
  1282.         //canvas.isDrawingMode = false;
  1283.         path.subtype = 'drawing';
  1284.  
  1285.         return this.addElement(path, true, false);
  1286.     }
  1287.  
  1288.     addElementBase(object, isViewer = false, show_buttons = true) {
  1289.  
  1290.         if (!object) return;
  1291.         //evented
  1292.  
  1293.         if (isViewer) {
  1294.             if (!['i-text'].includes(object.type)) return;
  1295.             if (!object.subtype == 'text_watermark')
  1296.                 object.set({ subtype: 'text' });
  1297.         }
  1298.  
  1299.         ['moving', 'scaling', 'rotating', 'resizing']
  1300.             .forEach(ev => object.on(ev, e => this.renderPosition(e.target)));
  1301.  
  1302.         object.set({ _controlsVisibility: { br: true }, borderDashArray: [4, 4] });
  1303.         if (['textbox'].includes(object.type)) {
  1304.             object.set({ _controlsVisibility: { mr: true } });
  1305.         }
  1306.  
  1307.         if (['i-text'].includes(object.type)) {
  1308.  
  1309.             if (object.subtype == 'text_watermark') {
  1310.                 object.customiseCornerIcons({
  1311.                     settings: {
  1312.                         borderColor: '#7b4ef9',
  1313.                         cornerSize: 20,
  1314.                         cornerShape: 'rect',
  1315.                         cornerBackgroundColor: 'rgba(0, 0, 0, 0)',
  1316.                         cornerPadding: 0
  1317.                     },
  1318.                     br: { icon: './assets/img/resize.svg' },
  1319.                     tl: { icon: './assets/img/rotate.svg' },
  1320.                 });
  1321.  
  1322.  
  1323.                 if (object.is_watermark) {
  1324.                     object.centeredRotation = true;
  1325.                     object.set({ _controlsVisibility: { br: true, tl: true } });
  1326.                 } else {
  1327.                     object.set({ _controlsVisibility: { br: true } });
  1328.                 }
  1329.                 object.on('modified', e => {
  1330.                     if (e.by != 'equally') return;
  1331.  
  1332.                     const target = e.target;
  1333.                     const scaleX = target.scaleX;
  1334.                     if (scaleX != 1) {
  1335.                         const fontSize = (target.styles && target.styles[0] && target.styles[0][0]
  1336.                             ? target.styles[0][0].fontSize : target.fontSize) || target.fontSize;
  1337.  
  1338.                         target.setSelectionStyles({ fontSize: fontSize * target.scaleX }, 0, target.text.length);
  1339.                         target.set({ scaleX: 1, scaleY: 1 });
  1340.                         target.canvas.renderAll();
  1341.                     }
  1342.                 });
  1343.             } else {
  1344.                 object.set({ _controlsVisibility: {} });
  1345.             }
  1346.  
  1347.             object.set({
  1348.                 evented: mp.texts_active
  1349.             });
  1350.         }
  1351.         if (object.type == 'image') {
  1352.             object.set({
  1353.                 evented: mp.images_active
  1354.             });
  1355.  
  1356.         }
  1357.  
  1358.  
  1359.         if (object.type == 'image' && object.is_watermark) {
  1360.             object.centeredRotation = true;
  1361.             object.set({ _controlsVisibility: { br: true, tl: true } });
  1362.         }
  1363.  
  1364.         object.customiseCornerIcons({
  1365.             settings: {
  1366.                 borderColor: '#7b4ef9',
  1367.                 cornerSize: 20,
  1368.                 cornerShape: 'rect',
  1369.                 cornerBackgroundColor: 'rgba(0, 0, 0, 0)',
  1370.                 cornerPadding: 0
  1371.             },
  1372.             tl: { icon: './assets/img/rotate.svg' },
  1373.             mr: { icon: './assets/img/resize-rl.svg' },
  1374.             br: { icon: './assets/img/resize.svg' },
  1375.             mb: { icon: './assets/img/resize-bc.svg' },
  1376.         });
  1377.     }
  1378.  
  1379.     addElement(object, lockAdding = false, center = true) {
  1380.         if (!object) return false;
  1381.         let canvas = viewer.pages[mobileEditor.page].fcanvas;
  1382.         let point = { x: (canvas.width / 2) - (62 / 2), y: canvas.height / 4 };
  1383.         object.set(point);
  1384.  
  1385.         if (center) {
  1386.             object.left = (canvas.width / 2) - (object.width * object.scaleX / 2);
  1387.             object.top = (canvas.height / 2) - (object.height * object.scaleY / 2);
  1388.         }
  1389.         //alert("before add");
  1390.  
  1391.         this.addElementBase(object);
  1392.         if (!lockAdding) canvas.add(object);
  1393.         canvas.setActiveObject(object).renderAll();
  1394.  
  1395.         this.renderPosition(object);
  1396.         this.editedCheck();
  1397.     }
  1398.  
  1399.     async addShape(type) {
  1400.         switch (type) {
  1401.             case 'rect':
  1402.                 return this.addElement(new fabric.Rect({
  1403.                     width: 100, height: 100,
  1404.                     stroke: 'red', fill: 'rgba(0, 0, 0, 0)',
  1405.                     strokeWidth: 1, strokeUniform: true,
  1406.                     subtype: 'rectangle'
  1407.                 }));
  1408.  
  1409.             case 'circle': return this.addElement(new fabric.Circle({
  1410.                 radius: 100, stroke: 'red', fill: 'rgba(0, 0, 0, 0)',
  1411.                 strokeWidth: 1, strokeUniform: true,
  1412.                 subtype: 'circle'
  1413.             }));
  1414.  
  1415.             case 'whiteout': return this.addElement(new fabric.Rect({
  1416.                 width: 150, height: 50, fill: '#fff',
  1417.                 strokeWidth: 0, strokeUniform: true,
  1418.                 subtype: 'whiteout'
  1419.             }));
  1420.         }
  1421.     }
  1422.  
  1423.     async addFormItem(type) {
  1424.         let canvas = viewer.pages[mobileEditor.page].fcanvas;
  1425.         let imageURL = false;
  1426.  
  1427.         switch (type) {
  1428.             case 'check_on':
  1429.                 imageURL = '../web/assets/img/check.svg';
  1430.                 break;
  1431.  
  1432.             case 'check_off':
  1433.                 imageURL = '../web/assets/img/x.svg';
  1434.                 break;
  1435.  
  1436.             case 'radio':
  1437.                 imageURL = '../web/assets/img/radio.svg';
  1438.                 break;
  1439.  
  1440.             case 'input':
  1441.                 let el = new fabric.Textbox('Input text', {
  1442.                     subtype: type,
  1443.                     fontSize: 16,
  1444.                     width: 100,
  1445.                     element_type: 'input'
  1446.                 });
  1447.                 el.left = (canvas.width / 2) - (el.width / 2);
  1448.                 el.top = (canvas.height / 2) - (el.height / 2);
  1449.  
  1450.                 return this.addElement(el);
  1451.                 break;
  1452.             case 'textarea':
  1453.                 formElements.addObject(viewer.pages[mobileEditor.page].fcanvas, {});
  1454.                 break;
  1455.  
  1456.             case 'checkbox':
  1457.                 formElements.addObject(viewer.pages[mobileEditor.page].fcanvas, { opts: { element_type: 'checkbox', width: 30, height: 30 } })
  1458.                 break;
  1459.  
  1460.             case 'dropdown':
  1461.                 formElements.addObject(viewer.pages[mobileEditor.page].fcanvas, { opts: { element_type: 'dropdown', height: 30, width: 150 } })
  1462.                 break;
  1463.         }
  1464.  
  1465.         if (!imageURL) return false;
  1466.         const img = await new Promise((resolve, reject) => {
  1467.             fabric.Image.fromURL(imageURL, (img, err) => {
  1468.                 if (err) return reject(err);
  1469.  
  1470.                 resolve(img);
  1471.             })
  1472.         });
  1473.  
  1474.         const scale = Math.min(50 / img.width, 50 / img.height);
  1475.         img.set({ scaleX: scale, scaleY: scale });
  1476.         img.subtype = type;
  1477.  
  1478.         if (type == 'radio') img.set({
  1479.             field_name: 'New field 2',
  1480.             element_type: 'radio',
  1481.             subtype: 'radio'
  1482.         });
  1483.  
  1484.  
  1485.         img.left = (canvas.width / 2) - (img.width / 2);
  1486.         img.top = (canvas.height / 2) - (img.height / 2);
  1487.  
  1488.         return this.addElement(img);
  1489.     }
  1490.  
  1491.  
  1492.     hideControlls() {
  1493.         const controls = document.querySelector('.controlls_q');
  1494.         controls.classList.add('hidden_q');
  1495.     }
  1496.  
  1497.     async renderPosition(target = false) {
  1498.         if (target && (target.canvas && target.canvas.skip_render)) {
  1499.             return false;
  1500.         }
  1501.  
  1502.         let canvas = target ? target.canvas : false;
  1503.         if (!canvas) canvas = viewer.pages[mobileEditor.page].fcanvas;
  1504.         const controls = document.querySelector('.controlls_q');
  1505.         if (!target || !target.canvas) {
  1506.             return controls.classList.add('hidden_q');
  1507.         }
  1508.  
  1509.         const tools = this.elements.tools;
  1510.         for (const key in tools) {
  1511.             tools[key].parentElement.classList.add('hidden_q_b');
  1512.         }
  1513.  
  1514.         const show = arr => {
  1515.             arr.forEach(key => tools[key].parentElement.classList.remove('hidden_q_b'));
  1516.             if (arr && arr.length) controls.classList.remove('hidden_q');
  1517.         };
  1518.  
  1519.         canvas.uniScaleTransform = ['whiteout', 'rectangle'].includes(target.subtype || '');
  1520.         console.log("target.subtype", target.subtype);
  1521.         if (target.subtype) {
  1522.             switch (target.subtype) {
  1523.                 case 'circle':
  1524.                 case 'rectangle':
  1525.                     show(['delete', 'annotations', 'setting']);
  1526.                     break;
  1527.  
  1528.                 case 'input':
  1529.                 case 'text':
  1530.                 case 'text_watermark':
  1531.                     if (target.is_watermark) {
  1532.                         show(['textEdit', 'text', 'delete']);
  1533.                     } else {
  1534.                         show(['textEdit', 'text', 'delete', 'annotations']);
  1535.                     }
  1536.                     break;
  1537.                 case 'drawing':
  1538.                     show(['delete', 'annotations'])
  1539.                     break;
  1540.  
  1541.                 case 'form_element_outer':
  1542.                     if (target.element_type == 'dropdown') {
  1543.                         show(['delete', 'annotations', 'setting_dropdown']);
  1544.                     } else {
  1545.                         show(['delete', 'annotations']);
  1546.                     }
  1547.  
  1548.                     break;
  1549.  
  1550.                 case 'image':
  1551.                 case 'image_group':
  1552.                     if (target.is_watermark) {
  1553.                         show(['watermark', 'delete', 'annotations', 'deselect_dropdown']);
  1554.                     } else {
  1555.                         show(['delete', 'annotations', 'deselect_dropdown']);
  1556.                     }
  1557.  
  1558.                     break;
  1559.  
  1560.                 case 'radio':
  1561.                 case 'check_on':
  1562.                 case 'check_off':
  1563.                 case 'whiteout':
  1564.                     show(['delete', 'annotations'])
  1565.                     break;
  1566.                 default:
  1567.                     console.log("default?");
  1568.  
  1569.                     break;
  1570.             }
  1571.         } else if (canvas.getActiveObject()) {
  1572.             switch (target.type) {
  1573.                 case 'i-text':
  1574.                 case 'textbox':
  1575.                     if (target.is_watermark) {
  1576.                         show(['textEdit', 'text', 'delete']);
  1577.                     } else {
  1578.                         show(['textEdit', 'text', 'delete', 'annotations']);
  1579.                     }
  1580.                     break;
  1581.             }
  1582.         }
  1583.  
  1584.  
  1585.  
  1586.         //      let bounds = canvas.upperCanvasEl.getBoundingClientRect();
  1587.         //      let css_scale_top =  bounds.height/$(canvas.upperCanvasEl).height();
  1588.         //      let viewport_scale = window.visualViewport.scale;
  1589.  
  1590.         //      console.log("scales is ", css_scale_top, viewport_scale);
  1591.         //      const sx = 0;//window.scrollX;
  1592.         //      const sy = 0;//window.scrollY;
  1593.  
  1594.         //      let target_width = target.width;
  1595.         //      if (target.originX == 'center') {
  1596.         //          console.log("origin center?");
  1597.         //          const sx = window.scrollX;
  1598.         //          const sy = window.scrollY;
  1599.         //          let left = target.left - sx,
  1600.         //              top = target.top - controls.clientHeight - 3 - sy;
  1601.  
  1602.         //          if (left < 0) { left = 0; }
  1603.         //          if (top < 0) { top = 0; }
  1604.  
  1605.         //          controls.style = `display: flex;left: ${left}px;top:${top}px;`;
  1606.         //      } else {
  1607.  
  1608.         //          let left = target.left - sx + (target.width * target.scaleX / 2),
  1609.         //              top = ((target.top) + (bounds.top) - controls.clientHeight - 3 - sy);
  1610.  
  1611.         // //           console.log("====debug:====");
  1612.         // //           console.log("target.top", target.top);
  1613.         // //           console.log("bounds.top", bounds.top);
  1614.         // //           console.log("controls.clientHeight", controls.clientHeight);
  1615.         // //           console.log("window.scrollY", window.scrollY);
  1616.  
  1617.         //          let buttons_size = document.querySelector(".control-widget-el-actions").getBoundingClientRect();
  1618.  
  1619.         //          if (left - (buttons_size.width / 2) < 0) {
  1620.         //              left = left - (left - (buttons_size.width / 2));
  1621.         //          }
  1622.         //          if (left + (buttons_size.width / 2) > target.canvas.width) {
  1623.         //              left = left + (target.canvas.width - (left + buttons_size.width / 2)); //(left-(buttons_size.width/2));
  1624.         //          }
  1625.  
  1626.         //          top = top+window.visualViewport.offsetTop;
  1627.  
  1628.  
  1629.         //          controls.style = `display: flex;left: ${left}px;top:${top}px;`;
  1630.         //      }
  1631.  
  1632.         let bounds = canvas.upperCanvasEl.getBoundingClientRect();
  1633.         let css_scale_top = bounds.height / $(canvas.upperCanvasEl).height();
  1634.         let viewport_scale = window.visualViewport.scale;
  1635.  
  1636.         //console.log("scales is ", css_scale_top, viewport_scale);
  1637.         const sx = 0;//window.scrollX;
  1638.         const sy = 0;//window.scrollY;
  1639.  
  1640.         let target_width = target.width;
  1641.  
  1642.         const fixPositons = (left, top, el) => {
  1643.             if (left < 0) left = 0;
  1644.             if (top < 100) top = 50;
  1645.  
  1646.             return { left, top };
  1647.         };
  1648.  
  1649.         if (target.originX == 'center') {
  1650.             const sx = window.scrollX;
  1651.             const sy = window.scrollY;
  1652.             let left = target.left - sx,
  1653.                 top = target.top - controls.clientHeight - 3 - sy;
  1654.  
  1655.             const fix = fixPositons(left, top, controls);
  1656.             controls.style = `display: flex;left: ${fix.left}px;top:${fix.top}px;`;
  1657.         } else {
  1658.             let left = target.left - sx + (target.width * target.scaleX / 2),
  1659.                 top = ((target.top) + (bounds.top) - controls.clientHeight - 3 - sy);
  1660.  
  1661.             //          console.log("====debug:====");
  1662.             //          console.log("target.top", target.top);
  1663.             //          console.log("bounds.top", bounds.top);
  1664.             //          console.log("controls.clientHeight", controls.clientHeight);
  1665.             //          console.log("window.scrollY", window.scrollY);
  1666.  
  1667.             let buttons_size = document.querySelector(".control-widget-el-actions").getBoundingClientRect();
  1668.  
  1669.             if (left - (buttons_size.width / 2) < 0) {
  1670.                 left = left - (left - (buttons_size.width / 2));
  1671.             }
  1672.             if (left + (buttons_size.width / 2) > target.canvas.width) {
  1673.                 left = left + (target.canvas.width - (left + buttons_size.width / 2)); //(left-(buttons_size.width/2));
  1674.             }
  1675.  
  1676.             // top = top + window.visualViewport.offsetTop;
  1677.             // left += visualViewport.offsetLeft;
  1678.  
  1679.             const fix = fixPositons(left, top, controls);
  1680.             controls.style = `display: flex;left: ${fix.left}px;top:${fix.top}px;`;
  1681.         }
  1682.     }
  1683.  
  1684.     createColorPicker(elementBody, key = false, callback = () => { }) { // fontColor
  1685.         if (typeof elementBody == 'string') elementBody = document.querySelector(elementBody);
  1686.         const picker = new EasyLogicColorPicker({
  1687.             outputFormat: 'hex',
  1688.             container: elementBody,
  1689.             onChange: _.debounce(function (color) {
  1690.                 if (window._lockColorChanges) {
  1691.                     window._lockColorChanges = false;
  1692.  
  1693.                     return;
  1694.                 }
  1695.  
  1696.                 const parent = elementBody.parentElement;
  1697.                 parent.querySelector('.info-color').innerHTML = color;
  1698.                 parent.querySelector('.pick-ico-color').style.background = color;
  1699.  
  1700.                 callback(color);
  1701.                 // TextEditor.changeFontColor_(color);
  1702.             }, 30),
  1703.  
  1704.             onInit: function (element) {
  1705.                 let close_generate = document.createElement("a");
  1706.                 close_generate.setAttribute("class", "close-color");
  1707.                 close_generate.setAttribute("href", "#")
  1708.                 close_generate.innerHTML = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  1709.                     <path d="M6 6L18 18" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
  1710.                     <path d="M18 6L6 18" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
  1711.                 </svg>`;
  1712.                 let el_find = element.$el.el;
  1713.                 if (el_find) {
  1714.                     el_find.appendChild(close_generate);
  1715.                     let close_btn_find = el_find.querySelector(".close-color");
  1716.                     close_btn_find.addEventListener("click", (ev) => {
  1717.                         ev.preventDefault();
  1718.                         ev.stopPropagation();
  1719.                         let parent_dropdown = elementBody.closest("[data-dropdown--mob]");
  1720.                         parent_dropdown.classList.toggle("active-drp");
  1721.                     })
  1722.                 }
  1723.  
  1724.             }
  1725.         });
  1726.  
  1727.         if (key) this.colorPicker[key] = picker;
  1728.     }
  1729.  
  1730.     createRange(slider = '', input = '', key = false, options = {}, callback = () => { }) {
  1731.         try {
  1732.             const range = $(document.querySelector(slider)).ionRangeSlider({
  1733.                 min: 0, max: 10, from: 0,
  1734.                 ...options,
  1735.                 onChange: data => {
  1736.  
  1737.                     $(input).val(data.from);
  1738.                     callback(data.from);
  1739.                 },
  1740.                 onUpdate: data => $(input).val(data.from)
  1741.             }).data('ionRangeSlider');
  1742.  
  1743.             if (key) this.rangesElements[key] = range;
  1744.         } catch (err) {
  1745.             console.error(err);
  1746.         }
  1747.     }
  1748.  
  1749.     setStylesForShapes(styles = {}) {
  1750.         const active = this.getActiveObject();
  1751.  
  1752.         if (active) {
  1753.             active.set(styles);
  1754.             active.canvas.renderAll();
  1755.         }
  1756.     }
  1757.  
  1758.     initRangesElements() {
  1759.         Array.from(document.querySelectorAll('[data-type="close_modal"]')).forEach(el => {
  1760.             el.addEventListener('click', e => {
  1761.                 e.target.closest('.modal--mobile').classList.remove('modal--show--mobile');
  1762.             });
  1763.         });
  1764.  
  1765.         this.createRange('[name="border_shape"]', '[name="border_shape_input"]', 'borderShape', {
  1766.             min: 0, max: 10, step: 1, from: 0
  1767.         }, from => this.setStylesForShapes({ strokeWidth: from }));
  1768.  
  1769.         this.createRange('[name="range_font_size"]', '[name="input_font_size"]', 'fontSize', {
  1770.             min: 6, max: 72, step: 1, from: 0
  1771.         }, from => {
  1772.             TextEditor.changeFontSize_(from);
  1773.         });
  1774.  
  1775.         this.createRange('[name="range_opacity"]', '[name="input_opacity"]', 'opacity', {
  1776.             min: 0.01, max: 1, step: 0.05, from: 0
  1777.         }, from => {
  1778.             TextEditor.changeOpacity_(from);
  1779.         });
  1780.  
  1781.         this.createRange('[name="range_opacity_watermark"]', '[name="input_opacity_watermark"]', 'opacity_watermark', {
  1782.             min: 0.01, max: 1, step: 0.05, from: 0
  1783.         }, from => {
  1784.             TextEditor.changeOpacity_(from);
  1785.         });
  1786.  
  1787.         this.createRange('[name="range_rotate_watermark"]', '[name="input_rotate_watermark"]', 'angle_watermark', {
  1788.             min: -360, max: 360, step: 1, from: 0
  1789.         }, from => {
  1790.             TextEditor.changeRotate_(from);
  1791.         });
  1792.  
  1793.         this.createRange('[name="range_rotate"]', '[name="input_rotate"]', 'angle', {
  1794.             min: -360, max: 360, step: 1, from: 0
  1795.         }, from => {
  1796.             TextEditor.changeRotate_(from);
  1797.         });
  1798.  
  1799.         this.createColorPicker('[data-type="text_color_picker"]', 'fontColor', color => TextEditor.changeFontColor_(color));
  1800.         this.createColorPicker('[data-type="border_color_shape"]', 'borderColorShape', color => {
  1801.             this.setStylesForShapes({ stroke: color });
  1802.         });
  1803.  
  1804.         this.createColorPicker('[data-type="fill_shape_color"]', 'fillShapeColor', color => {
  1805.             this.setStylesForShapes({ fill: color });
  1806.         });
  1807.     }
  1808.  
  1809.     getCoords(obj) {
  1810.         const coords = obj.getCoords();
  1811.         const left = Math.min(...coords.map(c => c.x));
  1812.         const top = Math.min(...coords.map(c => c.y));
  1813.         const right = Math.max(...coords.map(c => c.x));
  1814.         const bottom = Math.max(...coords.map(c => c.y));
  1815.  
  1816.         return { left, top, right, bottom, width: right - left, height: bottom - top };
  1817.     }
  1818. };
  1819.  
  1820. window.mp = mp;
  1821. let mob_btn_drop = $("[data-dropdown--mob]");
  1822. $.each(mob_btn_drop, function (index, element) {
  1823.     let el = $(element);
  1824.     el.on("click", function (event) {
  1825.         event.preventDefault();
  1826.         let closest_drop_mob = el.closest("[data-dropdown--mob]");
  1827.         closest_drop_mob.addClass("active-drp");
  1828.     });
  1829. });
  1830.  
  1831. $(document).on("click", function (event) {
  1832.     if (!event.target.closest("[data-dropdown--mob]")) {
  1833.         mob_btn_drop.removeClass("active-drp");
  1834.     }
  1835. });
  1836.  
  1837. if (false) {
  1838.     window.lockerScroll = amoutTouch => {
  1839.         console.log('amoutTouch', amoutTouch);
  1840.         viewer.pages[mobileEditor.page].fcanvas.allowTouchScrolling = amoutTouch > 1;
  1841.         document.querySelector('#pdf_editor_pages').style['touch-action'] = amoutTouch > 1 ? 'auto' : 'none';
  1842.     };
  1843.  
  1844.     document.addEventListener('touchstart', e => lockerScroll(e.touches.length));
  1845.     document.addEventListener('touchend', e => lockerScroll(e.touches.length));
  1846. }
  1847.  
  1848. document.querySelector(".page-counter").addEventListener("click", function (e) {
  1849.     e.preventDefault();
  1850.  
  1851.     let input = document.querySelector(".page_input");
  1852.  
  1853.     input.setAttribute("max", mobileEditor.total_pages);
  1854.     input.value = mobileEditor.page;
  1855.     input.classList.remove("hidden");
  1856.     document.querySelector(".page-counter").classList.add("hidden");
  1857.     input.focus();
  1858.     input.select();
  1859. });
  1860.  
  1861. document.querySelector(".page_input").addEventListener("input", debounce(function (e) {
  1862.     e.preventDefault();
  1863.  
  1864.     if (this.value > mobileEditor.total_pages) {
  1865.         this.value = mobileEditor.total_pages;
  1866.     }
  1867.  
  1868.     if (this.value < 1) {
  1869.         this.value = 1;
  1870.     }
  1871.  
  1872.     mobileEditor.selectPage(this.value);
  1873.     // mobileInit(parseInt(this.value), true);
  1874. }, 1000));
  1875.  
  1876. document.querySelector(".page_input").addEventListener("focusout", function () {
  1877.     document.querySelector(".page_input").classList.add("hidden");
  1878.     document.querySelector(".page-counter").classList.remove("hidden");
  1879.  
  1880. });
  1881.  
  1882. //mobileInit(mobileEditor.page + 1, true);
  1883.  
  1884.  
  1885. const ts = document.querySelector('.ts');
  1886. ts.addEventListener('change', async e => {
  1887.     const file = e.target.files[0];
  1888.     if (file) {
  1889.         const imageURL = URL.createObjectURL(file);
  1890.         const image = await new Promise((resolve, reject) => {
  1891.             fabric.Image.fromURL(imageURL, (image, err) => {
  1892.                 if (err) return reject(err);
  1893.                 resolve(image);
  1894.             });
  1895.         });
  1896.  
  1897.         image.subtype = 'image';
  1898.         let canvas = viewer.pages[mobileEditor.page].fcanvas;
  1899.         const minSize = Math.min(canvas.width * .3, canvas.height * .3);
  1900.         const scale = Math.min(minSize / image.width, minSize / image.height);
  1901.         image.set({ scaleX: scale, scaleY: scale });
  1902.  
  1903.         e.target.value = '';
  1904.         if (mp.image_is_watermark) {
  1905.             image.is_watermark = true;
  1906.             image.opacity = 0.5;
  1907.             mp.image_is_watermark = false;
  1908.         }
  1909.  
  1910.         //mp.addElement(image, false, image.is_watermark ? true : false);
  1911.         mp.addElement(image, false, true);
  1912.  
  1913.     }
  1914. });
  1915.  
  1916. function debounce(func, wait, immediate) {
  1917.     var timeout;
  1918.     return function () {
  1919.         var context = this, args = arguments;
  1920.         var later = function () {
  1921.             timeout = null;
  1922.             if (!immediate) func.apply(context, args);
  1923.         };
  1924.         var callNow = immediate && !timeout;
  1925.         clearTimeout(timeout);
  1926.         timeout = setTimeout(later, wait);
  1927.         if (callNow) func.apply(context, args);
  1928.     };
  1929. };
  1930.  
  1931. $(document).on("after_page_render", function (e, page) {
  1932.     viewer.pending_pages = [];
  1933.  
  1934.     let prev_page = page - 1,
  1935.         next_page = page + 1;
  1936.  
  1937.     if (prev_page > 0 && viewer.rendered_pages_array.indexOf(prev_page) == -1) {
  1938.         viewer.pending_pages.push(prev_page);
  1939.     }
  1940.     if (next_page <= viewer.total_pages && viewer.rendered_pages_array.indexOf(next_page) == -1) {
  1941.         viewer.pending_pages.push(next_page);
  1942.     }
  1943. });
  1944.  
  1945.  
  1946. setInterval(function () {
  1947.     viewer.pending_pages = viewer.pending_pages.filter(function (p) {
  1948.         return elementInViewport(document.querySelector(`#page_outer_${p}`));
  1949.     });
  1950.     if (!viewer.now_render && viewer.pending_pages.length) {
  1951.         viewer.renderSinglePage(viewer.pending_pages.pop());
  1952.     }
  1953. }, 1000);
  1954.  
  1955.  
  1956.  
  1957.  
  1958. function allViewedPages() {
  1959.     let pages = Object.values(document.querySelectorAll(".m_page_outer"));
  1960.     let ret = [];
  1961.     for (let i = 0; i < pages.length; i++) {
  1962.         let el = pages[i];
  1963.         if (elementInViewport(el)) {
  1964.             ret.push(parseInt(el.dataset.pageId));
  1965.         }
  1966.     }
  1967.     return ret;
  1968. }
  1969.  
  1970.  
  1971.  
  1972. function firstViewedPage() {
  1973.     let pages = Object.values(document.querySelectorAll(".m_page_outer"));
  1974.     for (let i = 0; i < pages.length; i++) {
  1975.         let el = pages[i];
  1976.         if (elementInViewport(el)) {
  1977.             return parseInt(el.dataset.pageId);
  1978.             break;
  1979.         }
  1980.     }
  1981.     return 1;
  1982. }
  1983.  
  1984.  
  1985.  
  1986.  
  1987.  
  1988.  
  1989.  
  1990.  
  1991. function preventScroll(e) {
  1992.     e.preventDefault();
  1993.     e.stopPropagation();
  1994.     return false;
  1995. }
  1996.  
  1997. let allow_fabric = false,
  1998.     fabric_has_active_element = false,
  1999.     touched_canvas = false;
  2000.  
  2001. let scrolled = false;
  2002. let touch_up = true;
  2003. let allow_fabric_move = false;
  2004.  
  2005.  
  2006. if (true) {
  2007.     container[0].addEventListener("scroll", async function (e) {
  2008.         scrolled = true;
  2009.         mp.hideControlls();
  2010.         if (viewer.pages[mp.last_touched_page] && viewer.pages[mp.last_touched_page].fcanvas) {
  2011.             if (viewer.pages[mp.last_touched_page].fcanvas._activeObject) {
  2012.                 viewer.pages[mp.last_touched_page].fcanvas.discardActiveObject();
  2013.                 viewer.pages[mp.last_touched_page].fcanvas.renderAll();
  2014.             }
  2015.             viewer.pages[mp.last_touched_page].fcanvas._prev_target = null;
  2016.         }
  2017.  
  2018.     });
  2019.  
  2020.     container[0].addEventListener("touchstart", async function (e) {
  2021.         touch_up = false;
  2022.         mp.last_touched_page = $(e.target).closest(".m_page_outer").data("page-id");
  2023.     }, { passive: false })
  2024.  
  2025.     container[0].addEventListener("touchmove", function (e) {
  2026.         scrolled = true;
  2027.     }, { passive: false })
  2028.  
  2029.     container[0].addEventListener("touchend", function (e) {
  2030.         if (!mp.draw_enabled) {
  2031.             scrolled = false;
  2032.             touch_up = true;
  2033.  
  2034.             setTimeout(() => {
  2035.                 if (!mp.texts_active) {
  2036.                     mp.enableScroll();
  2037.                 }
  2038.             }, 200);
  2039.         }
  2040.  
  2041.     }, { passive: false });
  2042.  
  2043. }
  2044.  
  2045. container.on('scroll', () => {
  2046.     document.querySelector(".scroll_current_page").innerHTML = firstViewedPage();
  2047. });
  2048.  
  2049. container.on('scroll', debounce(() => {
  2050.     if (viewer.loadingTask) {
  2051.         viewer.pending_pages = [];
  2052.         document.querySelectorAll(".m_page_outer:not(.canvas_ready)").forEach(function (el) {
  2053.             if (elementInViewport(el)) {
  2054.                 viewer.renderSinglePage(parseInt(el.dataset.pageId));
  2055.             }
  2056.         });
  2057.  
  2058.         console.log("selected page?", firstViewedPage());
  2059.         mobileEditor.selectPage(parseInt(firstViewedPage()), false)
  2060.     }
  2061.  
  2062.     if (viewer.pages[viewer.current_page] && viewer.pages[viewer.current_page].fcanvas) {
  2063.         try {
  2064.             const active = viewer.pages[viewer.current_page].fcanvas.getActiveObject();
  2065.             mp.renderPosition(active);
  2066.         } catch (e) {
  2067.             console.warn(e);
  2068.         }
  2069.     }
  2070. }, 100));
  2071.  
  2072.  
  2073. function elementInViewport(myElement) {
  2074.     //var myElement = document.getElementById('my-element')
  2075.     var bounding = myElement.getBoundingClientRect();
  2076.     var myElementHeight = myElement.offsetHeight;
  2077.     var myElementWidth = myElement.offsetWidth;
  2078.     var bounding = myElement.getBoundingClientRect();
  2079.  
  2080.     if (bounding.top >= -myElementHeight
  2081.         && bounding.left >= -myElementWidth
  2082.         && bounding.right <= (window.innerWidth || document.documentElement.clientWidth) + myElementWidth
  2083.         && bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) + myElementHeight) {
  2084.  
  2085.         return true;
  2086.     } else {
  2087.         return false;
  2088.     }
  2089. }
  2090.  
  2091. function sendTouchEvent(x, y, element, eventType) {
  2092.     const touchObj = new Touch({
  2093.         identifier: Date.now(),
  2094.         target: element,
  2095.         clientX: x,
  2096.         clientY: y,
  2097.         radiusX: 2.5,
  2098.         radiusY: 2.5,
  2099.         rotationAngle: 10,
  2100.         force: 0.5,
  2101.     });
  2102.  
  2103.     const touchEvent = new TouchEvent(eventType, {
  2104.         cancelable: true,
  2105.         bubbles: false,
  2106.         touches: [touchObj],
  2107.         targetTouches: [],
  2108.         changedTouches: [touchObj],
  2109.         shiftKey: true,
  2110.     });
  2111.  
  2112.     element.dispatchEvent(touchEvent);
  2113. }
Add Comment
Please, Sign In to add comment