Добавил с сервера статистику

This commit is contained in:
NikDizell 2026-03-04 15:26:53 +03:00
parent 711005f0ea
commit 7541e1e986
85 changed files with 1957 additions and 0 deletions

View File

@ -0,0 +1,238 @@
import ClassicEditor from './src/ckeditor';
import './src/override-django.css';
window.ClassicEditor = ClassicEditor;
window.ckeditorRegisterCallback = registerCallback;
window.ckeditorUnregisterCallback = unregisterCallback;
window.editors = {};
let editors = {};
let callbacks = {};
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function getCSRFToken(cookieName) {
let token = getCookie(cookieName);
if (!token) {
token = document.querySelector('input[name=csrfmiddlewaretoken]')?.value;
}
return token;
}
/**
* Checks whether the element or its children match the query and returns
* an array with the matches.
*
* @param {!HTMLElement} element
* @param {!string} query
*
* @returns {array.<HTMLElement>}
*/
function resolveElementArray(element, query) {
return element.matches(query) ? [element] : [...element.querySelectorAll(query)];
}
/**
* This function initializes the CKEditor inputs within an optional element and
* assigns properties necessary for the correct operation
*
* @param {HTMLElement} [element=document.body] - The element to search for elements
*
* @returns {void}
*/
function createEditors(element = document.body) {
const allEditors = resolveElementArray(element, '.django_ckeditor_5');
allEditors.forEach(editorEl => {
if (
editorEl.id.indexOf('__prefix__') !== -1 ||
editorEl.getAttribute('data-processed') === '1'
) {
return;
}
const script_id = `${editorEl.id}_script`;
// remove next sibling if it is an empty text node
if (editorEl.nextSibling.nodeType == Node.TEXT_NODE && editorEl.nextSibling.textContent.trim() === '') {
editorEl.nextSibling.remove();
}
const upload_url = element.querySelector(
`#${script_id}-ck-editor-5-upload-url`
).getAttribute('data-upload-url');
const upload_file_types = JSON.parse(element.querySelector(
`#${script_id}-ck-editor-5-upload-url`
).getAttribute('data-upload-file-types'));
const csrf_cookie_name = element.querySelector(
`#${script_id}-ck-editor-5-upload-url`
).getAttribute('data-csrf_cookie_name');
const labelElement = element.querySelector(`[for$="${editorEl.id}"]`);
if (labelElement) {
labelElement.style.float = 'none';
}
const config = JSON.parse(
element.querySelector(`#${script_id}-span`).textContent,
(key, value) => {
var match = value.toString().match(new RegExp('^/(.*?)/([gimy]*)$'));
if (match) {
var regex = new RegExp(match[1], match[2]);
return regex;
}
if (typeof value === 'string' && value.startsWith('callback:')) {
var callbackName = value.substring(9);
var callback = window[callbackName];
if (typeof callback === 'function') {
return callback;
}
}
return value;
}
);
config.simpleUpload = {
'uploadUrl': upload_url,
'headers': {
'X-CSRFToken': getCSRFToken(csrf_cookie_name),
},
};
config.fileUploader = {
'fileTypes': upload_file_types
};
config.licenseKey = 'GPL';
// Configure autosave if enabled
if (config.autosave) {
config.autosave.save = function(editor) {
return new Promise((resolve, reject) => {
const textarea = document.querySelector(`#${editorEl.id}`);
const data = editor.getData();
textarea.value = data;
// If save URL is provided, send to server
if (config.autosave.saveUrl) {
fetch(config.autosave.saveUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken(csrf_cookie_name),
},
body: JSON.stringify({
id: editorEl.id,
content: data
})
})
.then(response => response.json())
.then(result => resolve(result))
.catch(error => reject(error));
} else {
// Just update textarea
resolve();
}
});
};
}
ClassicEditor.create(
editorEl,
config
).then(editor => {
const textarea = document.querySelector(`#${editorEl.id}`);
editor.model.document.on('change:data', () => {
textarea.value = editor.getData();
});
if (editor.plugins.has('WordCount')) {
const wordCountPlugin = editor.plugins.get('WordCount');
const wordCountWrapper = element.querySelector(`#${script_id}-word-count`);
wordCountWrapper.innerHTML = '';
wordCountWrapper.appendChild(wordCountPlugin.wordCountContainer);
}
if (editorEl.hasAttribute('disabled')) {
editor.enableReadOnlyMode('django-ckeditor-5');
}
editors[editorEl.id] = editor;
if (callbacks[editorEl.id]) {
callbacks[editorEl.id](editor);
}
}).catch(error => {
console.error((error));
});
editorEl.setAttribute('data-processed', '1');
});
window.editors = editors;
}
/**
* This function filters the list of mutations only by added elements, thus
* eliminates the occurrence of text nodes and tags where it does not make sense
* to try to use with `QuerySelectorAll()` and `matches()` functions.
*
* @param {MutationRecord} recordList - It is the object inside the array
* passed to the callback of a MutationObserver.
*
* @returns {Array} Array containing filtered nodes.
*/
function getAddedNodes(recordList) {
return recordList
.flatMap(({ addedNodes }) => Array.from(addedNodes))
.filter(node => node.nodeType === 1);
}
/**
* Register a callback for when an editor with `id` is created.
*
* @param {!string} id - the id of the ckeditor element.
* @callback callback - the callback function to be invoked.
*/
function registerCallback(id, callback) {
callbacks[id] = callback;
}
/**
* Unregister a previously registered callback.
*
* @param {!string} id - the id of the ckeditor element.
*/
function unregisterCallback(id) {
callbacks[id] = null;
}
document.addEventListener("DOMContentLoaded", () => {
createEditors();
if (typeof django === "object" && django.jQuery) {
django.jQuery(document).on("formset:added", () => {createEditors();});
}
const observer = new MutationObserver((mutations) => {
let addedNodes = getAddedNodes(mutations);
addedNodes.forEach(node => {
// Initializes editors
createEditors(node);
});
});
// Configure MutationObserver options
const observerOptions = {
childList: true,
subtree: true,
};
// Selects the parent element where the events occur
const mainContent = document.body;
// Starts to observe the selected father element with the configured options
observer.observe(mainContent, observerOptions);
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,20 @@
/* istanbul ignore else -- @preserve */
/* istanbul ignore else: This is always true because otherwise it would not register a reducer callback. -- @preserve */
/* istanbul ignore file -- @preserve */
/* istanbul ignore if -- @preserve */
/* istanbul ignore if: paranoid check -- @preserve */
/* istanbul ignore next -- @preserve */
/* istanbul ignore next: paranoid check -- @preserve */
/* istanbul ignore next: static function definition -- @preserve */
/**
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,116 @@
import { ClassicEditor as ClassicEditorBase } from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
import { Essentials } from '@ckeditor/ckeditor5-essentials/src/essentials';
import { CKFinderUploadAdapter } from '@ckeditor/ckeditor5-adapter-ckfinder/src/uploadadapter';
import { Autoformat } from '@ckeditor/ckeditor5-autoformat/src/autoformat';
import { Bold } from '@ckeditor/ckeditor5-basic-styles/src/bold';
import { Italic } from '@ckeditor/ckeditor5-basic-styles/src/italic';
import { Underline } from '@ckeditor/ckeditor5-basic-styles/src/underline';
import { Strikethrough } from '@ckeditor/ckeditor5-basic-styles/src/strikethrough';
import { Code } from '@ckeditor/ckeditor5-basic-styles/src/code';
import { Subscript } from '@ckeditor/ckeditor5-basic-styles/src/subscript';
import { Superscript } from '@ckeditor/ckeditor5-basic-styles/src/superscript';
import { BlockQuote } from '@ckeditor/ckeditor5-block-quote/src/blockquote';
import { Heading } from '@ckeditor/ckeditor5-heading/src/heading';
import { Image } from '@ckeditor/ckeditor5-image/src/image';
import { ImageCaption } from '@ckeditor/ckeditor5-image/src/imagecaption';
import { ImageStyle } from '@ckeditor/ckeditor5-image/src/imagestyle';
import { ImageToolbar } from '@ckeditor/ckeditor5-image/src/imagetoolbar';
import { Link } from '@ckeditor/ckeditor5-link/src/link';
import { List } from '@ckeditor/ckeditor5-list/src/list';
import { Paragraph } from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import { ImageResize } from '@ckeditor/ckeditor5-image/src/imageresize';
import { SimpleUploadAdapter } from '@ckeditor/ckeditor5-upload/src/adapters/simpleuploadadapter';
import { Alignment } from '@ckeditor/ckeditor5-alignment/src/alignment';
import { Autosave } from '@ckeditor/ckeditor5-autosave/src/autosave';
import { PasteFromOffice } from '@ckeditor/ckeditor5-paste-from-office/src/pastefromoffice';
import { Font } from '@ckeditor/ckeditor5-font/src/font';
import { MediaEmbed } from '@ckeditor/ckeditor5-media-embed/src/mediaembed';
import { RemoveFormat } from '@ckeditor/ckeditor5-remove-format/src/removeformat';
import { Table } from '@ckeditor/ckeditor5-table/src/table';
import { TableToolbar } from '@ckeditor/ckeditor5-table/src/tabletoolbar';
import { TableProperties } from '@ckeditor/ckeditor5-table/src/tableproperties';
import { TableCellProperties } from '@ckeditor/ckeditor5-table/src/tablecellproperties';
import { Indent } from '@ckeditor/ckeditor5-indent/src/indent';
import { IndentBlock } from '@ckeditor/ckeditor5-indent/src/indentblock';
import { Highlight } from '@ckeditor/ckeditor5-highlight/src/highlight';
import { TodoList } from '@ckeditor/ckeditor5-list/src/todolist';
import { CodeBlock } from '@ckeditor/ckeditor5-code-block/src/codeblock';
import { ListProperties } from '@ckeditor/ckeditor5-list/src/listproperties';
import { SourceEditing } from '@ckeditor/ckeditor5-source-editing/src/sourceediting';
import { GeneralHtmlSupport } from '@ckeditor/ckeditor5-html-support/src/generalhtmlsupport';
import { ImageInsert } from '@ckeditor/ckeditor5-image/src/imageinsert';
import { TableCaption } from '@ckeditor/ckeditor5-table';
import { WordCount } from '@ckeditor/ckeditor5-word-count/src/wordcount';
import { Mention } from '@ckeditor/ckeditor5-mention/src/mention';
import { Markdown } from '@ckeditor/ckeditor5-markdown-gfm/src/markdown';
import { PageBreak } from '@ckeditor/ckeditor5-page-break/src/pagebreak';
import { Style } from '@ckeditor/ckeditor5-style';
import { HorizontalLine } from '@ckeditor/ckeditor5-horizontal-line';
import {LinkImage} from "@ckeditor/ckeditor5-link";
import {HtmlEmbed} from "@ckeditor/ckeditor5-html-embed";
import { FullPage } from '@ckeditor/ckeditor5-html-support';
import { SpecialCharacters } from '@ckeditor/ckeditor5-special-characters';
import { SpecialCharactersEssentials } from '@ckeditor/ckeditor5-special-characters';
import { ShowBlocks } from '@ckeditor/ckeditor5-show-blocks';
import { SelectAll } from '@ckeditor/ckeditor5-select-all';
import { FindAndReplace } from '@ckeditor/ckeditor5-find-and-replace';
export default class ClassicEditor extends ClassicEditorBase {
}
ClassicEditor.builtinPlugins = [
Essentials,
CKFinderUploadAdapter,
CodeBlock,
Autoformat,
Bold,
Italic,
Underline,
Strikethrough,
Code,
Subscript,
Superscript,
BlockQuote,
Heading,
Image,
ImageCaption,
ImageStyle,
ImageToolbar,
ImageResize,
Link,
List,
Paragraph,
Alignment,
Autosave,
Font,
PasteFromOffice,
SimpleUploadAdapter,
MediaEmbed,
RemoveFormat,
Table, TableToolbar,
TableCaption,
TableProperties,
TableCellProperties,
Indent,
IndentBlock,
Highlight,
TodoList,
ListProperties,
SourceEditing,
GeneralHtmlSupport,
ImageInsert,
WordCount,
Mention,
Markdown,
PageBreak,
Style,
HorizontalLine,
LinkImage,
HtmlEmbed,
FullPage,
SpecialCharacters,
SpecialCharactersEssentials,
ShowBlocks,
SelectAll,
FindAndReplace
];

View File

@ -0,0 +1,47 @@
/** Todo list **/
.ck .todo-list input {
padding: 0;
}
.ck .todo-list__checkmark:after {
height: 6px !important;
}
.ck .todo-list__checkmark {
padding: 0;
}
.ck.ck-content.ck-editor__editable {
min-height: 300px;
}
.ck h2 {
color: inherit;
background: inherit;
}
form .aligned .ck ul li {
list-style: inherit;
}
form .aligned .ck ul {
margin-left: 1.5em;
padding-left: inherit;
}
.ck-word-count{
display: flex;
margin-top: 10px;
}
.ck-word-count__words{
margin-right: 10px;
}
.ck.ck-editor {
position: relative;
width: 100%;
}
.ck-editor-container{
width: 100%;
}

View File

@ -0,0 +1,38 @@
/**
* @fileOverview CSS for jquery-autocomplete, the jQuery Autocompleter
* @author <a href="mailto:dylan@dyve.net">Dylan Verheul</a>
* @license MIT | GPL | Apache 2.0, see LICENSE.txt
* @see https://github.com/dyve/jquery-autocomplete
*/
.acResults {
padding: 0px;
border: 1px solid WindowFrame;
background-color: Window;
overflow: hidden;
}
.acResults ul {
margin: 0px;
padding: 0px;
list-style-position: outside;
list-style: none;
}
.acResults ul li {
margin: 0px;
padding: 2px 5px;
cursor: pointer;
display: block;
font: menu;
font-size: 12px;
overflow: hidden;
}
.acLoading {
background : url('../img/indicator.gif') right center no-repeat;
}
.acSelect {
background-color: Highlight;
color: HighlightText;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,116 @@
/**
* Ajax Queue Plugin
*/
/**
<script>
$(function(){
jQuery.ajaxQueue({
url: "test.php",
success: function(html){ jQuery("ul").append(html); }
});
jQuery.ajaxQueue({
url: "test.php",
success: function(html){ jQuery("ul").append(html); }
});
jQuery.ajaxSync({
url: "test.php",
success: function(html){ jQuery("ul").append("<b>"+html+"</b>"); }
});
jQuery.ajaxSync({
url: "test.php",
success: function(html){ jQuery("ul").append("<b>"+html+"</b>"); }
});
});
</script>
<ul style="position: absolute; top: 5px; right: 5px;"></ul>
*/
/*
* Queued Ajax requests.
* A new Ajax request won't be started until the previous queued
* request has finished.
*/
/*
* Synced Ajax requests.
* The Ajax request will happen as soon as you call this method, but
* the callbacks (success/error/complete) won't fire until all previous
* synced requests have been completed.
*/
(function(jQuery) {
var ajax = jQuery.ajax;
var pendingRequests = {};
var synced = [];
var syncedData = [];
jQuery.ajax = function(settings) {
// create settings for compatibility with ajaxSetup
settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings));
var port = settings.port;
switch(settings.mode) {
case "abort":
if ( pendingRequests[port] ) {
pendingRequests[port].abort();
}
return pendingRequests[port] = ajax.apply(this, arguments);
case "queue":
var _old = settings.complete;
settings.complete = function(){
if ( _old )
_old.apply( this, arguments );
jQuery([ajax]).dequeue("ajax" + port );;
};
jQuery([ ajax ]).queue("ajax" + port, function(){
ajax( settings );
});
return;
case "sync":
var pos = synced.length;
synced[ pos ] = {
error: settings.error,
success: settings.success,
complete: settings.complete,
done: false
};
syncedData[ pos ] = {
error: [],
success: [],
complete: []
};
settings.error = function(){ syncedData[ pos ].error = arguments; };
settings.success = function(){ syncedData[ pos ].success = arguments; };
settings.complete = function(){
syncedData[ pos ].complete = arguments;
synced[ pos ].done = true;
if ( pos == 0 || !synced[ pos-1 ] )
for ( var i = pos; i < synced.length && synced[i].done; i++ ) {
if ( synced[i].error ) synced[i].error.apply( jQuery, syncedData[i].error );
if ( synced[i].success ) synced[i].success.apply( jQuery, syncedData[i].success );
if ( synced[i].complete ) synced[i].complete.apply( jQuery, syncedData[i].complete );
synced[i] = null;
syncedData[i] = null;
}
};
}
return ajax.apply(this, arguments);
};
})((typeof window.jQuery == 'undefined' && typeof window.django != 'undefined')
? django.jQuery
: jQuery
);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
/*! Copyright (c) 2010 Brandon Aaron (http://brandon.aaron.sh/)
* Licensed under the MIT License (LICENSE.txt).
*
* Version 2.1.2
*/
(function($){
$.fn.bgiframe = ($.browser.msie && /msie 6\.0/i.test(navigator.userAgent) ? function(s) {
s = $.extend({
top : 'auto', // auto == .currentStyle.borderTopWidth
left : 'auto', // auto == .currentStyle.borderLeftWidth
width : 'auto', // auto == offsetWidth
height : 'auto', // auto == offsetHeight
opacity : true,
src : 'javascript:false;'
}, s);
var html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
'style="display:block;position:absolute;z-index:-1;'+
(s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
'"/>';
return this.each(function() {
if ( $(this).children('iframe.bgiframe').length === 0 )
this.insertBefore( document.createElement(html), this.firstChild );
});
} : function() { return this; });
// old alias
$.fn.bgIframe = $.fn.bgiframe;
function prop(n) {
return n && n.constructor === Number ? n + 'px' : n;
}
})((typeof window.jQuery == 'undefined' && typeof window.django != 'undefined') ? django.jQuery : jQuery);