comparison .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
comparison
equal deleted inserted replaced
-1:000000000000 0:78edf6b517a0
1 document.addEventListener( "DOMContentLoaded", function( event ) {
2
3 function _( str ) {
4 return __( str, "template.mod.php" );
5 }
6
7 // Edit file
8 document.querySelectorAll( "#template .template-files .file" ).forEach( function( button ) {
9 button.addEventListener( "click", function( e ) {
10 let file = this.innerText;
11 // get file from server
12 api( { fn: "get_template_file", file: file }, function( r ) {
13 if ( r.ok == "true" ) {
14 document.querySelector( ".template-editor-title" ).innerText = file;
15 document.querySelector( ".template-editor > textarea" ).value = r.file;
16
17 // Show Editor
18 document.querySelector( ".template-editor-bg" ).classList.remove( "hidden" );
19 document.body.classList.add( "editor" ); // for notifications
20
21 let ext = file.match( /\.[^\.]+$/, "" );
22 let aext = {
23 ".php" : "application/x-httpd-php",
24 ".html" : "application/x-httpd-php",
25 ".css" : "text/css"
26 }
27 let atags = {
28 ".php" : "php",
29 ".html" : "html",
30 ".css" : "css"
31 }
32
33 // Отображаем подходящие теги, остальные прячем
34 document.querySelectorAll( `#template .template-editor-bg .snip-grid > *` ).forEach( function( el ) {
35 if ( el.classList.contains( atags[ext] ) ) {
36 el.classList.remove( "hidden" );
37 } else {
38 el.classList.add( "hidden" );
39 }
40 } );
41
42 // Подключаем редактор Codemirror функцией расположенной в admin.js
43 codemirror_connect( "#template .template-editor > textarea", "cmt", { mode: aext[ext] } );
44
45 // track changes
46 document.querySelector( ".close-template-button" ).setAttribute( "data-changed", "false" );
47 cmt.on( "change", function( cmt, change ) {
48 document.querySelector( ".close-template-button" ).setAttribute( "data-changed", "true" );
49 document.querySelector( ".template-editor-grid" ).setAttribute( "data-changed", "true" );
50 } );
51
52 // set cursor to editor
53 cmt.focus();
54
55 // Save Teplate Ctrl+S
56 document.querySelector( "body" ).addEventListener( "keydown", CtrlS );
57
58 document.querySelector( ".template-editor-grid" ).setAttribute( "data-changed", "false" );
59 }
60 } );
61 } );
62 } );
63
64 // Для сниппетов
65 document.querySelectorAll( "#template .snip-grid [data-type='snip']" ).forEach( function( btn ) {
66 btn.addEventListener( "click", function( e ) {
67 let text = this.getAttribute( "data-text" );
68 let cm = window["cmt"];
69 if ( cm ) {
70 let otag = this.getAttribute( "data-otag" );
71 let ctag = this.getAttribute( "data-ctag" );
72 let selections = cm.getSelections();
73 let replacements = [];
74 for ( let i = 0; i < selections.length; i++ ) {
75 replacements[i] = otag + selections[i] + ctag;
76 }
77 cm.replaceSelections( replacements );
78 // с курсорами пока не понятен алгоритм
79 /*
80 selections = cm.listSelections();
81 let shift = +this.getAttribute( "data-len" );
82 if ( shift != 0 ) {
83 for ( let i = 0; i < selections.length; i++ ) {
84 selections[i].head.ch += shift;
85 selections[i].anchor.ch += shift;
86 }
87 }
88 */
89 cm.focus();
90 cm.refresh();
91 }
92 } );
93 } );
94
95 // Close Editor
96 document.querySelectorAll( ".close-template-button" ).forEach( function( button ) {
97 button.onclick = function( e ) {
98 document.querySelector( "body" ).removeEventListener( "keydown", CtrlS );
99 // detach
100 if ( window.cmt !== undefined ) {
101 if ( this.getAttribute( "data-changed" ) === "true" ) {
102 if ( confirm( _( "confirm_save" ) ) ) {
103 document.querySelector( ".save-template-button" ).setAttribute( "data-close", "true" );
104 document.querySelector( ".save-template-button" ).click();
105 return;
106 }
107 }
108 window.cmt.toTextArea();
109 window.cmt = null;
110 }
111 // hide editor
112 document.querySelector( ".template-editor-bg" ).classList.add( "hidden" );
113 document.body.classList.remove( "template_editor" );
114 //window.prevent_reload = false;
115 };
116 } );
117
118 // Save File
119 document.querySelectorAll( ".save-template-button" ).forEach( function( button ) {
120 button.onclick = function( e ) {
121 window.cmt.save(); // drop changes to textarea
122 let data = {
123 fn: "save_template_file",
124 file: document.querySelector( ".template-editor-title" ).innerText,
125 content: document.querySelector( ".template-editor > textarea" ).value
126 }
127 api( data, function( r ) {
128 if ( r.info_text ) {
129 notify( r.info_text, r.info_class, r.info_time );
130 }
131 if ( r.ok == "true" ) {
132 //?
133 document.querySelector( ".close-template-button" ).setAttribute( "data-changed", "false" );
134 // hide changed indicator
135 document.querySelector( ".template-editor-grid" ).setAttribute( "data-changed", "false" );
136 // highlight save button
137 document.querySelector( ".save-template-button" ).classList.add( "saved" );
138 setTimeout( function() {
139 document.querySelector( ".save-template-button" ).classList.remove( "saved" );
140 }, 1000 );
141 // close editor after save only if ok
142 if ( document.querySelector( ".save-template-button" ).getAttribute( "data-close" ) === "true" ) {
143 document.querySelector( ".save-template-button" ).setAttribute( "data-close", "false" );
144 document.querySelector( ".close-template-button" ).click();
145 }
146 }
147 } );
148 };
149 } );
150
151 function CtrlS( e ) {
152 // ы and і - fix for librewolf
153 if ( ( e.code == "KeyS" || e.key == "ы" || e.key == "і" ) && e.ctrlKey == true ) {
154 e.preventDefault(); // don't save page
155 if ( window.location.hash == "#template" ) {
156 document.querySelector( ".save-template-button" ).click();
157 }
158 }
159 }
160
161 // Install template (upload template)
162 let input = document.querySelector( "#template-upload" );
163 input.addEventListener( "change", async function( e ) {
164 const formData = new FormData();
165 formData.append( "fn", "install_template" );
166 for ( let i = 0; i < input.files.length; i++ ) {
167 formData.append( "myfile[]", input.files[i] );
168 }
169 try {
170 const response = await fetch( cms.api, { method: "POST", body: formData } );
171 const r = await response.json();
172 input.value = ""; // chrome fix
173 if ( r.info_text ) {
174 notify( r.info_text, r.info_class, r.info_time );
175 setTimeout( function() {
176 window.location.reload( true );
177 }, r.info_time );
178 }
179 } catch ( error ) {
180 console.error( "Error:", error );
181 }
182 } );
183
184 // prevent hide cursor when window resize
185 window.addEventListener( "resize", function() {
186 if ( window.cmt ) {
187 let cursor = window.cmt.getCursor();
188 window.cmt.scrollIntoView( { line:cursor.line, ch:cursor.ch } );
189 }
190 } );
191
192 // Select
193 document.querySelectorAll( "#template .field-select" ).forEach( function( select ) {
194 select.addEventListener( "click", function( e ) {
195 e.stopPropagation();
196 this.parentElement.classList.toggle( "open" );
197
198 // это можно убрать если переставить стили на родителя
199 select.nextElementSibling.classList.toggle( "open" );
200 } );
201 } );
202 // Option
203 document.querySelectorAll( "#template .field-options .option" ).forEach( function( option ) {
204 option.addEventListener( "click", function( e ) {
205 let input = this.closest( ".template-select-grid" ).querySelector( ".field-select" );
206 input.querySelector( ".value" ).innerText = this.innerText;
207 document.querySelector( "#template input[name='template']" ).value = this.innerText;
208 } );
209 } );
210 // Select
211 // Закрытие выпадающих списков при кликах вне их, а так же по ним
212 document.body.addEventListener( "click", function( e ) {
213 document.querySelectorAll( "#template .template-select-grid" ).forEach( function( list ) {
214 list.classList.remove( "open" );
215 } );
216
217 // это можно убрать если переставить стили на родителя
218 document.querySelectorAll( "#template .field-options" ).forEach( function( list ) {
219 list.classList.remove( "open" );
220 } );
221 } );
222
223 } );