В четверг, 7 мая, около 16 часов (MSK) регистратор заморозил домен «cyclowiki.org» без уведомления владельцев. Сайт недоступен из большинства стран. Правление изучает возможности решения проблемы.
MediaWiki:Gadget-AutoSave.js
Перейти к навигации
Перейти к поиску
Замечание: Возможно, после публикации вам придётся очистить кэш своего браузера, чтобы увидеть изменения.
- Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl+F5 или Ctrl+R (⌘+R на Mac)
- Google Chrome: Нажмите Ctrl+Shift+R (⌘+Shift+R на Mac)
- Internet Explorer / Edge: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl+F5
- Opera: Нажмите Ctrl+F5.
// =================================================
// === «Автосохранение вики-черновиков» ===
// === автор: Урахара из Циклопедии ===
// === лицензия: CC BY-SA 4.0 ===
// =================================================
// Работает даже на старых версиях MediaWiki (гарантированно — начиная с 1.19)
// Рабочей базой служил движок Mediawiki 1.39.1
// Не рассчитан для браузера Internet Explorer 10 и ниже
// Автосохранение срабатывает через 3 сек. после того, как вы перестали печатать
// При выходе со страницы сохранение происходит мгновенно (без задержки)
// Ручное сохранение (кнопка «Сохранить черновик» или Ctrl+S) тоже мгновенное
// Индикатор показывает «Редактирование…» пока вы печатаете, и иное по делу
// Работает даже без интернета (если страница уже загружена)
// Не нагружает сервер, обработка на стороне устройства пользователя
// Имеет защиту от ошибок — если что-то пойдёт не так, сломается только сам скрипт
// Сохраняется текст и несозданных новых статей (вбейте то же имя при воссоздании)
// При очистке кэша браузера всё равно сохраняет текст
// Текст исчезнет, если почистите историю браузера
// Текст исчезнет, если зайдёте в режим инкогнито и закроете окно
// Черновики старше 7 дней автоматически удаляются
// Браузер может удалить данные, если заполнится лимит сайта на хранилище
// ============ ЗАКОММЕНТИРОВАННЫЙ КОД ============
( function () {
'use strict';
// Проверяем, находимся ли мы на странице редактирования
if ( mw.config.get( 'wgAction' ) !== 'edit' && mw.config.get( 'wgAction' ) !== 'submit' ) {
return; // Не на странице редактирования - выходим
}
// Получаем название текущей страницы
var pageName = mw.config.get( 'wgPageName' ) || 'newpage';
var storageKey = 'wiki_draft_' + pageName;
var $textbox = $( '#wpTextbox1' );
if ( !$textbox.length ) {
console.log( 'AutoSave: Поле редактирования не найдено' );
return;
}
// Настройки
var config = {
saveDelay: 3000,
maxDraftAge: 7
};
// Состояние
var saveTimeout = null;
var lastSavedContent = '';
// Функция сохранения черновика
function saveDraft( silent ) {
var currentContent = $textbox.val();
if ( !currentContent || currentContent.trim() === '' ) {
console.log( 'AutoSave: Пустой контент, не сохраняем' );
return false;
}
if ( currentContent === lastSavedContent ) {
console.log( 'AutoSave: Контент не изменился' );
return false;
}
try {
var draftData = {
content: currentContent,
timestamp: Date.now(),
page: pageName
};
localStorage.setItem( storageKey, JSON.stringify( draftData ) );
lastSavedContent = currentContent;
console.log( 'AutoSave: Черновик сохранён', {
размер: currentContent.length,
время: new Date().toLocaleString()
} );
if ( !silent ) {
showNotification( 'Черновик сохранён', 'success' );
}
updateIndicator( 'saved' );
return true;
} catch ( e ) {
console.error( 'AutoSave: Ошибка сохранения', e );
showNotification( 'Ошибка сохранения черновика', 'error' );
return false;
}
}
// Функция уведомлений (простая, без зависимостей)
function showNotification( message, type ) {
if ( typeof mw.notify === 'function' ) {
mw.notify( message, {
type: type,
autoHide: true,
tag: 'autosave-notify'
} );
}
}
// Функция восстановления (без jQuery UI диалогов!)
function restoreDraft() {
try {
var saved = localStorage.getItem( storageKey );
if ( !saved ) {
console.log( 'AutoSave: Черновик не найден' );
return;
}
var draftData = JSON.parse( saved );
var currentContent = $textbox.val();
// Проверка страницы
if ( draftData.page !== pageName ) {
console.log( 'AutoSave: Черновик для другой страницы' );
return;
}
// Проверка возраста
var now = Date.now();
var daysOld = ( now - draftData.timestamp ) / ( 1000 * 60 * 60 * 24 );
console.log( 'AutoSave: Возраст черновика', daysOld.toFixed(1) + ' дней' );
if ( daysOld > config.maxDraftAge ) {
console.log( 'AutoSave: Черновик устарел, удаляем' );
localStorage.removeItem( storageKey );
return;
}
// Проверка совпадения
if ( draftData.content === currentContent ) {
console.log( 'AutoSave: Контент совпадает' );
lastSavedContent = currentContent;
return;
}
// Используем простой confirm вместо jQuery UI dialog
if ( confirm( 'Найден несохранённый черновик от ' +
new Date( draftData.timestamp ).toLocaleString() +
'. Восстановить?' ) ) {
$textbox.val( draftData.content );
lastSavedContent = draftData.content;
// Подсветка
$textbox.css( 'border', '2px solid #00af89' );
setTimeout( function() {
$textbox.css( 'border', '' );
}, 2000 );
showNotification( 'Черновик восстановлен', 'success' );
console.log( 'AutoSave: Черновик восстановлен' );
}
} catch ( e ) {
console.error( 'AutoSave: Ошибка восстановления', e );
}
}
// Кнопка сохранения
function addSaveButton() {
if ( $( '#autosave-save-btn' ).length ) return;
var $saveBtn = $( '<button>' )
.attr( 'id', 'autosave-save-btn' )
.text( 'Сохранить черновик' )
.addClass( 'mw-ui-button mw-ui-progressive' )
.css( 'margin-left', '10px' )
.click( function() {
var btn = this;
if ( saveDraft( false ) ) {
$( btn ).text( 'Сохранено!' );
setTimeout( function() {
$( btn ).text( 'Сохранить черновик' );
}, 2000 );
}
} );
$( '#wpSave' ).after( $saveBtn );
// Ctrl+S
$( document ).on( 'keydown', function( e ) {
if ( e.ctrlKey && e.key === 's' ) {
e.preventDefault();
$( '#autosave-save-btn' ).click();
}
} );
}
// Индикатор
function addStatusIndicator() {
if ( $( '#autosave-indicator' ).length ) return;
var $indicator = $( '<div>' )
.attr( 'id', 'autosave-indicator' )
.css( {
'font-size': '0.9em',
'margin': '5px 0',
'padding': '4px 8px',
'background': '#f8f9fa',
'border-radius': '2px'
} )
.text( 'Черновик не сохранён' );
$textbox.after( $indicator );
}
// Обновление индикатора
function updateIndicator( status ) {
var $indicator = $( '#autosave-indicator' );
if ( !$indicator.length ) return;
var messages = {
'saved': { text: 'Черновик сохранён', color: '#00af89' },
'editing': { text: 'Редактирование...', color: '#36c' },
'error': { text: 'Ошибка сохранения', color: '#d33' },
'idle': { text: 'Черновик не сохранён', color: '#72777d' }
};
var msg = messages[ status ] || messages.idle;
$indicator.text( msg.text ).css( 'color', msg.color );
}
// Очистка при сохранении
function clearOnSave() {
$( '#wpSave' ).on( 'click', function() {
localStorage.removeItem( storageKey );
updateIndicator( 'idle' );
console.log( 'AutoSave: Черновик очищен после сохранения' );
} );
}
// Автосохранение при вводе
$textbox.on( 'input', function() {
if ( saveTimeout ) {
clearTimeout( saveTimeout );
}
updateIndicator( 'editing' );
saveTimeout = setTimeout( function() {
saveDraft( true ); // silent mode
}, config.saveDelay );
} );
// При выходе
$( window ).on( 'beforeunload', function() {
var currentContent = $textbox.val();
if ( currentContent !== lastSavedContent && currentContent.trim() !== '' ) {
saveDraft( true );
}
} );
// Инициализация
$( document ).ready( function() {
console.log( 'AutoSave: Инициализация для страницы', pageName );
setTimeout( function() {
addSaveButton();
addStatusIndicator();
restoreDraft();
clearOnSave();
}, 500 );
console.log( 'AutoSave: Готов к работе' );
// Проверка localStorage
try {
localStorage.setItem( 'autosave_test', 'test' );
localStorage.removeItem( 'autosave_test' );
console.log( 'AutoSave: localStorage работает' );
} catch ( e ) {
console.error( 'AutoSave: localStorage недоступен', e );
}
} );
} )();