var htmlEditorMergedFields; var htmlEditorMergedLinks; var unlayerEditorUploadedFiles; var unlayerEditorElementInitialized; window.addEventListener('message', event => { if (!unlayerEditorElementInitialized) { unlayerEditorElementInitialized = []; } if (!unlayerEditorElementInitialized.includes(event.data.elementId)) { unlayerEditorElementInitialized.push(event.data.elementId); if (event.data.type === 'callFunction') { if (window.blazorHelper) { window.blazorHelper.invokeMethodAsync(event.data.data, event.data.elementId) .catch(error => console.error(error)); } } } }); var AgoraShared = { CheckDevice: { isSafari: function (elementId) { return /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent); }, isApple: function (elementId, content) { return /Mac|iPod|iPhone|iPad/.test(navigator.platform); } }, TimePicker: { FocusElement: function (elementId) { if ($('#' + elementId)) { $('#' + elementId).focus(); } }, SetContent: function (elementId, content) { if ($('#' + elementId)) { $('#' + elementId).html(content); } } }, RichTextEditor: { params: { standard: { plugins: 'code codesample link image autolink lists media paste table table textcolor', toolbar1: 'undo redo | paste | removeformat styleselect | fontselect | fontsizeselect bold italic underline | btnMergedFields btnMergedLinks | forecolor backcolor | alignleft aligncenter alignright alignjustify | outdent indent | link image media codesample | table | code ', menubar: false, branding: false, skin: 'oxide-blue', toolbar_mode: 'floating', custom_elements: "style", resize: 'both', image_title: true, automatic_uploads: true, file_picker_types: 'file image media', file_picker_callback: (cb, value, meta) => filePicker(cb, value, meta), content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }', relative_urls: false, convert_urls: false, remove_script_host: false, image_class_list: [ { title: 'Responsive', value: 'img-fluid' }, { title: 'None', value: ' ' } ] }, textOnly: { plugins: 'code codesample link autolink lists paste textcolor', toolbar1: 'undo redo | paste | removeformat | fontsizeselect bold italic underline | forecolor backcolor | alignleft aligncenter alignright alignjustify | outdent indent | link | code ', menubar: false, branding: false, skin: 'oxide-blue', toolbar_mode: 'floating', resize: 'both', image_title: true, automatic_uploads: true, file_picker_types: 'file image media', file_picker_callback: (cb, value, meta) => filePicker(cb, value, meta), forced_root_block: '', content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }', relative_urls: false, convert_urls: false, remove_script_host: false }, minimal: { toolbar1: 'bold italic underline textcolor', menubar: false, branding: false, skin: 'oxide-blue', toolbar_mode: 'floating', resize: 'both', image_title: true, automatic_uploads: true, file_picker_types: 'file image media', file_picker_callback: (cb, value, meta) => filePicker(cb, value, meta), content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }', relative_urls: false, convert_urls: false, remove_script_host: false }, grouped: { plugins: "emoticons hr image link lists charmap table textcolor", toolbar: "formatgroup paragraphgroup insertgroup", toolbar_groups: { formatgroup: { icon: 'format', tooltip: 'Formatting', items: 'fontselect | fontsizeselect bold italic underline | forecolor backcolor | superscript subscript | removeformat' }, paragraphgroup: { icon: 'paragraph', tooltip: 'Paragraph format', items: 'h1 h2 h3 | bullist numlist | alignleft aligncenter alignright alignjustify | indent outdent' }, insertgroup: { icon: 'plus', tooltip: 'Insert', items: 'link image emoticons charmap hr' } }, skin: 'oxide-blue', menubar: false, branding: false, resize: 'both', image_title: true, automatic_uploads: true, file_picker_types: 'file image media', file_picker_callback: (cb, value, meta) => filePicker(cb, value, meta), content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }', relative_urls: false, convert_urls: false, remove_script_host: false, image_class_list: [ { title: 'Responsive', value: 'img-fluid' }, { title: 'None', value: ' ' } ] }, bloated: { plugins: 'code codesample link image autolink lists media paste table table emoticons textcolor', toolbar1: 'undo redo | styleselect | fontselect | fontsizeselect bold italic underline | forecolor backcolor | link image media codesample | table | code', toolbar2: 'h1 h2 h3 | bullist numlist | alignleft aligncenter alignright alignjustify | outdent indent | emoticons charmap hr', menubar: false, branding: false, skin: 'oxide-blue', toolbar_mode: 'floating', resize: 'both', image_title: true, automatic_uploads: true, file_picker_types: 'file image media', file_picker_callback: (cb, value, meta) => filePicker(cb, value, meta), content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }', relative_urls: false, convert_urls: false, remove_script_host: false, image_class_list: [ { title: 'Responsive', value: 'img-fluid' }, { title: 'None', value: ' ' } ] }, mail: { plugins: 'code codesample link image autolink lists media paste table table textcolor', toolbar1: 'undo redo | paste | removeformat styleselect | fontselect | fontsizeselect bold italic underline | forecolor backcolor | alignleft aligncenter alignright alignjustify | outdent indent | link image media codesample | table | code ', menubar: false, branding: false, skin: 'oxide-blue', toolbar_mode: 'floating', resize: 'both', image_title: true, automatic_uploads: true, file_picker_types: 'file image media', file_picker_callback: (cb, value, meta) => filePicker(cb, value, meta), content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }', relative_urls: false, convert_urls: false, remove_script_host: false, } }, init: function (idTiny, mode, required, paragraph, language, readonly, rows, dotnetHelper, mergedFields, mergedLinks) { try { var options = AgoraShared.RichTextEditor.params[mode]; options.language = language; options.force_p_newlines = paragraph; options.force_br_newlines = true; options.forced_root_block = ''; options.height = rows + 'rem'; options.min_height = rows + 'rem'; if (readonly === 1) { options.readonly = 1; } options.selector = '#' + idTiny; var content = $('#' + idTiny).val(); if (required) { if (content == '' || content == null || content == undefined) { $('#' + 'val-' + idTiny).css('display', 'block'); $('#' + idTiny).next('.tox').css('border', '1px solid #dc3545'); } } if (mergedFields) { htmlEditorMergedLinks = JSON.parse(mergedFields); } if (mergedLinks) { htmlEditorMergedFields = JSON.parse(mergedLinks); } options.setup = function (editor) { if (htmlEditorMergedFields) { console.log('RichTextEditor.setup.addSplitButton'); editor.ui.registry.addSplitButton('btnMergedFields', { text: 'Champs de fusion', icon: 'template', tooltip: 'Ajouter un champs de fusion', onAction: function () { }, onItemAction: function (api, value) { editor.insertContent(value); }, fetch: function (callback) { console.log('RichTextEditor.setup.fetch'); var items = htmlEditorMergedFields.map(function (item) { console.log('RichTextEditor.setup.fetch', item); return { type: 'choiceitem', value: `${item.Item1}`, text: `${item.Item2}`, }; }); callback(items); } }); } if (htmlEditorMergedLinks) { console.log('RichTextEditor.setup.htmlEditorMergedLinks', htmlEditorMergedLinks); editor.ui.registry.addSplitButton('btnMergedLinks', { text: 'Lien de fusion', icon: 'template', tooltip: 'Ajouter un lien de fusion', onAction: function () { }, onItemAction: function (api, value) { editor.insertContent(value); }, fetch: function (callback) { var items = htmlEditorMergedLinks.map(function (item) { return { type: 'choiceitem', value: item.Item1, text: item.Item2, }; }); callback(items); } }); } editor.on('change', function (e) { editor.save(); if (required) { $('#' + idTiny).val(editor.getContent()); if (editor.getContent() == '') { $('#' + 'val-' + idTiny).css('display', 'block'); $('#' + idTiny).next('.tox').css('border', '1px solid #dc3545'); } else { $('#' + 'val-' + idTiny).css('display', 'none'); $('#' + idTiny).next('.tox').css('border', '1px solid #ccc'); } } $('#' + idTiny).change(); dotnetHelper.invokeMethodAsync("textArea_OnChange", $('#' + idTiny).val()); }); } console.log('tinymce:options', options); tinymce.init(options); } catch (error) { console.log('tinymce:error', error); } }, dispose: function (idTiny, dotnetHelper) { console.log('tinymce:dispose', idTiny, dotnetHelper); tinymce.remove('#' + idTiny); }, insertText: function (idTiny, str) { console.log('tinymce:insertText', idTiny, str); $('#' + idTiny).change(); tinymce.get(idTiny).execCommand('mceInsertContent', false, str); }, changeContent: function (idTiny, str) { console.log('tinymce:changeContent', idTiny, str); $('#' + idTiny).change(); if (tinymce.get(idTiny) != null) { tinymce.get(idTiny).setContent(str, { format: 'html' }); } }, getContent: function (idTiny) { console.log('tinymce:getContent'); return tinymce.get(idTiny).getContent(); } }, InfiniteScroll: { Observer: null, Initialize: function (component, observerTargetId) { AgoraShared.InfiniteScroll.Observer = new IntersectionObserver(e => { // run callback only if intersecting end of scroll area if (e && e[0].isIntersecting) { component.invokeMethodAsync('OnIntersection'); } }, { rootMargin: '0px', threshold: 0.5 }); let element = document.getElementById(observerTargetId); if (element == null) throw new Error("The observable target was not found"); AgoraShared.InfiniteScroll.Observer.observe(element); } }, Timer: { ActiveTimers: {}, Start: function (time, id) { // Credit: Mateusz Rybczonec const FULL_DASH_ARRAY = 288; const WARNING_THRESHOLD = 10; const ALERT_THRESHOLD = 5; const COLOR_CODES = { info: { color: "green" }, warning: { color: "orange", threshold: WARNING_THRESHOLD }, alert: { color: "red", threshold: ALERT_THRESHOLD } }; const TIME_LIMIT = time; let timePassed = 0; let timeLeft = TIME_LIMIT; let timerInterval = null; let remainingPathColor = COLOR_CODES.info.color; document.getElementById(id).innerHTML = `
${AgoraShared.Timer.formatTime( timeLeft )}
`; AgoraShared.Timer.startTimer(timePassed, TIME_LIMIT, timeLeft, COLOR_CODES, timerInterval, FULL_DASH_ARRAY, id); }, onTimesUp: function (id) { console.log('AgoraShared.Timer:onTimesUp', id); if (id in AgoraShared.Timer.ActiveTimers) { console.log('AgoraShared.Timer:onTimesUp.clearInterval', id); clearInterval(AgoraShared.Timer.ActiveTimers[id]); AgoraShared.Timer.ActiveTimers[id] = null; } }, Dispose: function (id) { console.log('AgoraShared.Timer:Dispose', id); AgoraShared.Timer.onTimesUp(id); if ($('#' + id).length) { $('#' + id).empty(); } }, startTimer: function (timePassed, TIME_LIMIT, timeLeft, COLOR_CODES, timerInterval, FULL_DASH_ARRAY, id) { timerInterval = setInterval(() => { timePassed = timePassed += 1; timeLeft = TIME_LIMIT - timePassed; document.getElementById("base-timer-label").innerHTML = AgoraShared.Timer.formatTime( timeLeft ); AgoraShared.Timer.setCircleDasharray(timeLeft, TIME_LIMIT, FULL_DASH_ARRAY); AgoraShared.Timer.setRemainingPathColor(timeLeft, COLOR_CODES); AgoraShared.Timer.ActiveTimers[id] = timerInterval; if (timeLeft === 0) { AgoraShared.Timer.onTimesUp(id); } }, 1000); }, formatTime: function (time) { const minutes = Math.floor(time / 60); let seconds = time % 60; if (seconds < 10) { seconds = `0${seconds}`; } return `${minutes}:${seconds}`; }, setRemainingPathColor: function (timeLeft, COLOR_CODES) { const { alert, warning, info } = COLOR_CODES; if (timeLeft <= alert.threshold) { document .getElementById("base-timer-path-remaining") .classList.remove(warning.color); document .getElementById("base-timer-path-remaining") .classList.add(alert.color); } else if (timeLeft <= warning.threshold) { document .getElementById("base-timer-path-remaining") .classList.remove(info.color); document .getElementById("base-timer-path-remaining") .classList.add(warning.color); } }, setCircleDasharray: function (timeLeft, TIME_LIMIT, FULL_DASH_ARRAY) { const circleDasharray = `${( AgoraShared.Timer.calculateTimeFraction(timeLeft, TIME_LIMIT) * FULL_DASH_ARRAY ).toFixed(0)} 283`; document .getElementById("base-timer-path-remaining") .setAttribute("stroke-dasharray", circleDasharray); }, calculateTimeFraction: function (timeLeft, TIME_LIMIT) { const rawTimeFraction = timeLeft / TIME_LIMIT; return rawTimeFraction - (1 / TIME_LIMIT) * (1 - rawTimeFraction); } }, GetValue: function (pstr_VariableName) { return eval(pstr_VariableName); }, Pager: { GetPageSize: function (pstr_PagerElementId) { if ($('#' + pstr_PagerElementId + ' > .pager-content').children().first().length > 0) { var parentHeight = $('#' + pstr_PagerElementId + ' > .pager-content').height(); var elementHeight = $('#' + pstr_PagerElementId + ' > .pager-content').children().first().height() + parseInt($('#' + pstr_PagerElementId + ' > .pager-content').children().first().css('marginBottom')) + parseInt($('#' + pstr_PagerElementId + ' > .pager-content').children().first().css('marginTop')) + parseInt($('#' + pstr_PagerElementId + ' > .pager-content').children().first().css('borderTopWidth')) + parseInt($('#' + pstr_PagerElementId + ' > .pager-content').children().first().css('borderBottomWidth')); return Math.floor(parentHeight / elementHeight); } return 0; } }, HtmlEditor: { A48Id: '0', element: null, translations: { fr: { assetManager: { addButton: 'Ajouter une image', inputPlh: 'https://chemin/vers/image.jpg', modalTitle: 'Sélectionner une image', uploadTitle: 'Déposez ou cliquez ici pour télécharger vos images', }, domComponents: { names: { '': 'Boîte', wrapper: 'Corps', text: 'Texte', comment: 'Commentaire', image: 'Image', video: 'Vidéo', label: 'Libellé', link: 'Lien', map: 'Carte', tfoot: 'Pied de tableau', tbody: 'Corps de tableau', thead: 'En-tête de tableau', table: 'Tableau', row: 'Ligne tableau', cell: 'Cellule tableau', }, }, deviceManager: { device: 'Appareil', devices: { desktop: 'Ordinateur', tablet: 'Tablette', mobileLandscape: 'Mobile format paysage', mobilePortrait: 'Mobile format portrait', }, }, panels: { buttons: { titles: { preview: 'Prévisualisation', fullscreen: 'Plein écran', 'sw-visibility': 'Voir les blocs', 'export-template': 'Télécharger le code', 'open-sm': 'Ouvrir le gestionnaire de style', 'open-tm': 'Paramètres', 'open-layers': 'Ouvrir le gestionnaire de calques', 'open-blocks': 'Ouvrir le gestionnaire de blocs', }, }, }, selectorManager: { label: 'Classes', selected: 'Sélectionné', emptyState: '- État -', states: { hover: 'Survol', active: 'Clic', 'nth-of-type(2n)': 'Paire/Impaire', }, }, styleManager: { empty: "Veuillez sélectionner un élément avant d'utiliser le gestionnaire de style", layer: 'Calque', fileButton: 'Images', sectors: { general: 'Général', layout: 'Disposition', typography: 'Typographie', decorations: 'Décorations', extra: 'Extra', flex: 'Flex', dimension: 'Dimension', }, // The core library generates the name by their `property` name properties: { float: 'Flottant', display: 'Affichage', position: 'Position', top: 'Supérieur', right: 'Droite', left: 'Gauche', bottom: 'Inférieur', width: 'Largeur', height: 'Hauteur', 'max-width': 'Largeur max.', 'max-height': 'Hauteur max.', margin: 'Marge externe', 'margin-top': 'Marge externe supérieure', 'margin-right': 'Marge externe droite', 'margin-left': 'Marge externe gauche', 'margin-bottom': 'Marge externe inférieure', padding: 'Marge interne', 'padding-top': 'Marge interne supérieure', 'padding-left': 'Marge interne gauche', 'padding-right': 'Marge interne droite', 'padding-bottom': 'Marge interne inférieure', 'font-family': 'Police de caractères', 'font-size': 'Taille de police', 'font-weight': 'Épaisseur de police', 'letter-spacing': 'Espacement entre les lettres', color: 'Couleur', 'line-height': 'Espacement des lignes', 'text-align': 'Alignement de texte', 'text-shadow': 'Ombre de texte', 'text-shadow-h': 'Ombre de texte: horizontale', 'text-shadow-v': 'Ombre de texte: verticale', 'text-shadow-blur': 'Flou ombre de texte', 'text-shadow-color': 'Couleur ombre de texte', 'border-top-left': 'Bord supérieur gauche', 'border-top-right': 'Bord supérieur droit', 'border-bottom-left': 'Bord inférieur gauche', 'border-bottom-right': 'Bord inférieur droit', 'border-radius-top-left': 'Bord supérieur arrondi gauche', 'border-radius-top-right': 'Bord supérieur arrondi droit', 'border-radius-bottom-left': 'Bord arrondi inférieur gauche', 'border-radius-bottom-right': 'Bord arrondi inférieur droit', 'border-radius': 'Bord arrondi', border: 'Bordure', 'border-width': 'Largeur de bordure', 'border-style': 'Style de bordure', 'border-color': 'Couleur de bordure', 'box-shadow': 'Ombre de boîte', 'box-shadow-h': 'Ombre de boîte: horizontale', 'box-shadow-v': 'Ombre de boîte: verticale', 'box-shadow-blur': 'Flou ombre de boîte', 'box-shadow-spread': "Extension d'ombre de boîte", 'box-shadow-color': "Couleur d'ombre de boîte", 'box-shadow-type': "Type d'ombre de boîte", background: 'Fond', 'background-image': 'Image de fond', 'background-repeat': 'Répéter fond', 'background-position': 'Position du fond', 'background-attachment': 'Plugin de fond', 'background-size': 'Taille du fond', 'background-color': 'Couleur de fond', transition: 'Transition', 'transition-property': 'Type de transition', 'transition-duration': 'Durée de la transition', 'transition-timing-function': 'Timing transition', perspective: 'Perspective', transform: 'Transformation', 'transform-rotate-x': 'Rotation horizontale', 'transform-rotate-y': 'Rotation verticale', 'transform-rotate-z': 'Rotation profondeur', 'transform-scale-x': 'Échelle horizontale', 'transform-scale-y': 'Échelle verticale', 'transform-scale-z': 'Échelle profondeur', 'flex-direction': 'Direction Flex', 'flex-wrap': 'Flex wrap', 'justify-content': 'Ajuster contenu', 'align-items': 'Aligner éléments', 'align-content': 'Aligner contenu', order: 'Ordre', 'flex-basis': 'Base Flex', 'flex-grow': 'Flex grow', 'flex-shrink': 'Flex shrink', 'align-self': 'Aligner', }, }, traitManager: { empty: 'Veuillez sélectionner un élément pour modifier les paramètres de cet élément', label: 'Paramètres composant', traits: { // The core library generates the name by their `name` property labels: { id: 'Identifiant', alt: 'Texte alternatif', title: 'Titre', href: 'URL', target: 'Ouverture', address: 'Adresse', mapType: 'Type de carte', start: 'Début', endText: 'Texte de d\'expiration', text: 'Texte', length: 'Taille', strings: 'Phrase(s)', }, // In a simple trait, like text input, these are used on input attributes attributes: { id: { placeholder: 'Votre texte ici' }, alt: { placeholder: 'Votre texte ici' }, title: { placeholder: 'Votre texte ici' }, href: { placeholder: 'eg. https://www.avanti-technologies.fr/' }, }, // In a trait like select, these are used to translate option names options: { target: { false: 'Même fenêtre', _blank: 'Nouvelle fenêtre', }, mapType: { q: 'Basique', w: 'Satellite', } }, }, }, }, }, inlineEditor: function (element) { const commands = element.Commands; commands.add('inlineCodeEdit', editor => { let container = document.createElement("div"); let codeViewer = editor && editor.CodeManager.getViewer('CodeMirror').clone(); codeViewer.set({ codeName: 'htmlmixed', theme: 'hopscotch', readOnly: false }); let md = editor.Modal; md.setTitle('Édition du code source'); let viewer = codeViewer.editor; if (!viewer) { let txtarea = document.createElement('textarea'); container.appendChild(txtarea); codeViewer.init(txtarea); viewer = codeViewer.editor; viewer.setOption('lineWrapping', 1); let btnCancel = document.createElement("button"); btnCancel.innerHTML = 'Annuler'; btnCancel.className = 'btn btn-secondary m-3'; btnCancel.onclick = () => { editor.Modal.close(); }; container.appendChild(btnCancel); let btnSave = document.createElement("button"); btnSave.innerHTML = 'Valider les modifications'; btnSave.className = 'btn btn-primary m-3'; btnSave.onclick = () => { let code = codeViewer.editor.getValue(); editor.DomComponents.getWrapper().set('content', ''); editor.setComponents(code); editor.Modal.close(); }; container.appendChild(btnSave); } md.setContent(''); md.setContent(container); codeViewer.setContent(editor.runCommand('gjs-get-inlined-html')); md.open(); viewer.refresh(); }); element.onReady(() => { // on ajout le bouton d'édition du code source element.Panels.addButton('options', { id: 'avtInlineCodeEdit', className: 'd-flex align-items-center justify-content-center', command: 'inlineCodeEdit', label: '', attributes: { title: 'Modifier le code source', }, }); }); }, fileImport: function (element) { element.Blocks.add('downloadButton', { category: 'Éléments', label: 'Fichier', media: '', content: { type: 'downloadButton' }, activate: true, }); const commands = element.Commands; commands.add('fileImportCmd', { run: function (editor, sender, component) { if (component) { let modal = editor.Modal; let container = document.createElement("div"); let inputFileImport = document.createElement("input"); inputFileImport.setAttribute("id", "fileImportInput"); inputFileImport.setAttribute("type", "file"); inputFileImport.className = 'w-100 my-5'; container.appendChild(inputFileImport); let btnCancel = document.createElement("button"); btnCancel.innerHTML = 'Annuler'; btnCancel.className = 'btn btn-secondary mr-2'; btnCancel.onclick = () => { modal.close(); }; container.appendChild(btnCancel); let btnSave = document.createElement("button"); btnSave.innerHTML = 'Télécharger'; btnSave.className = 'btn btn-primary m-3'; btnSave.onclick = () => { var fileInput = document.getElementById('fileImportInput'); var formData = new FormData(); formData.append('file0', fileInput.files[0]); var authToken = localStorage.getItem('authToken'); $.ajax({ url: 'api/FileUpload/PostGrapesJSFiles', type: 'POST', data: formData, contentType: false, crossDomain: true, dataType: 'json', mimeType: "multipart/form-data", processData: false, headers: { 'Authorization': 'Bearer ' + authToken }, success: function (result) { component.getTrait('href').attributes.value = result[0].src; component.getTrait('text').attributes.value = result[0].name; component.getTrait('title').attributes.value = result[0].name; component.set('content', InitMailButton(component)); } }); modal.close(); }; container.appendChild(btnSave); modal.setContent(''); modal.setContent(container); modal.setTitle('Télécharger un fichier'); modal.open(); } } }); }, customComponents: function (element) { element.DomComponents.addType('text', { model: { defaults: { textable: true, hoverable: true, droppable: true, editable: true, contenteditable: true, traits: [ { type: 'select', label: 'Style', name: 'class', options: [ { id: 'text', name: 'Normal', }, { id: 'h1', name: 'Titre principal' }, { id: 'h2', name: 'Titre' }, { id: 'h3', name: 'Sous-titre' }, { id: 'small', name: 'Petits caractères' }, ] }, ], }, }, }); element.DomComponents.addType('mailButton', { model: { defaults: { textable: true, hoverable: true, droppable: true, editable: true, contenteditable: false, traits: [ 'text', 'title', 'href', { name: 'color', type: 'color' }, { name: 'background-color', type: 'color' }, ], }, }, }); element.DomComponents.addType('downloadButton', { model: { defaults: { textable: true, hoverable: true, droppable: true, editable: true, contenteditable: false, traits: [ 'text', 'title', 'href', { name: 'color', type: 'color' }, { name: 'background-color', type: 'color' }, ], }, }, }); element.on('component:create', (component) => { if (component.get('type') === 'mailButton') { element.runCommand('open-sm'); component.set('content', InitMailButton(component)); } else if (component.get('type') === 'downloadButton') { element.runCommand('open-sm'); element.runCommand('fileImportCmd', component); } }); element.on('component:update', (component) => { if (component.get('type') === 'mailButton') { component.set('content', InitMailButton(component)); } }); element.DomComponents.addType('merged-field', { model: { defaults: { hoverable: true, droppable: true, editable: true, tagName: 'span', textable: true, }, toHTML() { return this.get('placeholder'); }, }, // The view below it's just an example for creating a different UX view: { events: { 'change': 'updatePlaceholder', }, updatePlaceholder(ev) { this.model.set({ placeholder: ev.target.value }); }, onAttrUpdate() { const viewStyle = 'padding: 5px;background-color: lightgrey;display: inline-flex;'; this.el.setAttribute('style', viewStyle); }, onRender() { console.log('onRender'); const { model, el } = this; const select = document.createElement('select'); select.innerHTML = htmlEditorMergedFields.map(item => `` ).join(''); el.innerHTML = ''; el.appendChild(select); select.setAttribute('style', 'padding: 5px; border-radius: 5px; border: 1px solid #313131; margin:5px;'); select.value = model.get('placeholder'); var button = document.createElement('button'); button.innerHTML = "Valider"; button.addEventListener("click", function () { const viewStyle = 'background-color: none;padding: 0;border: none;'; el.setAttribute('style', viewStyle); el.innerHTML = model.toHTML(); }); el.appendChild(button); }, } }); element.DomComponents.addType('merged-link', { model: { defaults: { tagName: 'span', textable: true, hoverable: true, droppable: true, editable: true, contenteditable: true, }, toHTML() { return this.get('placeholder'); }, }, // The view below it's just an example for creating a different UX view: { events: { 'change': 'updatePlaceholder', }, updatePlaceholder(ev) { this.model.set({ placeholder: ev.target.value }); }, onAttrUpdate() { const viewStyle = 'padding: 5px;background-color: lightgrey;display: inline-flex;'; this.el.setAttribute('style', viewStyle); }, onRender() { const { model, el } = this; const select = document.createElement('select'); select.innerHTML = htmlEditorMergedLinks.map(item => `` ).join(''); el.innerHTML = ''; el.appendChild(select); select.setAttribute('style', 'padding: 5px; border-radius: 5px; border: 1px solid #313131; margin:5px;'); select.value = model.get('placeholder'); var button = document.createElement('button'); button.innerHTML = "Valider"; button.addEventListener("click", function () { const viewStyle = 'background-color: none;padding: 0;border: none;'; el.innerHTML = model.toHTML(); el.setAttribute('style', viewStyle); element.editor.setComponents(element.runCommand('gjs-get-inlined-html')); }); el.appendChild(button); }, } }); element.DomComponents.addType('image', { model: { defaults: { hoverable: false, } }, }); element.DomComponents.addType('link', { model: { defaults: { tagName: 'a', textable: true, hoverable: true, droppable: true, editable: true, contenteditable: true, content: 'Texte du lien', traits: [ { type: 'text', label: 'Texte du lien', name: 'linktext', changeProp: 1 }, 'title', 'href', 'target', ], linktext: 'Texte du lien', }, init() { // Synchroniser le trait avec le contenu lors de l'initialisation const currentvalue = this.components().map(comp => comp.get('content')).join('') || 'Texte du lien'; this.set('linktext', currentvalue); }, updateTrait() { const currentvalue = this.components().map(comp => comp.get('content')).join(''); this.set('linktext', currentvalue); }, updated(property, value) { if (property == 'linktext') { this.components(value); } }, }, }); element.DomComponents.addType('video', { model: { defaults: { hoverable: false, traits: [ { type: 'select', label: 'Plateforme', name: 'provider', options: [ { id: 'so', name: 'Source HTML5', }, { id: 'ytnc', name: 'Youtube' }, ], } ], }, }, }); element.DomComponents.addType('map', { model: { defaults: { hoverable: false, }, }, }); element.DomComponents.addType('wrapper', { model: { defaults: { hoverable: false, traits: [], }, }, }); element.DomComponents.addType('tabs', { model: { defaults: { hoverable: false, }, }, }); element.DomComponents.addType('tab', { model: { defaults: { hoverable: false, }, }, }); element.DomComponents.addType('tab-container', { model: { defaults: { hoverable: false, }, }, }); element.DomComponents.addType('tab-contents', { model: { defaults: { hoverable: false, }, }, }); element.DomComponents.addType('tab-content', { model: { defaults: { hoverable: false, }, }, }); element.DomComponents.addType('countdown', { model: { defaults: { hoverable: false, }, }, }); element.DomComponents.addType('default', { model: { defaults: { hoverable: false, }, }, }); element.DomComponents.addType('custom-code', { model: { defaults: { hoverable: false, }, }, }); element.DomComponents.addType('typed', { model: { defaults: { attributes: { style: 'padding: 1rem;' }, hoverable: false, }, }, }); element.DomComponents.addType('content1', { model: { defaults: { attributes: { class: 'container-fluid row' }, hoverable: false, tagname: 'content1', components: [ { attributes: { class: 'col-md-6 p-3' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid m-auto' }, }, ], }, { attributes: { class: 'col-md-6 p-3' }, components: [ { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, '

Cliquez pour modifier le texte

' ], }, ] }, }, }); element.DomComponents.addType('content2', { model: { defaults: { hoverable: false, tagname: 'content2', attributes: { class: 'container-fluid row' }, components: [ { attributes: { class: 'col-md-6 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid' }, }, { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, '

Cliquez pour modifier le texte

' ], }, { attributes: { class: 'col-md-6 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid' }, }, { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, '

Cliquez pour modifier le texte

' ], } ], }, }, }); element.DomComponents.addType('content3', { model: { defaults: { hoverable: false, tagname: 'content3', attributes: { class: 'container-fluid row' }, components: [ { attributes: { class: 'col-md-4 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid mb-2' }, }, { type: 'image', tagName: 'image', attributes: { class: 'img-fluid' }, }, ], }, { attributes: { class: 'col-8 p-3 text-center' }, components: [ { type: 'video', tagName: 'video', attributes: { class: 'w-100' }, }, ], } ], }, }, }); element.DomComponents.addType('content4', { model: { defaults: { hoverable: false, tagname: 'content4', attributes: { class: 'container-fluid row' }, components: [ { attributes: { class: 'col-md-4 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid' }, }, { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, '

Cliquez pour modifier le texte

' ], }, { attributes: { class: 'col-md-4 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid' }, }, { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, '

Cliquez pour modifier le texte

' ], }, { attributes: { class: 'col-md-4 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid' }, }, { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, '

Cliquez pour modifier le texte

' ], } ], }, }, }); element.DomComponents.addType('content5', { model: { defaults: { hoverable: false, tagname: 'content5', attributes: { class: 'container-fluid row' }, components: [ { attributes: { class: 'col-md-3 p-3' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid' }, }, ], }, { attributes: { class: 'col-md-3 p-3' }, components: [ { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, '

Cliquez pour modifier le texte

' ], }, { attributes: { class: 'col-md-3 p-3' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid' }, }, ], }, { attributes: { class: 'col-md-3 p-3' }, components: [ { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, '

Cliquez pour modifier le texte

' ], }, ], }, }, }); element.DomComponents.addType('content6', { model: { defaults: { hoverable: false, tagname: 'content6', attributes: { class: 'container-fluid row' }, components: [ { attributes: { class: 'col-md-3 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid m-2' }, }, { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, ], }, { attributes: { class: 'col-md-3 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid m-2' }, }, { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, ], }, { attributes: { class: 'col-md-3 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid m-2' }, }, { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, ], }, { attributes: { class: 'col-md-3 p-3 text-center' }, components: [ { type: 'image', tagName: 'image', attributes: { class: 'img-fluid m-2' }, }, { type: 'text', tagName: 'h3', attributes: { class: 'h3' }, components: 'Cliquez pour modifier le texte', }, ], }, ], }, }, }); }, options: { storageManager: false, allowScripts: 1, height: '100%', container: '#htmlEditor', clearOnRender: true, fromElement: true, showOffsets: true, colorPicker: { appendTo: 'parent', offset: { top: 26, left: -166, }, }, i18n: { locale: 'fr', // Langue par défaut detectLocale: true, // L'éditeur détecte la langue de l'utilisateur localeFallback: 'fr', // Si aucune correspondant à l'utilisateur on affiche FR }, canvas: { // On charge le CSS du FO styles: [] }, assetManager: { embedAsBase64: true, uploadFile: function (e) { var files = e.dataTransfer ? e.dataTransfer.files : e.target.files; console.log('files', files); var formData = new FormData(); for (var i in files) { formData.append('file-' + i, files[i]) //containing all the selected images from local } var authToken = localStorage.getItem('authToken'); $.ajax({ url: 'api/FileUpload/PostGrapesJSFiles', type: 'POST', data: formData, contentType: false, crossDomain: true, dataType: 'json', mimeType: "multipart/form-data", processData: false, headers: { 'Authorization': 'Bearer ' + authToken }, success: function (result) { AgoraShared.HtmlEditor.element.AssetManager.add(result); var vlst_UserAssetPictures = []; if (localStorage.getItem('GrapesJS_' + AgoraShared.HtmlEditor.A48Id) !== null) { vlst_UserAssetPictures = JSON.parse(localStorage.getItem('GrapesJS_' + AgoraShared.HtmlEditor.A48Id)); } for (var i = 0; i < result.length; i++) { if (!vlst_UserAssetPictures.includes(result[i].src)) { vlst_UserAssetPictures.push(result[i].src); } } localStorage.setItem('GrapesJS_' + AgoraShared.HtmlEditor.A48Id, JSON.stringify(vlst_UserAssetPictures)); } }); }, }, blockManager: { blocks: [] }, styleManager: { clearProperties: 1, sectors: [ { name: 'Position', open: false, properties: [ { extend: 'float', type: 'radio', default: 'none', options: [ { value: 'none', className: 'fa fa-times' }, { value: 'left', className: 'fa fa-align-left' }, { value: 'right', className: 'fa fa-align-right' } ], }, { extend: 'display', type: 'select', default: 'block', options: [ { value: 'block' }, { value: 'inline' }, { value: 'inline-block' }, { value: 'none' }, ], }, { extend: 'position', type: 'select' }, 'top', 'right', 'left', 'bottom', ], }, { name: 'Dimension', open: false, properties: [ 'width', { id: 'flex-width', type: 'integer', name: 'Width', units: ['px', '%'], property: 'flex-basis', toRequire: 1, }, 'height', 'margin', 'padding' ], }, { name: 'Typographie', open: false, properties: [ 'font-family', 'font-size', 'font-weight', 'letter-spacing', 'color', 'line-height', { extend: 'text-align', options: [ { id: 'left', label: 'Left', className: 'fa fa-align-left' }, { id: 'center', label: 'Center', className: 'fa fa-align-center' }, { id: 'right', label: 'Right', className: 'fa fa-align-right' }, { id: 'justify', label: 'Justify', className: 'fa fa-align-justify' } ], }, { property: 'text-decoration', type: 'radio', default: 'none', options: [ { id: 'none', label: 'None', className: 'fa fa-times' }, { id: 'underline', label: 'underline', className: 'fa fa-underline' }, { id: 'line-through', label: 'Line-through', className: 'fa fa-strikethrough' } ], }, 'text-shadow' ], }, { name: 'Décorations', open: false, properties: [ 'opacity', 'border-radius', 'border', 'box-shadow', 'background', ], } ], }, plugins: [ 'grapesjs-agorashared', 'grapesjs-agorashared-inlineEditor', 'grapesjs-agorashared-fileImport' ], pluginsOpts: { 'grapesjs-preset-newsletter': { blocks: [ 'sect100', 'sect50', 'sect30', 'sect37', 'button', 'divider', 'text', 'image', 'text-sect', 'quote', 'grid-items', 'list-items', ], codeViewerTheme: 'material', cellStyle: { 'font-size': '12px', 'font-weight': 300, 'vertical-align': 'top', color: 'rgb(111, 119, 125)', margin: 0, padding: 0, }, category: 'Mise en page' }, 'gjs-blocks-basic': { category: 'Mise en page', flexGrid: true, labelColumn1: '1 colonne', labelColumn2: '2 colonnes', labelColumn3: '3 colonnes', labelColumn37: '2 colonnes 3/7', }, 'grapesjs-tui-image-editor': { script: [ 'https://uicdn.toast.com/tui.code-snippet/v1.5.2/tui-code-snippet.min.js', 'https://uicdn.toast.com/tui-color-picker/v2.2.7/tui-color-picker.min.js', 'https://uicdn.toast.com/tui-image-editor/v3.15.2/tui-image-editor.min.js' ], style: [ 'https://uicdn.toast.com/tui-color-picker/v2.2.7/tui-color-picker.min.css', 'https://uicdn.toast.com/tui-image-editor/v3.15.2/tui-image-editor.min.css', ], }, 'grapesjs-tabs': { tabsBlock: { label: 'Onglets', category: 'Mise en page' } }, 'grapesjs-tooltip': { labelTooltip: 'Infobulle', blockTooltip: { category: 'Extra', }, }, 'grapesjs-component-countdown': { label: 'Compte à rebours', block: { category: 'Extra' }, }, 'grapesjs-custom-code': { blockCustomCode: { label: 'Code', category: 'Extra' }, modalTitle: 'Importer votre code', buttonLabel: 'Insérer', }, 'grapesjs-typed': { block: { category: 'Extra', label: 'Saisie de texte', content: { type: 'typed', 'type-speed': 10, strings: [ 'Mon texte écrit', ], } } }, }, selectorManager: { componentFirst: true }, }, init: function (dotnetHelper, content, resourceURLs, isMailMode, A48Id, mergedFields, mergedLinks) { AgoraShared.HtmlEditor.A48Id = A48Id; $('#htmlEditor').html(content); try { // -- Ajout de nos propres plugins grapesjs.plugins.add('grapesjs-agorashared', AgoraShared.HtmlEditor.customComponents); grapesjs.plugins.add('grapesjs-agorashared-inlineEditor', AgoraShared.HtmlEditor.inlineEditor); if (isMailMode) { console.log('Mode newsletter'); AgoraShared.HtmlEditor.options.blockManager.blocks = htmlEditorMailBlocks; // -- Ajout des champs de fusion if (mergedFields) { console.log('Importation des champs de fusion...', mergedFields); htmlEditorMergedFields = JSON.parse(mergedFields); AgoraShared.HtmlEditor.options.blockManager.blocks.push(htmlEditorMergedFieldBlock); } if (mergedLinks) { console.log('Importation des liens de fusion...', mergedLinks); htmlEditorMergedLinks = JSON.parse(mergedLinks); AgoraShared.HtmlEditor.options.blockManager.blocks.push(htmlEditorMergedLinkBlock); } AgoraShared.HtmlEditor.options.plugins.push('grapesjs-preset-newsletter'); AgoraShared.HtmlEditor.options.plugins.push('grapesjs-custom-code'); } else { console.log('Mode webpage'); AgoraShared.HtmlEditor.options.blockManager.blocks = htmlEditorWebPageBlocks; AgoraShared.HtmlEditor.options.plugins.push('grapesjs-preset-webpage'); AgoraShared.HtmlEditor.options.plugins.push('grapesjs-preset-newsletter'); AgoraShared.HtmlEditor.options.plugins.push('gjs-blocks-basic'); AgoraShared.HtmlEditor.options.plugins.push('grapesjs-component-countdown'); AgoraShared.HtmlEditor.options.plugins.push('grapesjs-tabs'); AgoraShared.HtmlEditor.options.plugins.push('grapesjs-custom-code'); AgoraShared.HtmlEditor.options.plugins.push('grapesjs-touch'); AgoraShared.HtmlEditor.options.plugins.push('grapesjs-tooltip'); AgoraShared.HtmlEditor.options.plugins.push('grapesjs-typed'); AgoraShared.HtmlEditor.options.plugins.push('grapesjs-style-bg'); } grapesjs.plugins.add('grapesjs-agorashared-fileImport', AgoraShared.HtmlEditor.fileImport); // -- Ajout de notre CSS for (var i = 0; i < resourceURLs.length; i++) { var e = resourceURLs[i]; AgoraShared.HtmlEditor.options.canvas.styles.push(e); } // Ajout de la traduction FR var fr = AgoraShared.HtmlEditor.translations.fr; AgoraShared.HtmlEditor.options.i18n.messages = { fr }; // Initialisation AgoraShared.HtmlEditor.element = grapesjs.init(AgoraShared.HtmlEditor.options); // On cache l'onglet Options (Traits), on va déplacer son contenu ds le load ci-dessous AgoraShared.HtmlEditor.element.Panels.getPanel('options').view.className = 'd-none'; // Lancement de l'éditeur AgoraShared.HtmlEditor.element.on('load', function () { var $ = grapesjs.$; // On charge les images déjà uploadées par l'A48 var vlst_UserAssetPictures = JSON.parse(localStorage.getItem('GrapesJS_' + AgoraShared.HtmlEditor.A48Id)); if (vlst_UserAssetPictures) { for (var i = 0; i < vlst_UserAssetPictures.length; i++) { AgoraShared.HtmlEditor.element.AssetManager.add({ src: vlst_UserAssetPictures[i] }); } } // On re-style certains composants de l'éditeur pour une meilleure ergonomie // Attention ce css est inclus lors de l'enregistrement var cssEditor = ''; AgoraShared.HtmlEditor.element.getComponents().add(cssEditor); // ---------------------------------- // --------- Barre d'action --------- // ---------------------------------- { // On réédite les boutons d'action pour qu'ils utilisent les icones FA + traductions persos + ordre // --- Fullscreen if (AgoraShared.HtmlEditor.element.Panels.getButton('options', 'fullscreen')) { AgoraShared.HtmlEditor.element.Panels.addButton('options', { id: 'avtFullscreen', className: 'd-flex align-items-center justify-content-center', command: 'fullscreen', label: '', attributes: { title: 'Plein écran', }, }); AgoraShared.HtmlEditor.element.Panels.removeButton('options', 'fullscreen'); } // --- Borders if (AgoraShared.HtmlEditor.element.Panels.getButton('options', 'sw-visibility')) { AgoraShared.HtmlEditor.element.Panels.addButton('options', { id: 'avtBorders', className: 'd-flex align-items-center justify-content-center', command: 'sw-visibility', label: '', attributes: { title: 'Afficher les blocks', }, }); AgoraShared.HtmlEditor.element.Panels.removeButton('options', 'sw-visibility'); } // --- Preview if (AgoraShared.HtmlEditor.element.Panels.getButton('options', 'preview')) { AgoraShared.HtmlEditor.element.Panels.addButton('options', { id: 'avtPreview', className: 'd-flex align-items-center justify-content-center', command: 'preview', label: '', attributes: { title: 'Aperçu du résultat', }, }); AgoraShared.HtmlEditor.element.Panels.removeButton('options', 'preview'); } // --- Redo (ne marche pas en mode newsletter) if (!isMailMode && AgoraShared.HtmlEditor.element.Panels.getButton('options', 'redo')) { AgoraShared.HtmlEditor.element.Panels.addButton('options', { id: 'avtRedo', className: 'd-flex align-items-center justify-content-center', command: AgoraShared.HtmlEditor.element.Panels.getButton('options', 'redo').attributes.command, label: '', attributes: { title: 'Rétablir le dernier changement', }, }); AgoraShared.HtmlEditor.element.Panels.removeButton('options', 'redo'); } // --- Undo (ne marche pas en mode newsletter) if (!isMailMode && AgoraShared.HtmlEditor.element.Panels.getButton('options', 'undo')) { AgoraShared.HtmlEditor.element.Panels.addButton('options', { id: 'avtUndo', className: 'd-flex align-items-center justify-content-center', command: AgoraShared.HtmlEditor.element.Panels.getButton('options', 'undo').attributes.command, label: '', attributes: { title: 'Annuler le dernier changement', }, }); AgoraShared.HtmlEditor.element.Panels.removeButton('options', 'undo'); } // --- Import AgoraShared.HtmlEditor.element.Panels.removeButton('options', 'gjs-open-import-webpage'); AgoraShared.HtmlEditor.element.Panels.removeButton('options', 'export-template'); // --- Clear if (AgoraShared.HtmlEditor.element.Panels.getButton('options', 'canvas-clear')) { AgoraShared.HtmlEditor.element.Panels.removeButton('options', 'canvas-clear'); } AgoraShared.HtmlEditor.element.Panels.addButton('options', { id: 'avtClear', className: 'd-flex align-items-center justify-content-center', command: 'canvas-clear', label: '', attributes: { title: 'Supprimer tout le contenu', }, }); AgoraShared.HtmlEditor.element.Commands.add('canvas-clear', function () { if (confirm('Êtes-vous sûr de vouloir supprimer toute la page ?')) { AgoraShared.HtmlEditor.element.runCommand('core:canvas-clear'); AgoraShared.HtmlEditor.element.getComponents().add(cssEditor); } }); } // ---------------------------------- // ------ Barre de navigation ------- // ---------------------------------- { // --- Onglet de mise en forme du composant (Style Manager) AgoraShared.HtmlEditor.element.Panels.addButton('views', { id: 'avtStyleManager', command: 'open-sm', label: '', attributes: { title: 'Personnaliser un élément', }, }); AgoraShared.HtmlEditor.element.Panels.removeButton('views', 'open-sm'); // --- Onglet montrant la structure de la page (Layers Manager) AgoraShared.HtmlEditor.element.Panels.addButton('views', { id: 'avtLayers', command: 'open-layers', label: '', attributes: { title: 'Voir la structure du contenu', }, }); AgoraShared.HtmlEditor.element.Panels.removeButton('views', 'open-layers'); // --- Onglet d'ajout de composants (Blocks Manager) AgoraShared.HtmlEditor.element.Panels.addButton('views', { id: 'avtBlocks', command: 'open-blocks', label: '', attributes: { title: 'Ajouter un élément', }, }); AgoraShared.HtmlEditor.element.Panels.removeButton('views', 'open-blocks'); // --- Traits Manager // On ouvre l'onglet Options de composants (Traits) pour charger son contenu // car on va le déplacer dans l'onglet Style manager ci-dessous (pour une meilleure ergo) AgoraShared.HtmlEditor.element.Panels.getButton('views', 'open-tm').set('active', 1); AgoraShared.HtmlEditor.element.Panels.getButton('views', 'open-tm').set('active', 0); AgoraShared.HtmlEditor.element.Panels.removeButton('views', 'open-tm'); // Onglet actif par défaut : Ajout de composants (Blocks) AgoraShared.HtmlEditor.element.Panels.getButton('views', 'avtBlocks').set('active', 1); } // --- Style manager content Panel : // on met en forme le contenu de l'onglet qui permet de styler les composants individuellement { // Options du composants (Traits sector) var settingsSector = $('
' + '
Options
' + '
'); var settingsProps = settingsSector.find('.gjs-sm-properties'); settingsProps.append($('.gjs-trt-traits')); $('.gjs-sm-sectors').before(settingsSector); settingsSector.find('.gjs-sm-sector-title').on('click', function () { var settingsStyle = settingsProps.get(0).style; if (settingsStyle.display == 'none') { settingsStyle.display = 'block'; } else { settingsStyle.display = 'none'; } }); // Editeur de style avancé (Component Formatting sector) var componentFormattingSector = $('
' + '
Mise en forme avancée
' + '
'); var formattingProps = componentFormattingSector.find('.gjs-sm-properties'); $('.gjs-sm-sectors').before(componentFormattingSector); $('.gjs-sm-sectors').detach().appendTo($('.adv-formatting .gjs-sm-properties')); componentFormattingSector.find('.adv-formatting-title').on('click', function () { var formattingStyle = formattingProps.get(0).style; if (formattingStyle.display == 'none') { formattingStyle.display = 'block'; } else { formattingStyle.display = 'none'; } }); // Editeur des Class associées au composant (Tags sector) var tagsSector = $('
' + '
Classes
' + '
'); var tagsProps = tagsSector.find('.gjs-sm-tags'); tagsProps.append($('.gjs-clm-tags')); $('.gjs-sm-sectors').after(tagsSector); tagsSector.find('.gjs-sm-sector-title').on('click', function () { var tagsStyle = tagsProps.get(0).style; tagsProps.parent().toggleClass('gjs-sm-open'); if (tagsStyle.display == 'none') { tagsStyle.display = 'block'; } else { tagsStyle.display = 'none'; } }); } }); AgoraShared.HtmlEditor.element.on('asset:remove', function (e) { var vlst_UserAssetPictures = JSON.parse(localStorage.getItem('GrapesJS_' + AgoraShared.HtmlEditor.A48Id)); var vint_Index = vlst_UserAssetPictures.indexOf(e.id); if (vint_Index > -1) { vlst_UserAssetPictures.splice(vint_Index, 1); } localStorage.setItem('GrapesJS_' + AgoraShared.HtmlEditor.A48Id, JSON.stringify(vlst_UserAssetPictures)); }); console.log('htmlEditor', AgoraShared.HtmlEditor); } catch (error) { console.log('htmlEditor:init:error', error); } }, save: function () { return AgoraShared.HtmlEditor.element.getHtml() + ''; }, inlineSave: function () { return AgoraShared.HtmlEditor.element.runCommand('gjs-get-inlined-html'); }, destroy: function () { AgoraShared.HtmlEditor.element.destroy(); }, move: function (containerId) { if (!AgoraShared.HtmlEditor.element) return; var editor = AgoraShared.HtmlEditor.element; const target = document.getElementById(containerId); const container = editor.getContainer(); if (target && container && target !== container.parentElement) { target.appendChild(container); const html = editor.getHtml(); const css = editor.getCss(); editor.setComponents(html); editor.setStyle(css); editor.editor.refreshCanvas(); editor.refresh(); } }, isInit: function () { if (!AgoraShared.HtmlEditor.element) return false; else return true; }, setContent: function (content) { console.info(content); if (!AgoraShared.HtmlEditor.element) return; var editor = AgoraShared.HtmlEditor.element; //editor.html(content); //const html = editor.getHtml(); //const css = editor.getCss(); editor.setComponents(content); //editor.setStyle(css); editor.editor.refreshCanvas(); editor.refresh(); } }, UnlayerEditor: { init: function (dotnetHelper, isMailMode, projectId, jsonContent, culture, userId, mergeFields, mergeLinks, resourceURLs) { if (unlayer) { window.blazorHelper = dotnetHelper; unlayer.destroy(); console.log(''); console.log(' projectId', projectId); console.log(' culture', culture); console.log(' userId', userId); if (isMailMode) { console.log(' Mode newsletter'); unlayer.init({ version: 'latest', id: 'unlayerEditor', projectId: projectId, displayMode: 'email', tools: { form: { enabled: false }, menu: { enabled: false } }, customJS: [ 'https://' + window.location.host + '/api/Localization/GetLocalizedScript?Path=/js/unlayerCustom.js&lang=' + 'fr-FR&nocache=' + Math.random() ], appearance: { theme: 'modern_light', loader: { html: htmlLoaderDiv, css: htmlLoaderCSS } }, editor: { autoSelectOnDrop: true, }, locale: culture, user: userId, fonts: { showDefaultFonts: false, customFonts: [ { label: 'Andale Mono', value: 'andale mono,times' }, { label: 'Arial', value: 'arial,helvetica,sans-serif' }, { label: 'Arial Black', value: 'arial black,avant garde' }, { label: 'Book Antiqua', value: 'book antiqua,palatino' }, { label: 'Comic Sans MS', value: 'comic sans ms,sans-serif' }, { label: 'Courier New', value: 'courier new,courier' }, { label: 'Georgia', value: 'georgia,palatino' }, { label: 'Helvetica', value: 'helvetica' }, { label: 'Impact', value: 'impact,chicago' }, { label: 'Symbol', value: 'symbol' }, { label: 'Tahoma', value: 'tahoma,arial,helvetica,sans-serif' }, { label: 'Terminal', value: 'terminal,monaco' }, { label: 'Times New Roman', value: 'times new roman,times' }, { label: 'Trebuchet MS', value: 'trebuchet ms,geneva' }, { label: 'Verdana', value: 'verdana,geneva' }, { label: 'Webdings', value: 'webdings' }, { label: 'Wingdings', value: 'wingdings,zapf dingbats' }, { label: 'Segoe UI', value: 'segoe ui,tahoma,arial,helvetica,sans-serif' }, { label: 'Calibri', value: 'calibri,candara,segoe,Segoe UI,Optima,Arial,sans-serif' }, { label: 'Candara', value: 'candara,calibri,Segoe UI,sans-serif' }, { label: 'Consolas', value: 'consolas,monaco,monospace' }, { label: 'Corbel', value: 'corbel,calibri,tahoma,verdana,sans-serif' }, { label: 'Franklin Gothic Medium', value: 'franklin gothic medium,arial narrow,arial,sans-serif' }, { label: 'Gill Sans MT', value: 'gill sans mt,gill sans,sans-serif' }, { label: 'Lucida Console', value: 'lucida console,monaco,monospace' }, { label: 'Lucida Sans Unicode', value: 'lucida sans unicode,lucida grande,sans-serif' }, { label: 'Palatino Linotype', value: 'palatino linotype,book antiqua,palatino,serif' }, { label: 'Segoe Print', value: 'segoe print,comic sans ms,sans-serif' }, { label: 'Segoe Script', value: 'segoe script,comic sans ms,cursive' }, { label: 'Segoe UI Light', value: 'segoe ui light,segoe ui,sans-serif' }, { label: 'Segoe UI Semibold', value: 'segoe ui semibold,segoe ui,sans-serif' }, { label: 'Segoe UI Symbol', value: 'segoe ui symbol,segoe ui,sans-serif' }, { label: 'Sitka', value: 'sitka small,sitka text,sitka subheading,sitka heading,sitka display,sitka banner,serif' }, { label: 'Arial Narrow', value: 'arial narrow,arial,sans-serif' }, { label: 'Bookman Old Style', value: 'bookman old style,serif' }, { label: 'Century', value: 'century,serif' }, { label: 'Garamond', value: 'garamond,baskerville,serif' }, { label: 'Perpetua', value: 'perpetua,serif' }, { label: 'Rockwell', value: 'rockwell,serif' }, { label: 'Bodoni MT', value: 'bodoni mt,serif' }, { label: 'Baskerville Old Face', value: 'baskerville old face,serif' }, { label: 'Bell MT', value: 'bell mt,serif' }, { label: 'Century Gothic', value: 'century gothic,arial,sans-serif' }, { label: 'Berlin Sans FB', value: 'berlin sans fb,sans-serif' }, { label: 'Britannic Bold', value: 'britannic bold,sans-serif' }, { label: 'Eras ITC', value: 'eras itc,sans-serif' }, { label: 'Footlight MT Light', value: 'footlight mt light,sans-serif' }, { label: 'Goudy Old Style', value: 'goudy old style,serif' }, { label: 'Juice ITC', value: 'juice itc,cursive' }, { label: 'Kunstler Script', value: 'kunstler script,cursive' }, { label: 'Lucida Bright', value: 'lucida bright,serif' }, { label: 'Maiandra GD', value: 'maiandra gd,sans-serif' }, { label: 'Mistral', value: 'mistral,cursive' }, { label: 'MS Sans Serif', value: 'ms sans serif,Arial,sans-serif' }, { label: 'MS Serif', value: 'ms serif,times new roman,serif' }, { label: 'OCR A Extended', value: 'ocr a extended,monaco,monospace' }, { label: 'Poor Richard', value: 'poor richard,serif' }, { label: 'Rage Italic', value: 'rage italic,cursive' }, { label: 'Script MT Bold', value: 'script mt bold,cursive' }, { label: 'Tw Cen MT', value: 'tw cen mt,sans-serif' } ] }, features: { textEditor: { emojis: true, }, }, }); } else { console.log(' Mode Web'); if (!unlayerEditorUploadedFiles) { unlayerEditorUploadedFiles = []; } unlayer.init({ version: 'latest', id: 'unlayerEditor', projectId: projectId, displayMode: 'web', tools: { form: { enabled: false }, menu: { enabled: false } }, customJS: [ 'https://' + window.location.host + '/api/Localization/GetLocalizedScript?Path=/js/unlayerCustom.js&lang=' + 'fr-FR&nocache=' + Math.random() ], appearance: { theme: 'modern_light', loader: { html: htmlLoaderDiv, css: htmlLoaderCSS } }, editor: { autoSelectOnDrop: true, }, locale: culture, user: userId, customCSS: resourceURLs, fonts: { showDefaultFonts: false, customFonts: [ { label: 'Andale Mono', value: 'andale mono,times' }, { label: 'Arial', value: 'arial,helvetica,sans-serif' }, { label: 'Arial Black', value: 'arial black,avant garde' }, { label: 'Book Antiqua', value: 'book antiqua,palatino' }, { label: 'Comic Sans MS', value: 'comic sans ms,sans-serif' }, { label: 'Courier New', value: 'courier new,courier' }, { label: 'Georgia', value: 'georgia,palatino' }, { label: 'Helvetica', value: 'helvetica' }, { label: 'Impact', value: 'impact,chicago' }, { label: 'Symbol', value: 'symbol' }, { label: 'Tahoma', value: 'tahoma,arial,helvetica,sans-serif' }, { label: 'Terminal', value: 'terminal,monaco' }, { label: 'Times New Roman', value: 'times new roman,times' }, { label: 'Trebuchet MS', value: 'trebuchet ms,geneva' }, { label: 'Verdana', value: 'verdana,geneva' }, { label: 'Webdings', value: 'webdings' }, { label: 'Wingdings', value: 'wingdings,zapf dingbats' }, { label: 'Segoe UI', value: 'segoe ui,tahoma,arial,helvetica,sans-serif' }, { label: 'Calibri', value: 'calibri,candara,segoe,Segoe UI,Optima,Arial,sans-serif' }, { label: 'Candara', value: 'candara,calibri,Segoe UI,sans-serif' }, { label: 'Consolas', value: 'consolas,monaco,monospace' }, { label: 'Corbel', value: 'corbel,calibri,tahoma,verdana,sans-serif' }, { label: 'Franklin Gothic Medium', value: 'franklin gothic medium,arial narrow,arial,sans-serif' }, { label: 'Gill Sans MT', value: 'gill sans mt,gill sans,sans-serif' }, { label: 'Lucida Console', value: 'lucida console,monaco,monospace' }, { label: 'Lucida Sans Unicode', value: 'lucida sans unicode,lucida grande,sans-serif' }, { label: 'Palatino Linotype', value: 'palatino linotype,book antiqua,palatino,serif' }, { label: 'Segoe Print', value: 'segoe print,comic sans ms,sans-serif' }, { label: 'Segoe Script', value: 'segoe script,comic sans ms,cursive' }, { label: 'Segoe UI Light', value: 'segoe ui light,segoe ui,sans-serif' }, { label: 'Segoe UI Semibold', value: 'segoe ui semibold,segoe ui,sans-serif' }, { label: 'Segoe UI Symbol', value: 'segoe ui symbol,segoe ui,sans-serif' }, { label: 'Sitka', value: 'sitka small,sitka text,sitka subheading,sitka heading,sitka display,sitka banner,serif' }, { label: 'Arial Narrow', value: 'arial narrow,arial,sans-serif' }, { label: 'Bookman Old Style', value: 'bookman old style,serif' }, { label: 'Century', value: 'century,serif' }, { label: 'Garamond', value: 'garamond,baskerville,serif' }, { label: 'Perpetua', value: 'perpetua,serif' }, { label: 'Rockwell', value: 'rockwell,serif' }, { label: 'Bodoni MT', value: 'bodoni mt,serif' }, { label: 'Baskerville Old Face', value: 'baskerville old face,serif' }, { label: 'Bell MT', value: 'bell mt,serif' }, { label: 'Century Gothic', value: 'century gothic,arial,sans-serif' }, { label: 'Berlin Sans FB', value: 'berlin sans fb,sans-serif' }, { label: 'Britannic Bold', value: 'britannic bold,sans-serif' }, { label: 'Eras ITC', value: 'eras itc,sans-serif' }, { label: 'Footlight MT Light', value: 'footlight mt light,sans-serif' }, { label: 'Goudy Old Style', value: 'goudy old style,serif' }, { label: 'Juice ITC', value: 'juice itc,cursive' }, { label: 'Kunstler Script', value: 'kunstler script,cursive' }, { label: 'Lucida Bright', value: 'lucida bright,serif' }, { label: 'Maiandra GD', value: 'maiandra gd,sans-serif' }, { label: 'Mistral', value: 'mistral,cursive' }, { label: 'MS Sans Serif', value: 'ms sans serif,Arial,sans-serif' }, { label: 'MS Serif', value: 'ms serif,times new roman,serif' }, { label: 'OCR A Extended', value: 'ocr a extended,monaco,monospace' }, { label: 'Poor Richard', value: 'poor richard,serif' }, { label: 'Rage Italic', value: 'rage italic,cursive' }, { label: 'Script MT Bold', value: 'script mt bold,cursive' }, { label: 'Tw Cen MT', value: 'tw cen mt,sans-serif' } ] }, features: { textEditor: { emojis: true, }, }, }); } if (mergeFields && mergeFields.length > 0) { console.log(' setMergeTags'); unlayer.setMergeTags(JSON.parse(mergeFields)); } if (mergeLinks && mergeLinks.length > 0) { console.log(' setSpecialLinks'); unlayer.setSpecialLinks(JSON.parse(mergeLinks)); } unlayer.addEventListener('editor:ready', function () { if (isMailMode) { console.log(' setBodyValues 500px'); unlayer.setBodyValues({ contentWidth: "500px", }); } else { console.log(' setBodyValues 100%'); unlayer.setBodyValues({ contentWidth: "100%", }); } if (jsonContent && jsonContent.length > 0) { console.log(' loadDesign');/*, jsonContent);*/ unlayer.loadDesign(JSON.parse(jsonContent)); } console.log("NotifyUnlayerLoaded"); dotnetHelper.invokeMethodAsync("NotifyUnlayerLoaded"); }); unlayer.registerCallback('image', function (file, done) { console.log(' upload', file); var formData = new FormData(); formData.append('file', file.attachments[0]); var authToken = localStorage.getItem('authToken'); $.ajax({ url: 'api/FileUpload/PostGrapesJSFiles', type: 'POST', data: formData, contentType: false, crossDomain: true, dataType: 'json', mimeType: "multipart/form-data", processData: false, headers: { 'Authorization': 'Bearer ' + authToken }, success: function (result) { console.log(' file success', result); done({ progress: 100, url: result[0].src }); } }); }) } }, getHtml: function () { return new Promise((resolve, reject) => { try { console.log(' getHtml unlayer', unlayer); if (typeof unlayer === 'undefined' || typeof unlayer.exportHtml !== 'function') { console.error(' getHtml error: unlayer is not defined or exportHtml is not a function'); reject('Unlayer is not defined or exportHtml is not a function'); return; } unlayer.exportHtml((data) => { try { console.log(' getHtml exportHtml', data); if (data && data.html) { console.log(' getHtml', data.html); resolve(data.html); } else { console.log(' getHtml reject', data); reject('No HTML content in the exported data'); } } catch (callbackError) { console.error(' getHtml callback error', callbackError); reject(callbackError); } }, { minify: true }); } catch (error) { console.error(' getHtml error', error); reject(error); } }); }, getDesign: function () { return new Promise((resolve, reject) => { unlayer.exportHtml(function (data) { if (data && data.design) { console.log(' getDesign', data.design); resolve(JSON.stringify(data.design)); } else { setTimeout(() => { unlayer.exportHtml(function (retryData) { if (retryData && retryData.design) { console.log(' getDesign retry success', retryData.design); resolve(JSON.stringify(retryData.design)); } else { console.error(' getDesign retry failed:', retryData); reject(new Error('Export HTML returned null or invalid data on retry.')); } }); }, 1500); } }); }); }, destroy: function () { if (unlayer) { unlayer.destroy(); const editorContainer = document.getElementById('unlayerEditor'); if (editorContainer) { editorContainer.innerHTML = ''; } } }, insertFileData: function (elementId, fileName, fileUrl) { window.unlayer.exportHtml((data) => { const design = data.design; const updatedContent = design.body.rows.map(row => { row.columns = row.columns.map(column => { column.contents = column.contents.map(content => { if (content.values._meta.htmlID === elementId) { content.values.fileName = fileName; content.values.fileUrl = fileUrl; } return content; }); return column; }); return row; }); design.body.rows = updatedContent; window.unlayer.loadDesign(design); }); } } } function _base64ToArrayBuffer(base64) { var binary_string = window.atob(base64); var len = binary_string.length; var bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } return bytes.buffer; } var filePicker = function (cb, value, meta) { console.log('filePicker cb', cb); console.log('filePicker value', value); console.log('filePicker meta', meta); var input = document.createElement('input'); input.setAttribute('type', 'file'); if (meta.filetype === 'image') { console.log('filePicker image/*'); input.setAttribute('accept', 'image/*'); } input.onchange = function () { var file = this.files[0]; var reader = new FileReader(); reader.onload = function () { var id = 'blobid' + (new Date()).getTime(); var blobCache = tinymce.activeEditor.editorUpload.blobCache; var base64 = reader.result.split(',')[1]; var blobInfo = blobCache.create(id, file, base64); blobCache.add(blobInfo); let formData = new FormData(); formData.append("files", file); var authToken = localStorage.getItem('authToken'); $.ajax({ type: 'POST', url: '/api/FileUpload/Post', data: formData, cache: false, contentType: false, processData: false, headers: { 'Authorization': 'Bearer ' + authToken }, success: function (result) { console.log('filePicker result', result); cb(result.vstr_ImageUrl, { title: file.name, width: '100%', height: 'auto' }); }, error: function (xhr, status, error) { console.log('filePicker xhr', xhr); console.log('filePicker status', status); console.log('filePicker error', error); } }); }; reader.readAsDataURL(file); }; input.click(); } function initializeWordCloudCanvas(ContainerID, pobj_ListResults, pbln_IsSentence) { var canvas = document.getElementById(ContainerID); if (typeof (canvas) != 'undefined' && canvas != null && $('.wordcloud').length > 0) { // Exists. canvas.width = $('.wordcloud').width(); canvas.height = canvas.width * 0.5; var maxWeight = 0; for (let i = 0; i < pobj_ListResults.length; i++) { if (pobj_ListResults[i][1] > maxWeight) { maxWeight = pobj_ListResults[i][1]; } } var options = { list: pobj_ListResults, gridSize: Math.round(18 * canvas.width / 1024), weightFactor: function (size) { var ratioWidth = canvas.width / 1024; var percentSize = size; if (pobj_ListResults.length > 0) { percentSize = size / (pobj_ListResults.length); } if (percentSize < 0.08) { percentSize = 0.08; } if (pbln_IsSentence == "True") { if (pobj_ListResults.length <= 3) { return percentSize * 100 * (ratioWidth); } return percentSize * 100 * (ratioWidth * 5) / 2; } if (pobj_ListResults.length == 1) { return percentSize * 100 * ratioWidth; } else if (pobj_ListResults.length <= 3) { return percentSize * 100 * (ratioWidth * 4) / 2; } return percentSize * 100 * (ratioWidth * 5); }, fontFamily: 'OxygenLight', wait: 50, drawOutOfBound: true, shrinkToFit: true, color: function (word, weight, fontSize) { return (weight >= maxWeight) ? '#ffaa00' : '#232323'; }, rotateRatio: 0, }; WordCloud(canvas, options); } } var htmlEditorWebPageBlocks = [ { category: 'Éléments', id: 'text', label: 'Zone de texte', media: '', content: { type: 'text' }, activate: true }, { category: 'Éléments', id: 'image', label: 'Image', media: '', content: { type: 'image' }, activate: true, }, { category: 'Éléments', id: 'link', label: 'Lien de navigation', media: '', content: { type: 'link' }, }, { category: 'Éléments', id: 'video', label: 'Vidéo', media: '', content: { type: 'video' }, }, { category: 'Éléments', id: 'map', label: 'Carte', media: '', content: { type: 'map' }, }, { category: 'Blocs de contenu', id: 'content1', label: 'Bloc de contenu 1', media: '', content: { type: 'content1' }, }, { category: 'Blocs de contenu', id: 'content2', label: 'Bloc de contenu 2', media: '', content: { type: 'content2' }, }, { category: 'Blocs de contenu', id: 'content3', label: 'Bloc de contenu 3', media: '', content: { type: 'content3' }, }, { category: 'Blocs de contenu', id: 'content4', label: 'Bloc de contenu 4', media: '', content: { type: 'content4' }, }, { category: 'Blocs de contenu', id: 'content5', label: 'Bloc de contenu 5', media: '', content: { type: 'content5' }, }, { category: 'Blocs de contenu', id: 'content6', label: 'Bloc de contenu 6', media: '', content: { type: 'content6' }, }, ]; var htmlEditorMailBlocks = [ { category: 'Éléments', id: 'text', label: 'Zone de texte', media: '', content: { type: 'text' }, activate: true }, { category: 'Éléments', id: 'mailButton', label: 'Bouton', media: '', content: { type: 'mailButton' }, activate: true }, { category: 'Éléments', id: 'image', label: 'Image', media: '', content: { type: 'image' }, activate: true, }, { category: 'Éléments', id: 'link', label: 'Lien de navigation', media: '', content: { type: 'link' }, activate: true }, ]; var htmlEditorMergedFieldBlock = { category: 'Éléments', id: 'merged-field', label: 'Champs de fusion', media: '', content: { type: 'merged-field' }, select: true, activate: true, }; var htmlEditorMergedLinkBlock = { category: 'Éléments', id: 'merged-link', label: 'Lien de fusion', media: '', content: { type: 'merged-link' }, select: true, activate: true, }; function InitLink(component) { // Récupérez les valeurs mises à jour depuis les traits var text = component.getTrait('text').attributes.value; var href = component.getTrait('href').attributes.value; var title = component.getTrait('title').attributes.value; if (!text) { component.getTrait('text').attributes.value = text = 'Texte du lien'; } if (!href) { component.getTrait('href').attributes.value = href = 'https://agorabox.fr'; } if (!title) { component.getTrait('title').attributes.value = title = 'Titre du lien'; } // Mettez à jour le contenu du composant avec les nouvelles valeurs return ` ${text} `; } function InitMailButton(component) { // Récupérez les valeurs mises à jour depuis les traits var text = component.getTrait('text').attributes.value; var href = component.getTrait('href').attributes.value; var title = component.getTrait('title').attributes.value; var textColor = component.getTrait('color').attributes.value; var bgColor = component.getTrait('background-color').attributes.value; if (!text) { component.getTrait('text').attributes.value = text = 'Texte du bouton'; } if (!href) { component.getTrait('href').attributes.value = href = 'https://agorabox.fr'; } if (!title) { component.getTrait('title').attributes.value = title = 'Titre du bouton'; } if (!textColor) { component.getTrait('color').attributes.value = textColor = '#FFFFFF'; } if (!bgColor) { component.getTrait('background-color').attributes.value = bgColor = '#313131'; } // Mettez à jour le contenu du composant avec les nouvelles valeurs return `
${text}
`; } function addPayPalScript(clientId) { var script = document.createElement('script'); script.src = `https://www.paypal.com/sdk/js?client-id=${clientId}`; script.onload = function () { // Initialiser le bouton PayPal ici, si nécessaire }; document.head.appendChild(script); } window.browserInterop = { getTimezone: function () { return Intl.DateTimeFormat().resolvedOptions().timeZone; } }; window.AgoraShared = window.AgoraShared || {}; AgoraShared.dbManager = AgoraShared.dbManager || {}; AgoraShared.dbManager.isIndexedDBSupported = function () { // Vérifie si IndexedDB est supporté par le navigateur return 'indexedDB' in window; }; AgoraShared.dbManager = { ...AgoraShared.dbManager, // On conserve les fonctions existantes // Ouvre la base de données et retourne une promesse avec la base de données ouverte openDB: function (dbName, version, stores) { return new Promise((resolve, reject) => { let request = indexedDB.open(dbName, version); request.onupgradeneeded = function (event) { let db = event.target.result; stores.forEach(store => { if (!db.objectStoreNames.contains(store.name)) { let objectStore = db.createObjectStore(store.name, { keyPath: store.keyPath }); if (store.indices) { store.indices.forEach(index => { objectStore.createIndex(index.name, index.keyPath, { unique: index.unique }); }); } } }); }; request.onsuccess = function (event) { resolve(event.target.result); }; request.onerror = function (event) { reject("Erreur lors de l'ouverture d'IndexedDB: " + event.target.errorCode); }; }); }, // Ajoute ou met à jour un élément dans le store addOrUpdate: function (dbName, storeName, obj) { return new Promise((resolve, reject) => { this.openDB(dbName).then(db => { let transaction = db.transaction(storeName, "readwrite"); let store = transaction.objectStore(storeName); let request = store.put(obj); request.onsuccess = () => resolve(); request.onerror = (event) => reject("Erreur lors de l'ajout ou mise à jour de l'objet: " + event.target.errorCode); }).catch(error => reject(error)); }); }, // Récupère un élément depuis le store par clé get: function (dbName, storeName, key) { return new Promise((resolve, reject) => { this.openDB(dbName).then(db => { let transaction = db.transaction(storeName, "readonly"); let store = transaction.objectStore(storeName); let request = store.get(key); request.onsuccess = (event) => resolve(event.target.result); request.onerror = (event) => reject("Erreur lors de la récupération de l'objet: " + event.target.errorCode); }).catch(error => reject(error)); }); }, // Récupère tous les éléments depuis le store getAll: function (dbName, storeName) { return new Promise((resolve, reject) => { this.openDB(dbName).then(db => { let transaction = db.transaction(storeName, "readonly"); let store = transaction.objectStore(storeName); let request = store.getAll(); request.onsuccess = (event) => resolve(event.target.result); request.onerror = (event) => reject("Erreur lors de la récupération des objets: " + event.target.errorCode); }).catch(error => reject(error)); }); }, // Supprime un élément depuis le store par clé delete: function (dbName, storeName, key) { return new Promise((resolve, reject) => { this.openDB(dbName).then(db => { let transaction = db.transaction(storeName, "readwrite"); let store = transaction.objectStore(storeName); let request = store.delete(key); request.onsuccess = () => resolve(); request.onerror = (event) => reject("Erreur lors de la suppression de l'objet: " + event.target.errorCode); }).catch(error => reject(error)); }); }, // Nettoie tous les éléments d'un store clearStore: function (dbName, storeName) { return new Promise((resolve, reject) => { this.openDB(dbName).then(db => { let transaction = db.transaction(storeName, "readwrite"); let store = transaction.objectStore(storeName); let request = store.clear(); request.onsuccess = () => resolve(); request.onerror = (event) => reject("Erreur lors du nettoyage du store: " + event.target.errorCode); }).catch(error => reject(error)); }); }, // Vérifie si IndexedDB est supporté par le navigateur isSupported: function () { return !!window.indexedDB; } }; var htmlLoaderDiv = `
Chargement...
`; var htmlLoaderDiv = `
Chargement...
`; var htmlLoaderCSS = `.loader-wrapper { position: fixed; top: 0px !important; left: 0; width: 100% !important; height: 100% !important; background-color: #FFF; z-index: 99999; display: flex; flex-direction: column; justify-content: center; align-items: center; opacity: 0.75; } .loader-wrapper-bg { margin: 0 auto; text-align: center; position: relative; width: 90px; height: 90px; display: block; } .loader-wrapper-bg-spinner { position: absolute; width: 90px; height: 90px; animation: lds-rotate 2s ease-in-out infinite; } .loader-wrapper-bg-spinner-bubble { position: absolute; width: 16px; height: 16px; background: #FA0; border-radius: 50%; top: 0px; left: 0px; animation: lds-scale 2s linear infinite; } .loader-wrapper-bg-spinner:nth-child(1) { animation: lds-rotate-1 2s ease-in-out infinite; } .loader-wrapper-bg-spinner:nth-child(1) div { animation-delay: 0s; animation: lds-scale-1 1.5s ease-in-out infinite; } .loader-wrapper-bg-spinner:nth-child(2) { animation: lds-rotate-2 2.5s linear infinite; } .loader-wrapper-bg-spinner:nth-child(2) div { background: #000; animation-delay: -0.1s; animation: lds-scale-2 3s linear infinite; } .loader-wrapper-bg-spinner:nth-child(3) { animation: lds-rotate-3 1.5s linear infinite; } .loader-wrapper-bg-spinner:nth-child(3) div { animation-delay: -0.2s; animation: lds-scale 1s ease-in-out infinite; } .loader-wrapper-bg-spinner:nth-child(4) { animation: lds-rotate-4 2.5s ease-in-out infinite; } .loader-wrapper-bg-spinner:nth-child(4) div { background: #000; animation-delay: -0.3s; animation: lds-scale-1 2s linear infinite; } .loader-wrapper-bg-spinner:nth-child(5) { animation: lds-rotate-5 2.5s ease-in-out infinite; } .loader-wrapper-bg-spinner:nth-child(5) div { animation-delay: -0.4s; animation: lds-scale-2 3s ease-in-out infinite; } .loader-wrapper-bg-spinner:nth-child(6) { animation: lds-rotate-6 1.5s linear infinite; } .loader-wrapper-bg-spinner:nth-child(6) div { background: #000; animation-delay: -0.5s; animation: lds-scale 1.2s linear infinite; } .loader-wrapper-bg-spinner:nth-child(7) { animation: lds-rotate-7 2.5s ease-in-out infinite; } .loader-wrapper-bg-spinner:nth-child(7) div { animation-delay: -0.6s; animation: lds-scale-1 1.2s linear infinite; } .loader-wrapper-bg-spinner:nth-child(8) { animation: lds-rotate-8 1.8s ease-in-out infinite; } .loader-wrapper-bg-spinner:nth-child(8) div { background: #000; animation-delay: -0.7s; animation: lds-scale-2 1.2s linear infinite; } .loader-wrapper-text { padding-top: 30px; font-weight: bold; font-size: 1.2em; } @keyframes lds-scale { 0%, 20%, 80%, 100% { transform: scale(0.3); } 50% { transform: scale(1.5); } } @keyframes lds-scale-1 { 0%, 20%, 80%, 100% { transform: scale(1); } 50% { transform: scale(0.5); } } @keyframes lds-scale-2 { 0%, 80%, 100% { transform: scale(0.4); } 20%, 70% { transform: scale(1.1); } } @keyframes lds-rotate { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes lds-rotate-1 { 0% { transform: rotate(-45deg); } 100% { transform: rotate(315deg); } } @keyframes lds-rotate-2 { 0% { transform: rotate(-90deg); } 100% { transform: rotate(270deg); } } @keyframes lds-rotate-3 { 0% { transform: rotate(-135deg); } 100% { transform: rotate(225deg); } } @keyframes lds-rotate-4 { 0% { transform: rotate(-180deg); } 100% { transform: rotate(180deg); } } @keyframes lds-rotate-5 { 0% { transform: rotate(-225deg); } 100% { transform: rotate(135deg); } } @keyframes lds-rotate-6 { 0% { transform: rotate(-270deg); } 100% { transform: rotate(90deg); } } @keyframes lds-rotate-7 { 0% { transform: rotate(-315deg); } 100% { transform: rotate(45deg); } } @keyframes lds-rotate-8 { 0% { transform: rotate(-360deg); } 100% { transform: rotate(0deg); } }`;