Mercurial
diff .cms/js/template.js @ 0:78edf6b517a0 draft
24.10
author | Coffee CMS <info@coffee-cms.ru> |
---|---|
date | Fri, 11 Oct 2024 22:40:23 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.cms/js/template.js Fri Oct 11 22:40:23 2024 +0000 @@ -0,0 +1,223 @@ +document.addEventListener( "DOMContentLoaded", function( event ) { + + function _( str ) { + return __( str, "template.mod.php" ); + } + + // Edit file + document.querySelectorAll( "#template .template-files .file" ).forEach( function( button ) { + button.addEventListener( "click", function( e ) { + let file = this.innerText; + // get file from server + api( { fn: "get_template_file", file: file }, function( r ) { + if ( r.ok == "true" ) { + document.querySelector( ".template-editor-title" ).innerText = file; + document.querySelector( ".template-editor > textarea" ).value = r.file; + + // Show Editor + document.querySelector( ".template-editor-bg" ).classList.remove( "hidden" ); + document.body.classList.add( "editor" ); // for notifications + + let ext = file.match( /\.[^\.]+$/, "" ); + let aext = { + ".php" : "application/x-httpd-php", + ".html" : "application/x-httpd-php", + ".css" : "text/css" + } + let atags = { + ".php" : "php", + ".html" : "html", + ".css" : "css" + } + + // Отображаем подходящие теги, остальные прячем + document.querySelectorAll( `#template .template-editor-bg .snip-grid > *` ).forEach( function( el ) { + if ( el.classList.contains( atags[ext] ) ) { + el.classList.remove( "hidden" ); + } else { + el.classList.add( "hidden" ); + } + } ); + + // Подключаем редактор Codemirror функцией расположенной в admin.js + codemirror_connect( "#template .template-editor > textarea", "cmt", { mode: aext[ext] } ); + + // track changes + document.querySelector( ".close-template-button" ).setAttribute( "data-changed", "false" ); + cmt.on( "change", function( cmt, change ) { + document.querySelector( ".close-template-button" ).setAttribute( "data-changed", "true" ); + document.querySelector( ".template-editor-grid" ).setAttribute( "data-changed", "true" ); + } ); + + // set cursor to editor + cmt.focus(); + + // Save Teplate Ctrl+S + document.querySelector( "body" ).addEventListener( "keydown", CtrlS ); + + document.querySelector( ".template-editor-grid" ).setAttribute( "data-changed", "false" ); + } + } ); + } ); + } ); + + // Для сниппетов + document.querySelectorAll( "#template .snip-grid [data-type='snip']" ).forEach( function( btn ) { + btn.addEventListener( "click", function( e ) { + let text = this.getAttribute( "data-text" ); + let cm = window["cmt"]; + if ( cm ) { + let otag = this.getAttribute( "data-otag" ); + let ctag = this.getAttribute( "data-ctag" ); + let selections = cm.getSelections(); + let replacements = []; + for ( let i = 0; i < selections.length; i++ ) { + replacements[i] = otag + selections[i] + ctag; + } + cm.replaceSelections( replacements ); + // с курсорами пока не понятен алгоритм + /* + selections = cm.listSelections(); + let shift = +this.getAttribute( "data-len" ); + if ( shift != 0 ) { + for ( let i = 0; i < selections.length; i++ ) { + selections[i].head.ch += shift; + selections[i].anchor.ch += shift; + } + } + */ + cm.focus(); + cm.refresh(); + } + } ); + } ); + + // Close Editor + document.querySelectorAll( ".close-template-button" ).forEach( function( button ) { + button.onclick = function( e ) { + document.querySelector( "body" ).removeEventListener( "keydown", CtrlS ); + // detach + if ( window.cmt !== undefined ) { + if ( this.getAttribute( "data-changed" ) === "true" ) { + if ( confirm( _( "confirm_save" ) ) ) { + document.querySelector( ".save-template-button" ).setAttribute( "data-close", "true" ); + document.querySelector( ".save-template-button" ).click(); + return; + } + } + window.cmt.toTextArea(); + window.cmt = null; + } + // hide editor + document.querySelector( ".template-editor-bg" ).classList.add( "hidden" ); + document.body.classList.remove( "template_editor" ); + //window.prevent_reload = false; + }; + } ); + + // Save File + document.querySelectorAll( ".save-template-button" ).forEach( function( button ) { + button.onclick = function( e ) { + window.cmt.save(); // drop changes to textarea + let data = { + fn: "save_template_file", + file: document.querySelector( ".template-editor-title" ).innerText, + content: document.querySelector( ".template-editor > textarea" ).value + } + api( data, function( r ) { + if ( r.info_text ) { + notify( r.info_text, r.info_class, r.info_time ); + } + if ( r.ok == "true" ) { + //? + document.querySelector( ".close-template-button" ).setAttribute( "data-changed", "false" ); + // hide changed indicator + document.querySelector( ".template-editor-grid" ).setAttribute( "data-changed", "false" ); + // highlight save button + document.querySelector( ".save-template-button" ).classList.add( "saved" ); + setTimeout( function() { + document.querySelector( ".save-template-button" ).classList.remove( "saved" ); + }, 1000 ); + // close editor after save only if ok + if ( document.querySelector( ".save-template-button" ).getAttribute( "data-close" ) === "true" ) { + document.querySelector( ".save-template-button" ).setAttribute( "data-close", "false" ); + document.querySelector( ".close-template-button" ).click(); + } + } + } ); + }; + } ); + + function CtrlS( e ) { + // ы and і - fix for librewolf + if ( ( e.code == "KeyS" || e.key == "ы" || e.key == "і" ) && e.ctrlKey == true ) { + e.preventDefault(); // don't save page + if ( window.location.hash == "#template" ) { + document.querySelector( ".save-template-button" ).click(); + } + } + } + + // Install template (upload template) + let input = document.querySelector( "#template-upload" ); + input.addEventListener( "change", async function( e ) { + const formData = new FormData(); + formData.append( "fn", "install_template" ); + for ( let i = 0; i < input.files.length; i++ ) { + formData.append( "myfile[]", input.files[i] ); + } + try { + const response = await fetch( cms.api, { method: "POST", body: formData } ); + const r = await response.json(); + input.value = ""; // chrome fix + if ( r.info_text ) { + notify( r.info_text, r.info_class, r.info_time ); + setTimeout( function() { + window.location.reload( true ); + }, r.info_time ); + } + } catch ( error ) { + console.error( "Error:", error ); + } + } ); + + // prevent hide cursor when window resize + window.addEventListener( "resize", function() { + if ( window.cmt ) { + let cursor = window.cmt.getCursor(); + window.cmt.scrollIntoView( { line:cursor.line, ch:cursor.ch } ); + } + } ); + + // Select + document.querySelectorAll( "#template .field-select" ).forEach( function( select ) { + select.addEventListener( "click", function( e ) { + e.stopPropagation(); + this.parentElement.classList.toggle( "open" ); + + // это можно убрать если переставить стили на родителя + select.nextElementSibling.classList.toggle( "open" ); + } ); + } ); + // Option + document.querySelectorAll( "#template .field-options .option" ).forEach( function( option ) { + option.addEventListener( "click", function( e ) { + let input = this.closest( ".template-select-grid" ).querySelector( ".field-select" ); + input.querySelector( ".value" ).innerText = this.innerText; + document.querySelector( "#template input[name='template']" ).value = this.innerText; + } ); + } ); + // Select + // Закрытие выпадающих списков при кликах вне их, а так же по ним + document.body.addEventListener( "click", function( e ) { + document.querySelectorAll( "#template .template-select-grid" ).forEach( function( list ) { + list.classList.remove( "open" ); + } ); + + // это можно убрать если переставить стили на родителя + document.querySelectorAll( "#template .field-options" ).forEach( function( list ) { + list.classList.remove( "open" ); + } ); + } ); + +} );