0
|
1 document.addEventListener( "DOMContentLoaded", function( event ) {
|
|
2
|
|
3 function _( str ) {
|
|
4 return __( str, "pages.mod.php" );
|
|
5 }
|
|
6
|
|
7 // Полностью этот скрипт отключить нельзя если включены Инструменты,
|
|
8 // поэтому нужна проверка
|
|
9 if ( document.querySelector( "#pages" ) ) {
|
|
10 api( { fn: "get_pages_list" }, set_pages_list );
|
|
11 }
|
|
12
|
|
13 function set_pages_list( r ) {
|
|
14
|
|
15 if ( ! document.querySelector( "#pages" ) ) return;
|
|
16
|
|
17 if ( r.no_database ) {
|
|
18 document.querySelector( "#pages .pages-grid" ).innerHTML = r.no_database;
|
|
19 return;
|
|
20 }
|
|
21
|
|
22 if ( r.overloaded ) {
|
|
23 let m = _( "server_overloaded_xxx" );
|
|
24 m = m.replace( "xxx", r.pages.length );
|
|
25 notify( m, "info-error", 5000 );
|
|
26 }
|
|
27
|
|
28 // Запоминаем результаты какого поиска мы получили
|
|
29 // Это нужно чтобы не загружать снова все страницы при создании новой
|
|
30 // не производить сброс поиска.
|
|
31 let pages_search = document.querySelector( "#pages .page-search" );
|
|
32 pages_search.setAttribute( "data-result-of", r.search );
|
|
33
|
|
34 let grid = document.querySelector( "#pages .pages-grid" );
|
|
35 let count = document.querySelector( "#pages .main-footer .count" );
|
|
36 let loaded = document.querySelector( "#pages .main-footer .loaded" );
|
|
37 if ( cms.clear_pages_list ) {
|
|
38 cms.clear_pages_list = false;
|
|
39 grid.innerHTML = "";
|
|
40 loaded.value = "0";
|
|
41 }
|
|
42
|
|
43 // Всего страниц в БД
|
|
44 count.innerText = r.count;
|
|
45
|
|
46 // При удалении страниц подгружаются последние и не нужно менять смещение у пейджера
|
|
47 if ( cms.dont_change_offset ) {
|
|
48 cms.dont_change_offset = false;
|
|
49 } else {
|
|
50 loaded.setAttribute( "data-offset", r.offset );
|
|
51 }
|
|
52
|
|
53 // insert pages
|
|
54 let start = Date.now();
|
|
55 for ( let i = 0; i < r.pages.length; i++ ) {
|
|
56 grid.insertAdjacentHTML( "beforeend", r.pages[i].html );
|
|
57 loaded.value = +loaded.value + 1;
|
|
58 let page = grid.querySelector( `[data-id="${r.pages[i].id}"]` );
|
|
59 set_controls( page );
|
|
60 if ( Date.now() - start > 1000 ) {
|
|
61 let m = _( "browser_overloaded_xxx" );
|
|
62 m = m.replace( "xxx", i + 1 );
|
|
63 m = m.replace( "nnn", r.pages.length );
|
|
64 notify( m, "info-error", 5000 );
|
|
65 break;
|
|
66 }
|
|
67 }
|
|
68
|
|
69 create_pager();
|
|
70
|
|
71 // При создании страницы было обнаружено что поиск не сброшен,
|
|
72 // поэтому была вызвана функция загрузки страниц с пустым поиском
|
|
73 // и пришло время создать новую страницу
|
|
74 if ( cms.create_page_fn ) {
|
|
75 cms.create_page_fn();
|
|
76 cms.create_page_fn = null;
|
|
77 }
|
|
78
|
|
79 }
|
|
80
|
|
81 function create_pager() {
|
|
82 let loaded = document.querySelector( "#pages .main-footer .loaded" );
|
|
83 let offset = parseInt( loaded.getAttribute( "data-offset" ) );
|
|
84 let count = parseInt( document.querySelector( "#pages .main-footer .count" ).innerText );
|
|
85 if ( count === 0 ) { count++; }
|
|
86 let cookie_pp = get_cookie( "pages_pager" );
|
|
87 let pages = Math.ceil( count / cookie_pp );
|
|
88 let pager = document.querySelector( "#pages .main-footer .pager" );
|
|
89 pager.innerHTML = "";
|
|
90 if ( pages > 1 ) {
|
|
91 for ( let i = 1; i <= pages; i++ ) {
|
|
92 let p = document.createElement( "div" );
|
|
93 p.innerText = i;
|
|
94 p.setAttribute( "data-offset", ( i - 1 ) * cookie_pp );
|
|
95 pager.appendChild( p );
|
|
96 }
|
|
97 pager.querySelector( `[data-offset="${offset}"]` ).classList.add( "active" );
|
|
98 pager.childNodes.forEach( function( el ) {
|
|
99 el.addEventListener( "click", function( e ) {
|
|
100 let offset = this.getAttribute( "data-offset" );
|
|
101 let search = document.querySelector( "#pages .page-search" ).value;
|
|
102 let data = {
|
|
103 fn: "get_pages_list",
|
|
104 offset: offset,
|
|
105 search: search
|
|
106 }
|
|
107 document.querySelector( "#pages .main-main" ).scrollTop = 0;
|
|
108 cms.clear_pages_list = true;
|
|
109 api( data, set_pages_list );
|
|
110 } );
|
|
111 } );
|
|
112 // scroll
|
|
113 pager.onmousedown = function( e ) {
|
|
114 let pageX = 0;
|
|
115 let pageY0 = 0;
|
|
116
|
|
117 document.onmousemove = function( e ) {
|
|
118 if ( pageX !== 0 ) {
|
|
119 pager.scrollLeft = pager.scrollLeft + ( pageX - e.pageX );
|
|
120 }
|
|
121 pageX = e.pageX;
|
|
122 // fix for google chrome
|
|
123 if ( pageY0 === 0 ) {
|
|
124 pageY0 = e.pageY;
|
|
125 }
|
|
126 if ( Math.abs( pageY0 - e.pageY ) > 64 ) {
|
|
127 const event = new Event( "mouseup" );
|
|
128 pager.dispatchEvent( event );
|
|
129 }
|
|
130 }
|
|
131
|
|
132 // end drag
|
|
133 pager.onmouseup = function() {
|
|
134 document.onmousemove = null;
|
|
135 pager.onmouseup = null;
|
|
136 }
|
|
137
|
|
138 // disable browser drag
|
|
139 pager.ondragstart = function() {
|
|
140 return false;
|
|
141 }
|
|
142 }
|
|
143 }
|
|
144 }
|
|
145
|
|
146 // pager counter
|
|
147 let pager_counter = document.querySelector( "#pages .main-footer input" );
|
|
148 if ( pager_counter ) pager_counter.addEventListener( "keydown", function( e ) {
|
|
149 if ( e.keyCode === 13 ) { // keyCode work on mobile
|
|
150 let p = document.querySelector( "#pages .main-footer input" ).value;
|
|
151 set_cookie_expires( "pages_pager", p );
|
|
152 cms.clear_pages_list = true;
|
|
153 api( { fn: "get_pages_list", search: document.querySelector( "#pages .page-search" ).value }, set_pages_list );
|
|
154 }
|
|
155 } );
|
|
156
|
|
157 function set_controls( selector ) {
|
|
158
|
|
159 // Open properties
|
|
160 selector.querySelectorAll( ".page-prop-btn" ).forEach( function( button ) {
|
|
161 button.addEventListener( "click", function( e ) {
|
|
162 let id = this.closest( "[data-id]" ).getAttribute( "data-id" );
|
|
163 document.querySelector( `#pages .pages-grid [data-id="${id}"]` ).classList.toggle( "open" );
|
|
164 } );
|
|
165 } );
|
|
166
|
|
167 // Save properties
|
|
168 selector.querySelectorAll( ".page-prop-save-btn" ).forEach( function( button ) {
|
|
169 button.addEventListener( "click", function( e ) {
|
|
170 let id = this.closest( "[data-id]" ).getAttribute( "data-id" );
|
|
171 let item = document.querySelector( `#pages .pages-grid [data-id="${id}"] ` );
|
|
172 let data = {
|
|
173 fn: "save_prop",
|
|
174 id: id,
|
|
175 title: item.querySelector( '[name="title"]' ).value,
|
|
176 seo_title: item.querySelector( '[name="seo_title"]' ).value,
|
|
177 url: item.querySelector( '[name="url"]' ).value,
|
|
178 date: item.querySelector( '[name="date"]' ).value,
|
|
179 time: item.querySelector( '[name="time"]' ).value,
|
|
180 template: item.querySelector( '.template-select-grid .field-select' ).getAttribute( "data-template" ),
|
|
181 old_template: item.querySelector( '.template-select-grid .field-select' ).getAttribute( "data-old-template" ),
|
|
182 description: item.querySelector( '[name="description"]' ).value,
|
|
183 tags: item.querySelector( '[name="tags"]' ).value,
|
|
184 }
|
|
185 api( data, function( r ) {
|
|
186 if ( r.ok == "false" ) { // FIXME: never fire
|
|
187 notify( r.info_text, r.info_class, 5000 );
|
|
188 }
|
|
189 if ( r.ok == "true" ) {
|
|
190
|
|
191 // Update Title, URL and Date
|
|
192 item.querySelector( ".page-name" ).innerHTML = r.title;
|
|
193 item.querySelector( ".page-name" ).setAttribute( "href", r.base_path + r.url );
|
|
194 update_home();
|
|
195 let url_el = item.querySelector( "[name=url]" );
|
|
196 if ( url_el.value != r.url ) {
|
|
197 notify( _( "url_changed" ), "info-error", 5000 );
|
|
198 }
|
|
199 url_el.value = r.url;
|
|
200 let date = item.querySelector( ".page-date" );
|
|
201 date.innerHTML = r.created;
|
|
202 if ( r.planned ) {
|
|
203 date.classList.add( "future" );
|
|
204 } else {
|
|
205 date.classList.remove( "future" );
|
|
206 }
|
|
207
|
|
208 // update old template
|
|
209 item.querySelector( '.template-select-grid .field-select' ).setAttribute( "data-old-template", data.template );
|
|
210
|
|
211 // edit marker
|
|
212 document.querySelectorAll( "#pages .pages-grid > div" ).forEach( function( el ) {
|
|
213 el.classList.remove( "last-edited" );
|
|
214 } );
|
|
215 setTimeout( function() {
|
|
216 item.classList.add( "last-edited" );
|
|
217 }, 200 );
|
|
218
|
|
219 // highlight save button
|
|
220 button.classList.add( "saved" );
|
|
221 setTimeout( function() {
|
|
222 button.classList.remove( "saved" );
|
|
223 }, 200 );
|
|
224
|
|
225 notify( r.info_text, r.info_class, 5000 );
|
|
226
|
|
227 // update event for menu
|
|
228 if ( r.update_menu == "true" ) {
|
|
229 let event = new Event( "update_menu" );
|
|
230 document.body.dispatchEvent( event );
|
|
231 }
|
|
232 }
|
|
233
|
|
234 } );
|
|
235 } );
|
|
236 } );
|
|
237
|
|
238 // Pin Page
|
|
239 selector.querySelectorAll( ".pin" ).forEach( function( pin ) {
|
|
240 pin.addEventListener( "click", function( e ) {
|
|
241 let box = this.closest( "[data-id]" );
|
|
242 let id = box.getAttribute( "data-id" );
|
|
243 let pin = box.getAttribute( "data-pin" );
|
|
244 if ( pin === "1" ) {
|
|
245 pin = "0";
|
|
246 } else {
|
|
247 pin = "1";
|
|
248 }
|
|
249 let data = {
|
|
250 fn: "page_pin",
|
|
251 id: id,
|
|
252 pin: pin
|
|
253 }
|
|
254 api( data, function( r ) {
|
|
255 if ( r.ok == "true" ) {
|
|
256 box.setAttribute( "data-pin", pin );
|
|
257 }
|
|
258 } );
|
|
259 } );
|
|
260 } );
|
|
261
|
|
262 // Publish Page
|
|
263 selector.querySelectorAll( ".published" ).forEach( function( pub ) {
|
|
264 pub.addEventListener( "click", function( e ) {
|
|
265 let box = this.closest( "[data-id]" );
|
|
266 let id = box.getAttribute( "data-id" );
|
|
267 let published = box.getAttribute( "data-published" );
|
|
268 if ( published === "1" ) {
|
|
269 published = "0";
|
|
270 } else {
|
|
271 published = "1";
|
|
272 }
|
|
273 let data = {
|
|
274 fn: "page_publish",
|
|
275 id: id,
|
|
276 published: published
|
|
277 }
|
|
278 api( data, function( r ) {
|
|
279 if ( r.ok == "true" ) {
|
|
280 box.setAttribute( "data-published", published );
|
|
281 if ( published == "1" ) {
|
|
282 pub.setAttribute( "title", _( "published" ) );
|
|
283 } else {
|
|
284 pub.setAttribute( "title", _( "unpublished" ) );
|
|
285 }
|
|
286 }
|
|
287 } );
|
|
288 } );
|
|
289 } );
|
|
290
|
|
291 // Edit page
|
|
292 selector.querySelectorAll( ".page-edit-btn" ).forEach( function( button ) {
|
|
293 button.addEventListener( "click", function( e ) {
|
|
294 button.classList.add( "loading" );
|
|
295 let id = this.closest( "[data-id]" ).getAttribute( "data-id" );
|
|
296 // get page from server
|
|
297 api( { fn: "get_page", id: id }, function( r ) {
|
|
298 button.classList.remove( "loading" );
|
|
299 if ( r.result == "ok" ) {
|
|
300 let title = document.querySelector( "#pages .page-editor-title" );
|
|
301 title.innerHTML = r.page.title;
|
|
302 title.setAttribute( "href", r.base_path + r.page.url );
|
|
303 let props = document.querySelector( "#pages .page-properties" );
|
|
304 props.querySelector( "input[name='title']" ).value = r.page.title;
|
|
305 props.querySelector( "input[name='url']" ).value = r.page.url;
|
|
306 props.querySelector( "input[name='seo_title']" ).value = r.page.seo_title;
|
|
307 props.querySelector( "textarea[name='description']" ).value = r.page.description;
|
|
308 props.querySelector( "textarea[name='tags']" ).value = r.page.tags;
|
|
309 props.querySelector( "input[name='date']" ).value = r.date;
|
|
310 props.querySelector( "input[name='time']" ).value = r.time;
|
|
311 let select = props.querySelector( ".template-select-grid" );
|
|
312 let options = select.querySelector( ".field-options" );
|
|
313 options.innerHTML = r.options;
|
|
314 let tpl = select.querySelector( ".field-select" );
|
|
315 tpl.setAttribute( "data-template", r.option );
|
|
316 tpl.setAttribute( "data-old-template", r.option );
|
|
317 tpl.querySelector( ".value" ).innerText = r.option_tr;
|
|
318 document.querySelector( "#pages .page-editor > textarea" ).value = r.page.text;
|
|
319 if ( r.page.modified != null ) { // prevent delete attribute
|
|
320 document.querySelector( "#pages .page-editor > textarea" ).setAttribute( "data-modified", r.page.modified );
|
|
321 }
|
|
322 document.querySelector( "#pages .save-page-button" ).setAttribute( "data-id", r.page.id );
|
|
323
|
|
324 options.querySelectorAll( ".option" ).forEach( function( option ) {
|
|
325 option.addEventListener( "click", click_select_option );
|
|
326 } );
|
|
327
|
|
328
|
|
329 // Images
|
|
330 document.querySelector( "#pages .link-file-tag" ).innerHTML = "";
|
|
331 document.querySelector( "#pages .del-uploaded-files" ).classList.add( "disabled" );
|
|
332 document.querySelector( "#pages .mediateka-files-grid" ).innerHTML = r.flist;
|
|
333 document.querySelectorAll( "#pages .mediateka-files-grid input[type=checkbox]" ).forEach( function( checkbox ) {
|
|
334 checkbox.addEventListener( "dblclick", img_check_dblclick );
|
|
335 checkbox.addEventListener( "change", img_rechecked );
|
|
336 } );
|
|
337 document.querySelectorAll( "#pages .file-block" ).forEach( function( block ) {
|
|
338 block.addEventListener( "click", img_click );
|
|
339 } );
|
|
340 document.querySelectorAll( "#pages .mediateka-files-grid img" ).forEach( function( img ) {
|
|
341 img.addEventListener( "dblclick", img_lbox );
|
|
342 } );
|
|
343
|
|
344 // Show Editor
|
|
345 document.querySelector( "#pages .page-editor-bg" ).classList.remove( "hidden" );
|
|
346 document.body.classList.add( "editor" ); // for notifications
|
|
347
|
|
348 // Connect Editor
|
|
349 codemirror_connect( "#pages .page-editor > textarea", "cm" );
|
|
350
|
|
351 // restore scroll and cursor position
|
|
352 let cursor = localStorage.getItem( "cursor_page_" + id );
|
|
353 if ( cursor ) {
|
|
354 cursor = JSON.parse( cursor );
|
|
355 window.cm.scrollTo( cursor.left, cursor.top );
|
|
356 window.cm.setCursor( { line:cursor.line, ch:cursor.ch } );
|
|
357 window.cm.refresh();
|
|
358 //window.cm.scrollIntoView( { line:cursor.line, ch:cursor.ch } ); // fix glitch
|
|
359 }
|
|
360
|
|
361 // track changes
|
|
362 document.querySelector( "#pages .close-page-button" ).setAttribute( "data-changed", "false" );
|
|
363 document.querySelector( "#pages .page-editor-grid" ).setAttribute( "data-changed", "false" );
|
|
364 cm.on( "change", function( cm, change ) {
|
|
365 document.querySelector( "#pages .close-page-button" ).setAttribute( "data-changed", "true" );
|
|
366 document.querySelector( "#pages .page-editor-grid" ).setAttribute( "data-changed", "true" );
|
|
367 } );
|
|
368 // save scroll and cursor position
|
|
369 [ "cursorActivity", "scroll" ].forEach( function( event ) {
|
|
370 cm.on( event, function() {
|
|
371 let cursor = window.cm.getCursor();
|
|
372 let scroll = window.cm.getScrollInfo();
|
|
373 localStorage.setItem( "cursor_page_" + id, JSON.stringify( { line:cursor.line, ch:cursor.ch, left: scroll.left, top: scroll.top } ) );
|
|
374 } );
|
|
375 } );
|
|
376
|
|
377 // set focus to editor
|
|
378 cm.focus();
|
|
379
|
|
380 // Save Page Ctrl+S
|
|
381 document.documentElement.addEventListener( "keydown", CtrlS );
|
|
382
|
|
383 // open tags panel
|
|
384 if ( document.documentElement.offsetWidth >= 1024 ) {
|
|
385 document.querySelector( "#pages .page-editor-grid" ).classList.add( "tags-opened" );
|
|
386 }
|
|
387 }
|
|
388 } );
|
|
389 } );
|
|
390 } );
|
|
391
|
|
392 // Select
|
|
393 selector.querySelectorAll( ".field-select" ).forEach( function( select ) {
|
|
394 select.addEventListener( "click", function( e ) {
|
|
395 e.stopPropagation();
|
|
396 this.parentElement.classList.toggle( "open" );
|
|
397
|
|
398 // это можно убрать если переставить стили на родителя
|
|
399 select.nextElementSibling.classList.toggle( "open" );
|
|
400 } );
|
|
401 } );
|
|
402 // Option шаблона
|
|
403 // вынесено в функцию потому что динамическое изменение
|
|
404 selector.querySelectorAll( ".field-options .option" ).forEach( function( option ) {
|
|
405 option.addEventListener( "click", click_select_option );
|
|
406 } );
|
|
407
|
|
408 // Транслитерация URL
|
|
409 selector.querySelectorAll( ".url-translit" ).forEach( function( btn ) {
|
|
410 btn.addEventListener( "click", function( e ) {
|
|
411 let url = selector.querySelector( "input[name='title']" ).value;
|
|
412 let tr_url = url_translit( url );
|
|
413 this.previousElementSibling.value = tr_url;
|
|
414 } );
|
|
415 } );
|
|
416
|
|
417 // Выбор всех страниц двойным кликом
|
|
418 let check = selector.querySelector( `:scope > input[type=checkbox]` );
|
|
419 if ( check ) check.addEventListener( "dblclick", function( e ) {
|
|
420 let stat = ! this.checked;
|
|
421 document.querySelectorAll( "#pages .pages-grid > div > input[type=checkbox]" ).forEach( function( chbox ) {
|
|
422 chbox.checked = stat;
|
|
423 } );
|
|
424 } );
|
|
425
|
|
426 }
|
|
427
|
|
428 // Клик по опции выбора шаблона
|
|
429 function click_select_option( e ) {
|
|
430 let select = this.closest( ".template-select-grid" );
|
|
431 let value = this.getAttribute( "value" );
|
|
432 select_switch_to( select, value );
|
|
433 }
|
|
434
|
|
435 //
|
|
436 function select_switch_to( select, value ) {
|
|
437 let field_select = select.querySelector( ".field-select" );
|
|
438 let old_value = field_select.getAttribute( "data-template" );
|
|
439 if ( old_value != value ) {
|
|
440 let old_name = field_select.innerText;
|
|
441 let field_options = select.querySelector( ".field-options" );
|
|
442 let option = field_options.querySelector( `[value="${value}"]` );
|
|
443 field_select.querySelector( ".value" ).innerText = option.innerText;
|
|
444 field_select.setAttribute( "data-template", value );
|
|
445 option.remove();
|
|
446 let option_html = `<div class=option value="${old_value}">${old_name}</div>`;
|
|
447 field_options.insertAdjacentHTML( "afterbegin", option_html );
|
|
448 field_options.firstChild.addEventListener( "click", click_select_option );
|
|
449 }
|
|
450 }
|
|
451
|
|
452 // Select for editor
|
|
453 document.querySelectorAll( ".page-properties .field-select" ).forEach( function( select ) {
|
|
454 select.addEventListener( "click", function( e ) {
|
|
455 e.stopPropagation();
|
|
456 this.parentElement.classList.toggle( "open" );
|
|
457 // это можно убрать если переставить стили на родителя
|
|
458 select.nextElementSibling.classList.toggle( "open" );
|
|
459 } );
|
|
460 } );
|
|
461
|
|
462 // Select
|
|
463 // Закрытие выпадающих списков при кликах вне их, а так же по ним
|
|
464 document.body.addEventListener( "click", function( e ) {
|
|
465 document.querySelectorAll( "#pages .template-select-grid" ).forEach( function( list ) {
|
|
466 list.classList.remove( "open" );
|
|
467 } );
|
|
468
|
|
469 // это можно убрать если переставить стили на родителя
|
|
470 document.querySelectorAll( "#pages .field-options" ).forEach( function( list ) {
|
|
471 list.classList.remove( "open" );
|
|
472 } );
|
|
473 } );
|
|
474
|
|
475 // Search page
|
|
476 let pages_search = document.querySelector( "#pages .page-search" );
|
|
477 if ( pages_search ) pages_search.addEventListener( "keydown", function( e ) {
|
|
478 if ( e.keyCode === 13 ) {
|
|
479 // сохраняем событие целиком чтобы ниже считать Shift, Ctrl, Alt
|
|
480 cms.search_event = e;
|
|
481 search_pages();
|
|
482 }
|
|
483 } );
|
|
484
|
|
485 let search_btn = document.querySelector( "#pages .page-search-button" );
|
|
486 if ( search_btn ) search_btn.addEventListener( "click", function( e ) {
|
|
487 // клик по кнопке не дает Ctrl, Shift, Alt, запишем это
|
|
488 cms.search_event = { "ctrlKey": false, "shiftKey": false, "altKey": false };
|
|
489 search_pages();
|
|
490 document.querySelector( "#pages .page-search" ).focus();
|
|
491 } );
|
|
492
|
|
493 function search_pages() {
|
|
494 let search_string = document.querySelector( "#pages .page-search" ).value;
|
|
495 let data = {
|
|
496 fn: "get_pages_list",
|
|
497 search: search_string,
|
|
498 Ctrl: cms.search_event.ctrlKey,
|
|
499 Shift: cms.search_event.shiftKey,
|
|
500 Alt: cms.search_event.altKey,
|
|
501 };
|
|
502 cms.clear_pages_list = true;
|
|
503 api( data, set_pages_list );
|
|
504 }
|
|
505
|
|
506 // Reset Search
|
|
507 let reset_btn = document.querySelector( "#pages .reset" );
|
|
508 if ( reset_btn ) reset_btn.addEventListener( "click", function() {
|
|
509 document.querySelector( "#pages .page-search" ).value = "";
|
|
510 document.querySelector( "#pages .page-search-button" ).click();
|
|
511 } );
|
|
512
|
|
513 // Delete pages
|
|
514 document.querySelectorAll( "#pages .del-pages-btn" ).forEach( function( button ) {
|
|
515 button.addEventListener( "click", function( e ) {
|
|
516 let ids = [];
|
|
517 document.querySelectorAll( "#pages .pages-grid input[type=checkbox]:checked" ).forEach( function( ch ) {
|
|
518 let id = ch.closest( "[data-id]" ).getAttribute( "data-id" );
|
|
519 ids.push( id );
|
|
520 } );
|
|
521 if ( ids.length === 0 ) {
|
|
522 notify( _( "no_selected_pages" ), "info-error", 5000 );
|
|
523 return;
|
|
524 }
|
|
525 if ( ! confirm( _( "confirm_delete_pages" ) ) ) {
|
|
526 return;
|
|
527 }
|
|
528 let data = {
|
|
529 fn: "del_pages",
|
|
530 ids: ids
|
|
531 };
|
|
532 api( data, function( r ) {
|
|
533 if ( r.info_text ) {
|
|
534 notify( r.info_text, r.info_class, 5000 );
|
|
535 if ( r.info_class == "info-success" ) {
|
|
536 data.ids.forEach( function( id ) {
|
|
537 document.querySelector( `#pages .pages-grid [data-id="${id}"]` ).remove();
|
|
538 localStorage.removeItem( "cursor_page_" + id );
|
|
539 } );
|
|
540 let count = document.querySelector( "#pages .main-footer .count" );
|
|
541 let loaded = document.querySelector( "#pages .main-footer .loaded" );
|
|
542 loaded.value = parseInt( loaded.value ) - data.ids.length;
|
|
543 count.innerText = parseInt( count.innerText ) - data.ids.length;
|
|
544 // load pages
|
|
545 let offset = +loaded.getAttribute( "data-offset" ) + document.querySelectorAll( "#pages .pages-grid > *" ).length;
|
|
546 let search = document.querySelector( "#pages .page-search" ).value;
|
|
547 let data2 = {
|
|
548 fn: "get_pages_list",
|
|
549 count: data.ids.length,
|
|
550 offset: offset,
|
|
551 search: search
|
|
552 };
|
|
553 // Не менять атрибут смещения у пейджера
|
|
554 cms.dont_change_offset = true;
|
|
555 api( data2, set_pages_list );
|
|
556 }
|
|
557 }
|
|
558 // update event for menu
|
|
559 if ( r.update_menu == "true" ) {
|
|
560 let event = new Event( "update_menu" );
|
|
561 document.body.dispatchEvent( event );
|
|
562 }
|
|
563 } );
|
|
564 } );
|
|
565 } );
|
|
566
|
|
567 // copy file link button
|
|
568 document.querySelector( "#pages .link-file-copy-btn" ).addEventListener( "click", function( e ) {
|
|
569 let img = this.previousElementSibling.innerText;
|
|
570 let tmp = document.createElement( "textarea" );
|
|
571 document.body.appendChild( tmp );
|
|
572 tmp.value = img;
|
|
573 tmp.select();
|
|
574 let r = document.execCommand( "copy" );
|
|
575 tmp.remove();
|
|
576 if ( r ) {
|
|
577 if ( img ) {
|
|
578 notify( _( "copyed" ), "info-success", 5000 );
|
|
579 } else {
|
|
580 notify( _( "select_file" ), "info-error", 5000 );
|
|
581 }
|
|
582 } else {
|
|
583 notify( _( "copy_error" ), "info-error", 5000 );
|
|
584 }
|
|
585 cm.focus();
|
|
586 } );
|
|
587
|
|
588 function CtrlS( e ) {
|
|
589 // ы and і - fix for librewolf
|
|
590 if ( ( e.code == "KeyS" || e.key == "ы" || e.key == "і" ) && e.ctrlKey == true ) {
|
|
591 e.preventDefault(); // don't save page
|
|
592 if ( window.location.hash == "#pages" ) {
|
|
593 document.querySelector( "#pages .save-page-button" ).click();
|
|
594 }
|
|
595 }
|
|
596 /*/ Ловим кнопки codemirror
|
|
597 if ( e.code == "F1" ) {
|
|
598 let dialog = document.querySelector( ".CodeMirror-dialog-top" );
|
|
599 let html = dialog.outerHTML;
|
|
600 cms.dialog = html;
|
|
601 //notify( html, "info-success", 5000000 );
|
|
602 }
|
|
603 if ( e.code == "F2" ) {
|
|
604 document.querySelector( ".CodeMirror" ).insertAdjacentHTML( "beforeend", cms.dialog );
|
|
605 }
|
|
606 */
|
|
607 }
|
|
608
|
|
609 // Save Page
|
|
610 document.querySelectorAll( "#pages .save-page-button" ).forEach( function( button ) {
|
|
611 button.addEventListener( "click", function( e ) {
|
|
612 window.cm.save(); // drop changes to textarea
|
|
613 let main_div = document.querySelector( "#pages" );
|
|
614 let prop_div = main_div.querySelector( ".page-properties" );
|
|
615 let data = {
|
|
616 fn: "save_page",
|
|
617 id: main_div.querySelector( ".save-page-button" ).getAttribute( "data-id" ),
|
|
618 modified: main_div.querySelector( ".page-editor > textarea" ).getAttribute( "data-modified" ),
|
|
619 text: main_div.querySelector( ".page-editor > textarea" ).value,
|
|
620 title: prop_div.querySelector( "input[name='title']" ).value,
|
|
621 url: prop_div.querySelector( "input[name='url']" ).value,
|
|
622 seo_title: prop_div.querySelector( "input[name='seo_title']" ).value,
|
|
623 description: prop_div.querySelector( "textarea[name='description']" ).value,
|
|
624 tags: prop_div.querySelector( "textarea[name='tags']" ).value,
|
|
625 date: prop_div.querySelector( "input[name='date']" ).value,
|
|
626 time: prop_div.querySelector( "input[name='time']" ).value,
|
|
627 template: prop_div.querySelector( ".template-select-grid .field-select" ).getAttribute( "data-template" ),
|
|
628 old_template: prop_div.querySelector( ".template-select-grid .field-select" ).getAttribute( "data-old-template" ),
|
|
629 }
|
|
630 api( data, function( r ) {
|
|
631 if ( r.ok == "true" ) {
|
|
632 // set text
|
|
633 if ( r.new_text ) {
|
|
634 window.cm.setValue( r.new_text );
|
|
635 }
|
|
636
|
|
637 // Update Title and URL
|
|
638 main_div.querySelector( ".page-editor-title" ).innerHTML = r.title;
|
|
639 main_div.querySelector( ".page-editor-title" ).setAttribute( "href", r.base_path + r.url );
|
|
640 prop_div.querySelector( "input[name='url']" ).value = r.url;
|
|
641
|
|
642 // update old template
|
|
643 prop_div.querySelector( ".template-select-grid .field-select" ).setAttribute( "data-old-template", data.template );
|
|
644
|
|
645 // Update item in page list
|
|
646 let item = main_div.querySelector( `.pages-grid [data-id='${data.id}']` );
|
|
647 item.querySelector( `.page-name` ).innerHTML = r.title;
|
|
648 item.querySelector( `.page-name` ).setAttribute( "href", r.base_path + r.url );
|
|
649 update_home();
|
|
650 item.querySelector( `input[name='title']` ).value = r.title;
|
|
651 item.querySelector( `input[name='url']` ).value = r.url;
|
|
652 item.querySelector( `input[name='seo_title']` ).value = data.seo_title;
|
|
653 item.querySelector( `textarea[name='description']` ).value = data.description;
|
|
654 item.querySelector( `textarea[name='tags']` ).value = data.tags;
|
|
655
|
|
656 // Выставить шаблон в плашке в списке страниц
|
|
657 let select = item.querySelector( `.template-select-grid` );
|
|
658 select_switch_to( select, data.template );
|
|
659 item.querySelector( `.template-select-grid .field-select` ).setAttribute( "data-old-template", data.template );
|
|
660
|
|
661 item.querySelector( `input[name='date']` ).value = data.date;
|
|
662 item.querySelector( `input[name='time']` ).value = data.time;
|
|
663 if ( r.planned ) {
|
|
664 item.querySelector( `.page-date` ).classList.add( "future" );
|
|
665 } else {
|
|
666 item.querySelector( `.page-date` ).classList.remove( "future" );
|
|
667 }
|
|
668
|
|
669 main_div.querySelector( ".page-editor > textarea" ).setAttribute( "data-modified", r.modified );
|
|
670 main_div.querySelector( ".close-page-button" ).setAttribute( "data-changed", "false" );
|
|
671 main_div.querySelector( ".page-editor-grid" ).setAttribute( "data-changed", "false" );
|
|
672 // edit marker
|
|
673 main_div.querySelectorAll( ".pages-grid > div" ).forEach( function( item ) {
|
|
674 item.classList.remove( "last-edited" );
|
|
675 } );
|
|
676 item.classList.add( "last-edited" );
|
|
677 // close editor after save
|
|
678 if ( main_div.querySelector( ".save-page-button" ).getAttribute( "data-close" ) === "true" ) {
|
|
679 main_div.querySelector( ".save-page-button" ).setAttribute( "data-close", "false" );
|
|
680 main_div.querySelector( ".close-page-button" ).click();
|
|
681 }
|
|
682 // highlight save button
|
|
683 main_div.querySelector( ".save-page-button" ).classList.add( "saved" );
|
|
684 setTimeout( function() {
|
|
685 main_div.querySelector( ".save-page-button" ).classList.remove( "saved" );
|
|
686 }, 1000 );
|
|
687
|
|
688 notify( r.info_text, r.info_class, r.info_time );
|
|
689
|
|
690 // update event for menu
|
|
691 if ( r.update_menu == "true" ) {
|
|
692 let event = new Event( "update_menu" );
|
|
693 document.body.dispatchEvent( event );
|
|
694 }
|
|
695 }
|
|
696 if ( r.ok == "false" ) {
|
|
697 // highlight save button
|
|
698 main_div.querySelector( ".save-page-button" ).classList.add( "error" );
|
|
699 setTimeout( function() {
|
|
700 main_div.querySelector( ".save-page-button" ).classList.remove( "error" );
|
|
701 }, 1000 );
|
|
702
|
|
703 notify( r.info_text, r.info_class, r.info_time );
|
|
704 }
|
|
705 } );
|
|
706 } );
|
|
707 } );
|
|
708
|
|
709 // transliterate file name
|
|
710 function __tr_file( str ) {
|
|
711 let ext = str.match( /\.[^\.]+$/, "" );
|
|
712 str = str.replace( /\.[^\.]+$/, "" );
|
|
713 let sp = cms.tr[" "];
|
|
714 cms.tr[" "] = "_";
|
|
715 for ( let i in cms.tr ) {
|
|
716 let re = new RegExp( i, "g" );
|
|
717 str = str.replace( re, cms.tr[i] );
|
|
718 }
|
|
719 if ( sp === undefined ) {
|
|
720 delete cms.tr[" "];
|
|
721 } else {
|
|
722 cms.tr[" "] = sp;
|
|
723 }
|
|
724 str = str.replace( /[^-A-Za-z0-9_]+/g, "" );
|
|
725 if ( ext[0] ) {
|
|
726 str = str + ext[0];
|
|
727 }
|
|
728 str = str.toLowerCase();
|
|
729 return str;
|
|
730 }
|
|
731
|
|
732 // Upload files
|
|
733 let upload_btn = document.querySelector( "#pages .upload-files input[type=file]" );
|
|
734 if ( upload_btn ) upload_btn.addEventListener( "change", async function( event ) {
|
|
735 const formData = new FormData();
|
|
736 let id = document.querySelector( "#pages .save-page-button" ).getAttribute( "data-id" );
|
|
737 formData.append( "id", id );
|
|
738 formData.append( "fn", "upload_files" );
|
|
739 let n = 0;
|
|
740 for ( let i = 0; i < this.files.length; i++ ) {
|
|
741 formData.append( "myfile[]", this.files[i] );
|
|
742 let f = `${cms.base_path}uploads/${id}/` + __tr_file( this.files[i].name );
|
|
743 let f_exists = document.querySelector( `#pages .file-block [data-src="${f}"]` );
|
|
744 if ( f_exists ) { n++; }
|
|
745 }
|
|
746 let google_chrome_fix = this;
|
|
747 if ( n ) {
|
|
748 let c = confirm( _( "same_files" ) + ` - ${n} ` + _( "pc" ) + "\n" + _( "confirm_replace" ) );
|
|
749 if ( ! c ) {
|
|
750 google_chrome_fix.value = "";
|
|
751 return c;
|
|
752 }
|
|
753 }
|
|
754 let bar = document.querySelector( "#pages .upload-progress" );
|
|
755
|
|
756
|
|
757 let ajax = new XMLHttpRequest();
|
|
758
|
|
759 ajax.upload.addEventListener( "progress", function( event ) {
|
|
760 let percent = Math.round( (event.loaded / event.total) * 100 );
|
|
761 bar.style.width = percent + "%";
|
|
762 }, false );
|
|
763
|
|
764 ajax.addEventListener( "error", function( event ) {
|
|
765 notify( _( "error_upload_file" ), "info-error", 3600000 );
|
|
766 bar.style = "";
|
|
767 }, false );
|
|
768
|
|
769 ajax.addEventListener( "abort", function( event ) {
|
|
770 notify( _( "error_upload_file" ), "info-error", 3600000 );
|
|
771 bar.style = "";
|
|
772 }, false );
|
|
773
|
|
774 ajax.addEventListener( "load", function( event ) {
|
|
775 bar.style = "";
|
|
776 google_chrome_fix.value = "";
|
|
777 if ( event.target.status == 413 ) {
|
|
778 notify( _( "too_large" ), "info-error", 5000 );
|
|
779 } else {
|
|
780 let r = JSON.parse( event.target.responseText );
|
|
781 if ( r.info_text ) {
|
|
782 notify( r.info_text, r.info_class, r.info_time );
|
|
783 if ( r.info_class == "info-success" ) {
|
|
784
|
|
785 // удалить файлы которые были обновлены
|
|
786 let tmp = document.createElement( "div" );
|
|
787 tmp.innerHTML = r.flist;
|
|
788 let imgs = tmp.querySelectorAll( "img" );
|
|
789 imgs.forEach( function( img ) {
|
|
790 let file = img.getAttribute( "data-src" );
|
|
791 let exists_file = document.querySelector( `#pages .file-block [data-src="${file}"]` );
|
|
792 if ( exists_file ) {
|
|
793 exists_file.parentElement.remove();
|
|
794 }
|
|
795 } );
|
|
796
|
|
797 let container = document.querySelector( "#pages .mediateka-files-grid" );
|
|
798 container.innerHTML = r.flist + container.innerHTML;
|
|
799
|
|
800 // images checkboxes
|
|
801 container.querySelectorAll( "input[type=checkbox]" ).forEach( function( checkbox ) {
|
|
802 checkbox.addEventListener( "dblclick", img_check_dblclick );
|
|
803 checkbox.addEventListener( "change", img_rechecked );
|
|
804 } );
|
|
805
|
|
806 // open lightbox
|
|
807 container.querySelectorAll( "img" ).forEach( function( img ) {
|
|
808 img.addEventListener( "dblclick", img_lbox );
|
|
809 } );
|
|
810
|
|
811 // generate link
|
|
812 container.querySelectorAll( ".file-block" ).forEach( function( file_block ) {
|
|
813 file_block.addEventListener( "click", img_click );
|
|
814 } );
|
|
815
|
|
816 // select last uploaded
|
|
817 container.querySelector( ".file-block" ).click();
|
|
818 }
|
|
819 }
|
|
820 }
|
|
821 }, false );
|
|
822
|
|
823 ajax.open( "POST", cms.api );
|
|
824 ajax.send( formData );
|
|
825
|
|
826 } );
|
|
827
|
|
828 // Close Editor
|
|
829 document.querySelectorAll( "#pages .close-page-button" ).forEach( function( button ) {
|
|
830 button.addEventListener( "click", function( e ) {
|
|
831
|
|
832 // hide mediateka
|
|
833 if ( ! document.querySelector( "#pages .page-editor-panel" ).classList.contains( "hidden" ) ) {
|
|
834 document.querySelector( "#pages .open-mediateka" ).click();
|
|
835 }
|
|
836
|
|
837 // hide editor
|
|
838 document.querySelector( "#pages .page-editor-bg" ).classList.add( "hidden" );
|
|
839 document.body.classList.remove( "editor" );
|
|
840
|
|
841 document.documentElement.removeEventListener( "keydown", CtrlS );
|
|
842
|
|
843 // detach
|
|
844 if ( window.cm !== undefined ) {
|
|
845 if ( this.getAttribute( "data-changed" ) === "true" ) {
|
|
846 if ( confirm( _( "confirm_save" ) ) ) {
|
|
847 document.querySelector( "#pages .save-page-button" ).setAttribute( "data-close", "true" );
|
|
848 document.querySelector( "#pages .save-page-button" ).click();
|
|
849 return;
|
|
850 }
|
|
851 }
|
|
852 window.cm.toTextArea();
|
|
853 window.cm = null;
|
|
854 }
|
|
855
|
|
856 } );
|
|
857 } );
|
|
858
|
|
859 // Create Page
|
|
860 document.querySelectorAll( "#pages .add-page-btn" ).forEach( function( btn ) {
|
|
861 btn.addEventListener( "click", function ( e ) {
|
|
862 // Отложенный вызов на случай если нужно очистить поиск
|
|
863 cms.create_page_fn = function() {
|
|
864 api( { fn: "create_page" }, function( r ) {
|
|
865 if ( r.info_text ) {
|
|
866 notify( r.info_text, r.info_class, r.info_time );
|
|
867 }
|
|
868 if ( r.pages ) {
|
|
869 let grid = document.querySelector( "#pages .pages-grid" );
|
|
870 grid.insertAdjacentHTML( "afterbegin", r.pages[0].html );
|
|
871 // Подкрутить список страниц в начало
|
|
872 document.querySelector( "#pages .main-main" ).scrollTop = 0;
|
|
873
|
|
874 let page_box = grid.querySelector( `[data-id="${r.pages[0].id}"]` );
|
|
875
|
|
876 set_controls( page_box );
|
|
877
|
|
878 let counter = document.querySelector( "#pages .main-footer .count" );
|
|
879 counter.innerText = +counter.innerText + 1;
|
|
880
|
|
881 let showed_pages_el = document.querySelector( "#pages .main-footer .counters input" );
|
|
882 if ( showed_pages_el.value === get_cookie( "pages_pager" ) ) {
|
|
883 document.querySelector( "#pages .pages-grid > div:last-child" ).remove();
|
|
884 } else {
|
|
885 showed_pages_el.value = +showed_pages_el.value + 1;
|
|
886 }
|
|
887 }
|
|
888 } );
|
|
889 }
|
|
890 // Если сейчас не результаты поиска отображены,
|
|
891 // и если мы видим первый пейджер
|
|
892 // то сразу выполнить создание страницы
|
|
893 let empty_search = document.querySelector( "#pages .page-search" ).getAttribute( "data-result-of" ) === "";
|
|
894 let offset_zero = +document.querySelector( "#pages .main-footer .counters input" ).getAttribute( "data-offset" ) === 0;
|
|
895 if ( empty_search && offset_zero ) {
|
|
896 cms.create_page_fn();
|
|
897 cms.create_page_fn = null;
|
|
898 } else {
|
|
899 document.querySelector( "#pages .reset" ).click();
|
|
900 // Создание страницы произведет функция set_pages_list()
|
|
901 }
|
|
902 } );
|
|
903 } );
|
|
904
|
|
905 // Open Properties
|
|
906 document.querySelector( "#pages .open-properties" ).addEventListener( "click", function( e ) {
|
|
907 document.querySelector( "#pages .page-editor-grid" ).classList.toggle( "properties" );
|
|
908 document.querySelector( "#pages .page-properties" ).classList.toggle( "hidden" );
|
|
909 if ( window.cm ) {
|
|
910 let cursor = window.cm.getCursor();
|
|
911 window.cm.scrollIntoView( { line:cursor.line, ch:cursor.ch } );
|
|
912 }
|
|
913 if ( document.querySelector( "#pages .page-editor-grid" ).classList.contains( "properties" ) ) {
|
|
914 document.querySelector( "#pages .page-editor-grid" ).classList.remove( "mediateka" );
|
|
915 document.querySelector( "#pages .page-editor-panel" ).classList.add( "hidden" );
|
|
916 }
|
|
917 } );
|
|
918
|
|
919 // Open Mediateka
|
|
920 document.querySelector( "#pages .open-mediateka" ).addEventListener( "click", function( e ) {
|
|
921 document.querySelector( "#pages .page-editor-grid" ).classList.toggle( "mediateka" );
|
|
922 document.querySelector( "#pages .page-editor-panel" ).classList.toggle( "hidden" );
|
|
923 if ( window.cm ) {
|
|
924 let cursor = window.cm.getCursor();
|
|
925 window.cm.scrollIntoView( { line:cursor.line, ch:cursor.ch } );
|
|
926 }
|
|
927 if ( document.querySelector( "#pages .page-editor-grid" ).classList.contains( "mediateka" ) ) {
|
|
928 document.querySelector( "#pages .page-editor-grid" ).classList.remove( "properties" );
|
|
929 document.querySelector( "#pages .page-properties" ).classList.add( "hidden" );
|
|
930 }
|
|
931 cm.focus();
|
|
932 } );
|
|
933
|
|
934 // Replace Dialog Toggle
|
|
935 document.querySelector( "#pages .codemirror-replace" ).addEventListener( "click", function( e ) {
|
|
936 let dialog = document.querySelector( "#pages .CodeMirror-dialog" );
|
|
937 if ( dialog ) {
|
|
938 dialog.remove();
|
|
939 } else {
|
|
940 let mediateka = ! document.querySelector( "#pages .page-editor-panel" ).classList.contains( "hidden" );
|
|
941 if ( mediateka && window.innerWidth < 1024 ) {
|
|
942 document.querySelector( "#pages .open-mediateka" ).click();
|
|
943 }
|
|
944 window.cm.execCommand( "replace" );
|
|
945 }
|
|
946 } );
|
|
947
|
|
948 // generate link to clicked file
|
|
949 function img_click() {
|
|
950 this.parentElement.querySelectorAll( ".file-block" ).forEach( function( block ) {
|
|
951 block.classList.remove( "active-file" );
|
|
952 } );
|
|
953 this.classList.add( "active-file" );
|
|
954 let i = this.querySelector( "img" );
|
|
955 let t = i.getAttribute( "data-type" );
|
|
956 let link = i.getAttribute( "data-src" );
|
|
957 let w = i.getAttribute( "width" );
|
|
958 let h = i.getAttribute( "height" );
|
|
959 let e = link.replace( /.*\./, "" );
|
|
960 let img = [ "webp", "tiff", "jpeg", "jpg", "png", "svg", "gif", "bmp", "ico" ];
|
|
961 let mus = [ "mp3", "ogg", "m4a", "flac" ];
|
|
962 let vid = [ "mp4", "mkv", "webm" ];
|
|
963 let a = `<a href="${link}" target=_blank>${link}</a>`;
|
|
964 let tag = this.closest( ".mediateka-grid" ).querySelector( ".link-file-tag" );
|
|
965 if ( img.indexOf( e ) >= 0 ) {
|
|
966 link = `<img alt="" src="${a}"`;
|
|
967 if ( w ) {
|
|
968 link += ` width="${w}"`;
|
|
969 }
|
|
970 if ( h ) {
|
|
971 link += ` height="${h}"`;
|
|
972 }
|
|
973 link += ` loading="lazy"`;
|
|
974 link += ">";
|
|
975 tag.innerHTML = link;
|
|
976 } else if ( mus.indexOf( e ) >= 0 ) {
|
|
977 link = `<audio src="${a}" controls></audio>`;
|
|
978 tag.innerHTML = link;
|
|
979 } else if ( vid.indexOf( e ) >= 0 ) {
|
|
980 link = `<video src="${a}" poster="" controls preload="none"></video>`;
|
|
981 tag.innerHTML = link;
|
|
982 } else {
|
|
983 link = `<a href="${a}">TEXT</a>`;
|
|
984 tag.innerHTML = link;
|
|
985 }
|
|
986 let inner_link = tag.querySelector( "a" );
|
|
987 inner_link.addEventListener( "click", file_link_click );
|
|
988 cm.focus();
|
|
989 }
|
|
990
|
|
991 function file_link_click( e ) {
|
|
992 e.preventDefault();
|
|
993 let tmp = document.createElement( "textarea" );
|
|
994 document.body.appendChild( tmp );
|
|
995 tmp.value = e.target.getAttribute( "href" );
|
|
996 tmp.select();
|
|
997 let r = document.execCommand( "copy" );
|
|
998 tmp.remove();
|
|
999 if ( r ) {
|
|
1000 notify( _( "copyed" ), "info-success", 5000 );
|
|
1001 } else {
|
|
1002 notify( _( "copy_error" ), "info-error", 5000 );
|
|
1003 }
|
|
1004 cm.focus();
|
|
1005 }
|
|
1006
|
|
1007 // enable or disable delete files button
|
|
1008 function img_rechecked() {
|
|
1009 let checked = document.querySelectorAll( "#pages .mediateka-files-grid input[type=checkbox]:checked" );
|
|
1010 if ( checked.length ) {
|
|
1011 document.querySelector( "#pages .del-uploaded-files" ).classList.remove( "disabled" );
|
|
1012 } else {
|
|
1013 document.querySelector( "#pages .del-uploaded-files" ).classList.add( "disabled" );
|
|
1014 }
|
|
1015 }
|
|
1016
|
|
1017 // Выбор всех картинок двойным кликом
|
|
1018 function img_check_dblclick( e ) {
|
|
1019 let stat = ! this.checked;
|
|
1020 document.querySelectorAll( "#pages .mediateka-files-grid input[type=checkbox]" ).forEach( function( chbox ) {
|
|
1021 chbox.checked = stat;
|
|
1022 } );
|
|
1023 img_rechecked();
|
|
1024 }
|
|
1025
|
|
1026 // view in lightbox
|
|
1027 function img_lbox() {
|
|
1028 let src = this.getAttribute( "data-src" );
|
|
1029 let e = src.replace( /.*\./, "" );
|
|
1030 let img = [ "webp", "tiff", "jpeg", "jpg", "png", "svg", "gif", "bmp", "ico" ];
|
|
1031 let mus = [ "mp3", "ogg", "m4a", "flac" ];
|
|
1032 let vid = [ "mp4", "mkv", "webm" ];
|
|
1033 let t;
|
|
1034 if ( document.querySelector( "#lbox-window" ) == null ) {
|
|
1035 if ( img.indexOf( e ) >= 0 ) {
|
|
1036 t = document.createElement( "img" );
|
|
1037 } else if ( mus.indexOf( e ) >= 0 ) {
|
|
1038 t = document.createElement( "audio" );
|
|
1039 t.setAttribute( "controls", true );
|
|
1040 } else if ( vid.indexOf( e ) >= 0 ) {
|
|
1041 t = document.createElement( "video" );
|
|
1042 t.setAttribute( "controls", true );
|
|
1043 }
|
|
1044 if ( t !== undefined ) {
|
|
1045 t.src = src;
|
|
1046 let d = document.createElement( "div" );
|
|
1047 d.id = "lbox-window";
|
|
1048 d.appendChild( t );
|
|
1049 document.body.appendChild( d );
|
|
1050 d.addEventListener( "click", function( e ) {
|
|
1051 this.remove();
|
|
1052 } );
|
|
1053 }
|
|
1054 }
|
|
1055 }
|
|
1056
|
|
1057
|
|
1058 // Delete files
|
|
1059 document.querySelector( "#pages .del-uploaded-files" ).addEventListener( "click", function( e ) {
|
|
1060 if ( ! this.classList.contains( "disabled" ) ) {
|
|
1061 let flist = [];
|
|
1062 document.querySelectorAll( "#pages .mediateka-files-grid input[type=checkbox]:checked" ).forEach( function( e ) {
|
|
1063 let f = e.closest( ".file-block" ).querySelector( "img" ).getAttribute( "data-src" );
|
|
1064 flist.push( f );
|
|
1065 } );
|
|
1066 let data = {
|
|
1067 fn: "del_files",
|
|
1068 flist: flist
|
|
1069 };
|
|
1070 api( data, function( r ) {
|
|
1071 if ( r.info_text ) {
|
|
1072 document.querySelector( "#pages .link-file-tag" ).innerHTML = "";
|
|
1073 notify( r.info_text, r.info_class, r.info_time );
|
|
1074 if ( r.info_class == "info-success" ) {
|
|
1075 for ( let f in flist ) {
|
|
1076 document.querySelector( `#pages .mediateka-files-grid img[data-src="${flist[f]}"]` ).parentElement.remove();
|
|
1077 }
|
|
1078 document.querySelector( "#pages .del-uploaded-files" ).classList.add( "disabled" );
|
|
1079 }
|
|
1080 }
|
|
1081 } );
|
|
1082 }
|
|
1083 } );
|
|
1084
|
|
1085 // prevent hide cursor when window resize
|
|
1086 window.addEventListener( "resize", function() {
|
|
1087 if ( window.cm ) {
|
|
1088 let cursor = window.cm.getCursor();
|
|
1089 window.cm.scrollIntoView( { line:cursor.line, ch:cursor.ch } );
|
|
1090 }
|
|
1091 } );
|
|
1092
|
|
1093 // show/hide tags
|
|
1094 let tags_btn = document.querySelector( "#pages .tags-helper" );
|
|
1095 if ( tags_btn ) tags_btn.addEventListener( "click", function( e ) {
|
|
1096 document.querySelector( "#pages .page-editor-grid" ).classList.toggle( "tags-opened" );
|
|
1097 cm.focus();
|
|
1098 cm.refresh();
|
|
1099 } );
|
|
1100
|
|
1101 // for tags
|
|
1102 document.querySelectorAll( "#pages .tags-grid [data-type='wrap']" ) .forEach( function( btn ) {
|
|
1103 btn.addEventListener( "click", function( e ) {
|
|
1104 let otag = this.getAttribute( "data-otag" );
|
|
1105 let ctag = this.getAttribute( "data-ctag" );
|
|
1106 let len = this.getAttribute( "data-len" );
|
|
1107 let ch = this.getAttribute( "data-ch" );
|
|
1108 let line = this.getAttribute( "data-line" );
|
|
1109
|
|
1110 //wrap_selections( otag, ctag, len, line, ch );
|
|
1111 let cursor = cm.getCursor();
|
|
1112 let selections = cm.getSelections();
|
|
1113 let replacements = [];
|
|
1114 for ( let i = 0; i < selections.length; i++ ) {
|
|
1115 replacements[i] = otag + selections[i] + ctag;
|
|
1116 }
|
|
1117 cm.replaceSelections( replacements );
|
|
1118 // Прятять панельку на мобильнике
|
|
1119 if ( window.innerWidth < 1024 ) {
|
|
1120 //document.querySelector( "#pages .tags-helper" ).click();
|
|
1121 let grid = this.closest( ".editor-grid" );
|
|
1122 grid.classList.remove( "tags-opened" );
|
|
1123 }
|
|
1124 if ( selections.length < 2 ) {
|
|
1125 if ( line ) {
|
|
1126 cursor.line += +line;
|
|
1127 cursor.ch = +ch;
|
|
1128 } else if ( len ) {
|
|
1129 cursor.ch += +len;
|
|
1130 }
|
|
1131 cm.setCursor( cursor );
|
|
1132 }
|
|
1133 cm.focus();
|
|
1134 cm.refresh();
|
|
1135 } );
|
|
1136 } );
|
|
1137 // for <a> tag
|
|
1138 document.querySelectorAll( "#pages .tags-grid [data-type='wrap-a']" ) .forEach( function( btn ) {
|
|
1139 btn.addEventListener( "click", function( e ) {
|
|
1140 let cursor = cm.getCursor();
|
|
1141 let selections = cm.getSelections();
|
|
1142 let replacements = [];
|
|
1143
|
|
1144 for ( let i = 0; i < selections.length; i++ ) {
|
|
1145 if ( selections[i].match( /https?:\/\// ) ) {
|
|
1146 replacements[i] = `<a href="${selections[i]}" target=_blank>${selections[i]}</a>`;
|
|
1147 } else {
|
|
1148 replacements[i] = `<a href="" target=_blank>${selections[i]}</a>`;
|
|
1149 }
|
|
1150 }
|
|
1151
|
|
1152 cm.replaceSelections( replacements );
|
|
1153
|
|
1154 if ( selections.length == 1 && selections[0] === "" ) {
|
|
1155 cursor.ch += 9;
|
|
1156 cm.setCursor( cursor );
|
|
1157 }
|
|
1158
|
|
1159 if ( window.innerWidth < 1024 ) {
|
|
1160 //document.querySelector( "#pages .tags-helper" ).click();
|
|
1161 let grid = this.closest( ".editor-grid" );
|
|
1162 grid.classList.remove( "tags-opened" );
|
|
1163 }
|
|
1164
|
|
1165 cm.focus();
|
|
1166 cm.refresh();
|
|
1167 } );
|
|
1168 } );
|
|
1169 // for tags <ul> and <ol>
|
|
1170 document.querySelectorAll( "#pages .tags-grid [data-type='wrap-list']" ) .forEach( function( btn ) {
|
|
1171 btn.addEventListener( "click", function( e ) {
|
|
1172 let tag = this.getAttribute( "data-tag" );
|
|
1173 let selections = cm.getSelections();
|
|
1174 let replacements = [];
|
|
1175
|
|
1176 if ( selections.length == 1 && selections[0] === "" ) {
|
|
1177 replacements[0] = `<${tag}>\n <li></li>\n</${tag}>`;
|
|
1178 } else if ( selections.length == 1 ) {
|
|
1179 let lines = selections[0].split( "\n" );
|
|
1180 replacements[0] = `<${tag}>\n <li>` + lines.join( "</li>\n <li>" ) + `</li>\n</${tag}>`;
|
|
1181 } else {
|
|
1182 let n = selections.length - 1;
|
|
1183 for ( let i = 0; i <= n; i++ ) {
|
|
1184 replacements[i] = ` <li>${selections[i]}</li>`;
|
|
1185 }
|
|
1186 replacements[0] = `<${tag}>\n` + replacements[0];
|
|
1187 replacements[n] = replacements[n] + `\n</${tag}>`;
|
|
1188 }
|
|
1189
|
|
1190 cm.replaceSelections( replacements );
|
|
1191
|
|
1192 if ( window.innerWidth < 1024 ) {
|
|
1193 //document.querySelector( "#pages .tags-helper" ).click();
|
|
1194 let grid = this.closest( ".editor-grid" );
|
|
1195 grid.classList.remove( "tags-opened" );
|
|
1196 }
|
|
1197
|
|
1198 cm.focus();
|
|
1199 cm.refresh();
|
|
1200 } );
|
|
1201 } );
|
|
1202
|
|
1203 // fix glitches codemirror
|
|
1204 let fix = document.querySelector( "aside a[href='#pages']" );
|
|
1205 if ( fix ) fix.addEventListener( "click", function( e ) {
|
|
1206 setTimeout( function( e ) {
|
|
1207 if ( window.cm ) {
|
|
1208 cm.refresh();
|
|
1209 cm.focus();
|
|
1210 }
|
|
1211 }, 50 );
|
|
1212 } );
|
|
1213
|
|
1214 // Транслитерация URL
|
|
1215 let tr_url = document.querySelector( "#pages .page-editor-grid .url-translit" );
|
|
1216 if ( tr_url ) tr_url.addEventListener( "click", function( e ) {
|
|
1217 let url = document.querySelector( "#pages .page-editor-grid .page-properties input[name='title']" ).value;
|
|
1218 let tr_url = url_translit( url );
|
|
1219 this.previousElementSibling.value = tr_url;
|
|
1220 } );
|
|
1221 function url_translit( url ) {
|
|
1222 url = url.toLowerCase();
|
|
1223 for ( let i in cms.tr ) {
|
|
1224 let re = new RegExp( i, "g" );
|
|
1225 url = url.replace( re, cms.tr[i] );
|
|
1226 }
|
|
1227 url = url.replace( / +/g, "-" );
|
|
1228 url = url.replace( /[^-a-z0-9_]+/g, "" );
|
|
1229 url = url.replace( /^[-_]+|[-_]+$/g, "" );
|
|
1230 return url;
|
|
1231 }
|
|
1232
|
|
1233 function update_home() {
|
|
1234 document.querySelectorAll( `#pages .pages-grid [data-id]` ).forEach( function( page ) {
|
|
1235 if ( page.querySelector( `.page-name[href="${cms.base_path}"]` ) ) {
|
|
1236 page.classList.add( "home" );
|
|
1237 } else {
|
|
1238 page.classList.remove( "home" );
|
|
1239 }
|
|
1240 } );
|
|
1241 }
|
|
1242
|
|
1243
|
|
1244 // Замена текста на всех страницах
|
|
1245 document.querySelectorAll( "#pages-utils .replace-btn" ).forEach( function( button ) {
|
|
1246 button.addEventListener( "click", function( e ) {
|
|
1247 let data = {
|
|
1248 fn: "replace_in_pages",
|
|
1249 table: document.querySelector( "#pages-utils input[name='table']" ).value,
|
|
1250 id_col: document.querySelector( "#pages-utils input[name='id_col']" ).value,
|
|
1251 column: document.querySelector( "#pages-utils input[name='column']" ).value,
|
|
1252 search_regex: document.querySelector( "#pages-utils input[name='search_regex']" ).value,
|
|
1253 replace: document.querySelector( "#pages-utils input[name='replace']" ).value,
|
|
1254 };
|
|
1255 if ( data.search_regex && confirm( _( "replace_in_pages_confirm" ) ) ) {
|
|
1256 api( data, function( r ) {
|
|
1257 if ( r.info_text ) {
|
|
1258 notify( r.info_text, r.info_class, r.info_time );
|
|
1259 }
|
|
1260 } );
|
|
1261 }
|
|
1262 } );
|
|
1263 } );
|
|
1264
|
|
1265 } );
|