Mercurial
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 } ); |