MediaWiki:Common.js: Różnice pomiędzy wersjami
Z LawRus
auto-sync z repo |
auto-sync z repo |
||
| (Nie pokazano 2 pośrednich wersji utworzonych przez tego samego użytkownika) | |||
| Linia 80: | Linia 80: | ||
setTimeout( window.lawrusTruncateAll, 300 ); | setTimeout( window.lawrusTruncateAll, 300 ); | ||
} ); | } ); | ||
function lawrusInitPdfButton() { | |||
var $entry = $( '.wpis-kroniki' ); | |||
if ( !$entry.length ) return; | |||
var $actions = $entry.find( '.lawrus-actions' ); | |||
if ( !$actions.length ) return; | |||
var $btn = $( '<button class="lawrus-pdf-btn" type="button">↓ Pobierz PDF</button>' ); | |||
$btn.on( 'click', function () { | |||
window.print(); | |||
} ); | |||
$actions.append( $btn ); | |||
} | |||
/* -- Lightbox dla zalacznikow graficznych ----------------------------------- | |||
Klik w miniaturke zalacznika (obraz) pokazuje pelny obraz w nakladce NA | |||
stronie wpisu, zamiast nawigowac do pliku. Zamkniecie: X / klik w tlo / Esc | |||
— uzytkownik wraca dokladnie na wpis. Bez JS link dziala normalnie (href to | |||
bezposredni URL pliku, ustawiony przez link={{filepath:}} w szablonie). */ | |||
function lawrusInitAttachmentLightbox() { | |||
$( document ).on( 'click', '.lawrus-attachment-img a', function ( e ) { | |||
var href = $( this ).attr( 'href' ); | |||
if ( !href ) return; | |||
e.preventDefault(); | |||
var alt = $( this ).find( 'img' ).attr( 'alt' ) || ''; | |||
var $overlay = $( | |||
'<div class="lawrus-lightbox-overlay" role="dialog" aria-modal="true" aria-label="Podgląd zdjęcia / Image preview">' + | |||
'<button type="button" class="lawrus-lightbox-close" aria-label="Zamknij / Close">×</button>' + | |||
'<img class="lawrus-lightbox-img" alt="">' + | |||
'</div>' | |||
); | |||
$overlay.find( '.lawrus-lightbox-img' ).attr( { src: href, alt: alt } ); | |||
function close() { | |||
$overlay.remove(); | |||
$( document ).off( 'keydown.lawrusLightbox' ); | |||
} | |||
// Klik w tlo lub w przycisk X zamyka; klik w sam obraz — nie. | |||
$overlay.on( 'click', function ( ev ) { | |||
if ( ev.target === this || $( ev.target ).hasClass( 'lawrus-lightbox-close' ) ) { | |||
close(); | |||
} | |||
} ); | |||
$( document ).on( 'keydown.lawrusLightbox', function ( ev ) { | |||
if ( ev.key === 'Escape' || ev.keyCode === 27 ) { | |||
close(); | |||
} | |||
} ); | |||
$( document.body ).append( $overlay ); | |||
} ); | |||
} | |||
/* -- Okienko wyboru jezyka (pierwsza wizyta) -------------------------------- | |||
Cookie lawrus_lang = pl|en. Czytane TEZ po stronie serwera (LocalSettings.php, | |||
hook BeforeInitialize) zeby przy kolejnych wejsciach od razu serwowac strone | |||
w wybranym jezyku interfejsu (uselang). Surowa nazwa cookie, bez prefiksu MW. */ | |||
function lawrusGetCookie( name ) { | |||
var m = document.cookie.match( '(?:^|; )' + name + '=([^;]*)' ); | |||
return m ? decodeURIComponent( m[ 1 ] ) : null; | |||
} | |||
function lawrusSetLangCookie( lang, persist ) { | |||
var c = 'lawrus_lang=' + lang + '; path=/; SameSite=Lax'; | |||
if ( persist ) { c += '; max-age=' + ( 60 * 60 * 24 * 365 ); } // 1 rok | |||
// bez max-age -> cookie sesyjne: zapyta przy nastepnym otwarciu przegladarki | |||
if ( window.location.protocol === 'https:' ) { c += '; Secure'; } | |||
document.cookie = c; | |||
} | |||
/* Jawny ?uselang=en|pl w URL = swiadomy wybor jezyka (przycisk LangSwitch na | |||
stronach statycznych/Katalog, przelacznik PL/EN we wpisie i w drilldownie). | |||
Zapisujemy go w cookie lawrus_lang, zeby serwer (BeforeInitialize) utrzymal ten | |||
jezyk takze przy kolejnej nawigacji -- inaczej menu MediaWiki (Nawigacja, Strona | |||
glowna...) wracaloby do PL po kliknieciu w pasek boczny (linki sidebara nie nosza | |||
uselang). Cookie roczne -- wybor jest swiadomy. Dziala dla anonimow (zalogowani | |||
maja jezyk w preferencjach konta). Po zapisie tlumi tez okienko pierwszej wizyty. */ | |||
function lawrusSyncLangCookie() { | |||
var ul = new URL( window.location.href ).searchParams.get( 'uselang' ); | |||
if ( ul !== 'en' && ul !== 'pl' ) { return; } | |||
if ( lawrusGetCookie( 'lawrus_lang' ) === ul ) { return; } | |||
lawrusSetLangCookie( ul, true ); | |||
} | |||
function lawrusInitLangPrompt() { | |||
// wgUserId jest null dla anonimow, liczba dla zalogowanych (ci maja | |||
// jezyk w preferencjach konta, nie pokazujemy im okienka). | |||
if ( mw.config.get( 'wgUserId' ) ) { return; } | |||
if ( lawrusGetCookie( 'lawrus_lang' ) ) { return; } // wybor juz zapisany | |||
var $overlay = $( | |||
'<div class="lawrus-lang-modal-overlay" role="dialog" aria-modal="true" aria-label="Choose language / Wybierz jezyk">' + | |||
'<div class="lawrus-lang-modal">' + | |||
'<p class="lawrus-lang-modal-title">Choose your language<br>Wybierz język</p>' + | |||
'<div class="lawrus-lang-modal-buttons">' + | |||
'<button type="button" data-lang="en">Continue in English</button>' + | |||
'<button type="button" data-lang="pl">Kontynuj po polsku</button>' + | |||
'</div>' + | |||
'<label class="lawrus-lang-modal-remember">' + | |||
'<input type="checkbox" id="lawrus-lang-remember"> ' + | |||
'Don’t show this message again / Nie pokazuj więcej tego komunikatu' + | |||
'</label>' + | |||
'</div>' + | |||
'</div>' | |||
); | |||
$overlay.on( 'click', 'button[data-lang]', function () { | |||
var lang = $( this ).data( 'lang' ); | |||
var persist = $overlay.find( '#lawrus-lang-remember' ).prop( 'checked' ); | |||
lawrusSetLangCookie( lang, persist ); | |||
// Zapisalismy preferencje w cookie -> przeladowujemy bez jawnego uselang, | |||
// zeby zadecydowal serwer (LocalSettings.php): dla EN ustawi interfejs | |||
// angielski I przekieruje polska strone statyczna na bliźniaka EN | |||
// (Strona główna -> Main Page itd.) -- dokladnie jak przycisk PL/EN. | |||
var url = new URL( window.location.href ); | |||
url.searchParams.delete( 'uselang' ); | |||
if ( url.toString() === window.location.href ) { | |||
// URL bez zmian (np. PL na stronie PL) -> serwer i tak nic nie zmieni, | |||
// wystarczy zamknac okienko. Dla EN URL tez sie nie zmieni, ale | |||
// przeladowanie jest potrzebne by serwer zadzialal -> wymuszamy nizej. | |||
if ( lang === 'en' ) { | |||
window.location.reload(); | |||
} else { | |||
$overlay.remove(); | |||
} | |||
} else { | |||
window.location.href = url.toString(); | |||
} | |||
} ); | |||
$( document.body ).append( $overlay ); | |||
} | |||
function lawrusInitLangSwitch() { | function lawrusInitLangSwitch() { | ||
| Linia 106: | Linia 241: | ||
var lang = $( this ).data( 'lang' ); | var lang = $( this ).data( 'lang' ); | ||
var url = new URL( window.location.href ); | var url = new URL( window.location.href ); | ||
// Jawny uselang (takze 'pl') zostawiamy w URL, zeby wygral z cookie | |||
// preferencji ustawionym przez okienko wyboru jezyka. | |||
url.searchParams.set( 'uselang', lang === 'en' ? 'en' : 'pl' ); | |||
window.location.href = url.toString(); | window.location.href = url.toString(); | ||
} ); | } ); | ||
| Linia 132: | Linia 265: | ||
var lang = $( this ).data( 'lang' ); | var lang = $( this ).data( 'lang' ); | ||
var url = new URL( window.location.href ); | var url = new URL( window.location.href ); | ||
// Jawny uselang (takze 'pl') wygrywa z cookie preferencji jezyka. | |||
url.searchParams.set( 'uselang', lang === 'en' ? 'en' : 'pl' ); | |||
window.location.href = url.toString(); | window.location.href = url.toString(); | ||
} ); | |||
} | |||
/* -- Dodawanie wpisu: duplikat nazwy + propozycja nowej nazwy ---------------- | |||
Na Specjalna:FormStart przed wysłaniem sprawdza, czy wpis o tej nazwie już | |||
istnieje. Jeśli tak — pyta: otworzyć istniejący czy utworzyć nowy. Dla nowego | |||
proponuje nazwę (wiodąca liczba +1, a gdy brak liczby — prefiks "0_") i wstawia | |||
ją do pola JAKO PROPOZYCJĘ — użytkownik może ją zmienić; nic nie dzieje się | |||
automatycznie. */ | |||
function lawrusEscapeRegex( s ) { | |||
return s.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' ); | |||
} | |||
/* Propozycja nazwy nowego wpisu na podstawie nazwy wpisanej i listy wszystkich | |||
tytułów (NS_MAIN). Reguły: | |||
- nazwa bez wiodącej liczby (np. "test") lub z prefiksem licznika i spacją | |||
(stare "0 test"): baza = nazwa bez prefiksu; szukamy najwyższego istniejącego | |||
"N-baza"/"N baza" i proponujemy (max+1)-baza (gdy brak — "0-baza"). Dzięki | |||
temu przy istniejących "test" i "0-test" propozycją jest "1-test". | |||
Separator dodajemy jako MYŚLNIK "-" — MediaWiki NIE zamienia go na spację | |||
(w przeciwieństwie do "_"), więc pozostaje widoczny w tytule. | |||
- nazwa "rocznikowa"/z wiodącą liczbą (np. "1022-Rus-Prawda", "0-test"): | |||
wiodąca liczba +1 (liczba znacząca = rok lub kolejny numer). */ | |||
function lawrusProposeEntryName( name, titles ) { | |||
// MediaWiki traktuje "_" i spację w tytułach równoważnie i zwraca formę ze | |||
// spacjami (allpages: "0_test" -> "0 test"). Normalizujemy "_" do spacji. | |||
var norm = function ( s ) { return String( s ).replace( /_/g, ' ' ).trim(); }; | |||
var nName = norm( name ); | |||
var base; | |||
var pm = nName.match( /^\d+\s+([\s\S]+)$/ ); // stara forma "N baza" (separator: spacja/_) | |||
if ( pm ) { | |||
base = pm[ 1 ]; | |||
} else if ( /^\d/.test( nName ) ) { | |||
// wiodąca liczba (rocznik "1022-Rus-Prawda" lub licznik "0-test") -> +1 | |||
var ym = nName.match( /^(\d+)([\s\S]*)$/ ); | |||
return ( parseInt( ym[ 1 ], 10 ) + 1 ) + ym[ 2 ]; | |||
} else { | |||
base = nName; | |||
} | |||
// Najwyższe istniejące "N-baza" / "N baza" (separator: myślnik lub spacja/_). | |||
var re = new RegExp( '^(\\d+)[\\s-]+' + lawrusEscapeRegex( base ) + '$', 'i' ); | |||
var max = -1; | |||
( titles || [] ).forEach( function ( t ) { | |||
var m = norm( t ).match( re ); | |||
if ( m ) { max = Math.max( max, parseInt( m[ 1 ], 10 ) ); } | |||
} ); | |||
return ( max + 1 ) + '-' + base; | |||
} | |||
function lawrusInitFormStartGuard() { | |||
if ( mw.config.get( 'wgCanonicalSpecialPageName' ) !== 'FormStart' ) { return; } | |||
var $form = $( '.pfFormInputWrapper' ).closest( 'form' ); | |||
if ( !$form.length ) { return; } | |||
function askDuplicate( name, $input ) { | |||
var safe = mw.html.escape( name ); | |||
var $overlay = $( | |||
'<div class="lawrus-lang-modal-overlay" role="dialog" aria-modal="true">' + | |||
'<div class="lawrus-lang-modal">' + | |||
'<p class="lawrus-lang-modal-title">' + | |||
'Wpis „' + safe + '” już istnieje.<br>' + | |||
'An entry named “' + safe + '” already exists.' + | |||
'</p>' + | |||
'<div class="lawrus-lang-modal-buttons">' + | |||
'<button type="button" data-act="existing">Otwórz istniejący / Open existing</button>' + | |||
'<button type="button" data-act="new">Utwórz nowy / Create new</button>' + | |||
'</div>' + | |||
'<label class="lawrus-lang-modal-remember">' + | |||
'<a href="#" data-act="cancel">Anuluj / Cancel</a>' + | |||
'</label>' + | |||
'</div>' + | |||
'</div>' | |||
); | |||
$overlay.on( 'click', '[data-act]', function ( e ) { | |||
e.preventDefault(); | |||
var act = $( this ).data( 'act' ); | |||
$overlay.remove(); | |||
if ( act === 'existing' ) { | |||
$form[ 0 ].submit(); // natywny submit pomija ten handler -> edycja istniejącego | |||
} else if ( act === 'new' ) { | |||
// tylko propozycja — pobierz wszystkie tytuły, policz rodzeństwo | |||
// "N_baza" i wstaw propozycję do pola (użytkownik może ją zmienić). | |||
var applyProposal = function ( titles ) { | |||
$input.val( lawrusProposeEntryName( name, titles ) ) | |||
.trigger( 'input' ).trigger( 'change' ).trigger( 'focus' ); | |||
}; | |||
new mw.Api().get( { | |||
action: 'query', list: 'allpages', apnamespace: 0, | |||
aplimit: 'max', formatversion: 2 | |||
} ).done( function ( d ) { | |||
var titles = ( ( d.query && d.query.allpages ) || [] ) | |||
.map( function ( p ) { return p.title; } ); | |||
applyProposal( titles ); | |||
} ).fail( function () { | |||
applyProposal( [] ); | |||
} ); | |||
} | |||
} ); | |||
$( document.body ).append( $overlay ); | |||
} | |||
$form.on( 'submit', function ( e ) { | |||
var $input = $form.find( 'input[name="page_name"]' ); | |||
var name = $.trim( $input.val() || '' ); | |||
if ( name === '' ) { return; } // puste — niech obsłuży PHP | |||
e.preventDefault(); | |||
mw.loader.using( 'mediawiki.api' ).done( function () { | |||
new mw.Api().get( { | |||
action: 'query', titles: name, formatversion: 2 | |||
} ).done( function ( data ) { | |||
var pages = ( data.query && data.query.pages ) || []; | |||
var exists = pages.length && !pages[ 0 ].missing && !pages[ 0 ].invalid; | |||
if ( exists ) { | |||
askDuplicate( name, $input ); | |||
} else { | |||
$form[ 0 ].submit(); // wolna nazwa — twórz nowy | |||
} | |||
} ).fail( function () { | |||
$form[ 0 ].submit(); // błąd API — nie blokuj użytkownika | |||
} ); | |||
} ); | |||
} ); | } ); | ||
} | } | ||
| Linia 176: | Linia 431: | ||
console.log( '[LawRus] Common.js: document.ready, ns=' + mw.config.get( 'wgNamespaceNumber' ) ); | console.log( '[LawRus] Common.js: document.ready, ns=' + mw.config.get( 'wgNamespaceNumber' ) ); | ||
lawrusSyncLangCookie(); | |||
lawrusInitLangPrompt(); | |||
lawrusInitFormStartGuard(); | |||
lawrusInitPdfButton(); | |||
lawrusInitAttachmentLightbox(); | |||
lawrusInitLangSwitch(); | lawrusInitLangSwitch(); | ||
lawrusInitDrilldownLangSwitch(); | lawrusInitDrilldownLangSwitch(); | ||
Aktualna wersja na dzień 09:12, 22 cze 2026
/* --- LawRus -- Common.js ---------------------------------------------------
1. Przenoszenie sekcji uczestnikow pod wlasciwe sekcje Umow w formularzu.
2. Walidacja formularza WpisKroniki przed zapisem (status >= 4).
3. Skracanie streszczenia w tabelach Cargo do 100 znakow + rozwin.
-------------------------------------------------------------------------- */
/* DataTables: wylacz autoWidth zanim Cargo zainicjuje tabele.
preInit.dt odpala przed kazdym new DataTable() -- niezaleznie od kolejnosci
ladowania modulow. Bez tego DataTables nadpisuje inline-style'em nasze
CSS-owe szerokosci kolumn. */
$( document ).on( 'preInit.dt', function ( e, settings ) {
settings.oFeatures.bAutoWidth = false;
if ( !$( settings.nTable ).hasClass( 'cargoDynamicTable' ) ) { return; }
/* Usun separatory tysiecy z kolumn roku (dodawane przez formatNum w EN locale).
Lapi "1,888" / "1 888" / "1 888" -- zwraca "1888". */
var stripThousands = function ( data ) {
if ( !data && data !== 0 ) { return data; }
return String( data ).replace( /^(\d{1,3})[, ](\d{3})$/, '$1$2' );
};
settings.aoColumnDefs = settings.aoColumnDefs || [];
settings.aoColumnDefs.push( {
targets: [ 3, 4 ],
render: stripThousands
} );
} );
/* -- Skracanie streszczenia -------------------------------------------------
Kolumna streszczenie = zawsze td:nth-child(2) w kazdym LawRus cargo query.
Przypisanie do window.lawrusTruncateAll pozwala wywolac ja z konsoli. */
window.lawrusTruncateAll = function () {
$( 'table.cargoDynamicTable tbody tr' ).each( function () {
var $td = $( this ).children( 'td' ).eq( 1 );
if ( !$td.length ) { return; }
if ( $td.find( '.lawrus-short' ).length ) { return; }
var text = $td.text().replace( /\s+/g, ' ' ).trim();
if ( text.length <= 100 ) { return; }
var e = function ( s ) {
return s.replace( /&/g, '&' )
.replace( /</g, '<' )
.replace( />/g, '>' );
};
$td.html(
'<span class="lawrus-short">' +
e( text.substring( 0, 100 ) ) +
'<a href="#" class="lawrus-more" style="color:#3366cc;cursor:pointer;margin-left:2px">…</a>' +
'</span>' +
'<span class="lawrus-full-wrap" style="display:none">' +
e( text ) +
' <a href="#" class="lawrus-less" style="color:#3366cc;cursor:pointer">↑</a>' +
'</span>'
);
} );
};
/* draw.dt -- kazdy redraw DataTables (init, sort, filtr, paginacja) */
$( document ).on( 'draw.dt', window.lawrusTruncateAll );
/* Klikniecia -- delegowane, niezalezne od DataTables */
$( document ).on( 'click', '.lawrus-more', function ( e ) {
e.preventDefault();
var $td = $( this ).closest( 'td' );
$td.find( '.lawrus-short' ).hide();
$td.find( '.lawrus-full-wrap' ).show();
} );
$( document ).on( 'click', '.lawrus-less', function ( e ) {
e.preventDefault();
var $td = $( this ).closest( 'td' );
$td.find( '.lawrus-full-wrap' ).hide();
$td.find( '.lawrus-short' ).show();
} );
/* window.load -- odpala po zaladowaniu WSZYSTKICH zasobow strony (DataTables
na pewno gotowe do tego momentu). */
$( window ).on( 'load', function () {
window.lawrusTruncateAll();
setTimeout( window.lawrusTruncateAll, 300 );
} );
function lawrusInitPdfButton() {
var $entry = $( '.wpis-kroniki' );
if ( !$entry.length ) return;
var $actions = $entry.find( '.lawrus-actions' );
if ( !$actions.length ) return;
var $btn = $( '<button class="lawrus-pdf-btn" type="button">↓ Pobierz PDF</button>' );
$btn.on( 'click', function () {
window.print();
} );
$actions.append( $btn );
}
/* -- Lightbox dla zalacznikow graficznych -----------------------------------
Klik w miniaturke zalacznika (obraz) pokazuje pelny obraz w nakladce NA
stronie wpisu, zamiast nawigowac do pliku. Zamkniecie: X / klik w tlo / Esc
— uzytkownik wraca dokladnie na wpis. Bez JS link dziala normalnie (href to
bezposredni URL pliku, ustawiony przez link={{filepath:}} w szablonie). */
function lawrusInitAttachmentLightbox() {
$( document ).on( 'click', '.lawrus-attachment-img a', function ( e ) {
var href = $( this ).attr( 'href' );
if ( !href ) return;
e.preventDefault();
var alt = $( this ).find( 'img' ).attr( 'alt' ) || '';
var $overlay = $(
'<div class="lawrus-lightbox-overlay" role="dialog" aria-modal="true" aria-label="Podgląd zdjęcia / Image preview">' +
'<button type="button" class="lawrus-lightbox-close" aria-label="Zamknij / Close">×</button>' +
'<img class="lawrus-lightbox-img" alt="">' +
'</div>'
);
$overlay.find( '.lawrus-lightbox-img' ).attr( { src: href, alt: alt } );
function close() {
$overlay.remove();
$( document ).off( 'keydown.lawrusLightbox' );
}
// Klik w tlo lub w przycisk X zamyka; klik w sam obraz — nie.
$overlay.on( 'click', function ( ev ) {
if ( ev.target === this || $( ev.target ).hasClass( 'lawrus-lightbox-close' ) ) {
close();
}
} );
$( document ).on( 'keydown.lawrusLightbox', function ( ev ) {
if ( ev.key === 'Escape' || ev.keyCode === 27 ) {
close();
}
} );
$( document.body ).append( $overlay );
} );
}
/* -- Okienko wyboru jezyka (pierwsza wizyta) --------------------------------
Cookie lawrus_lang = pl|en. Czytane TEZ po stronie serwera (LocalSettings.php,
hook BeforeInitialize) zeby przy kolejnych wejsciach od razu serwowac strone
w wybranym jezyku interfejsu (uselang). Surowa nazwa cookie, bez prefiksu MW. */
function lawrusGetCookie( name ) {
var m = document.cookie.match( '(?:^|; )' + name + '=([^;]*)' );
return m ? decodeURIComponent( m[ 1 ] ) : null;
}
function lawrusSetLangCookie( lang, persist ) {
var c = 'lawrus_lang=' + lang + '; path=/; SameSite=Lax';
if ( persist ) { c += '; max-age=' + ( 60 * 60 * 24 * 365 ); } // 1 rok
// bez max-age -> cookie sesyjne: zapyta przy nastepnym otwarciu przegladarki
if ( window.location.protocol === 'https:' ) { c += '; Secure'; }
document.cookie = c;
}
/* Jawny ?uselang=en|pl w URL = swiadomy wybor jezyka (przycisk LangSwitch na
stronach statycznych/Katalog, przelacznik PL/EN we wpisie i w drilldownie).
Zapisujemy go w cookie lawrus_lang, zeby serwer (BeforeInitialize) utrzymal ten
jezyk takze przy kolejnej nawigacji -- inaczej menu MediaWiki (Nawigacja, Strona
glowna...) wracaloby do PL po kliknieciu w pasek boczny (linki sidebara nie nosza
uselang). Cookie roczne -- wybor jest swiadomy. Dziala dla anonimow (zalogowani
maja jezyk w preferencjach konta). Po zapisie tlumi tez okienko pierwszej wizyty. */
function lawrusSyncLangCookie() {
var ul = new URL( window.location.href ).searchParams.get( 'uselang' );
if ( ul !== 'en' && ul !== 'pl' ) { return; }
if ( lawrusGetCookie( 'lawrus_lang' ) === ul ) { return; }
lawrusSetLangCookie( ul, true );
}
function lawrusInitLangPrompt() {
// wgUserId jest null dla anonimow, liczba dla zalogowanych (ci maja
// jezyk w preferencjach konta, nie pokazujemy im okienka).
if ( mw.config.get( 'wgUserId' ) ) { return; }
if ( lawrusGetCookie( 'lawrus_lang' ) ) { return; } // wybor juz zapisany
var $overlay = $(
'<div class="lawrus-lang-modal-overlay" role="dialog" aria-modal="true" aria-label="Choose language / Wybierz jezyk">' +
'<div class="lawrus-lang-modal">' +
'<p class="lawrus-lang-modal-title">Choose your language<br>Wybierz język</p>' +
'<div class="lawrus-lang-modal-buttons">' +
'<button type="button" data-lang="en">Continue in English</button>' +
'<button type="button" data-lang="pl">Kontynuj po polsku</button>' +
'</div>' +
'<label class="lawrus-lang-modal-remember">' +
'<input type="checkbox" id="lawrus-lang-remember"> ' +
'Don’t show this message again / Nie pokazuj więcej tego komunikatu' +
'</label>' +
'</div>' +
'</div>'
);
$overlay.on( 'click', 'button[data-lang]', function () {
var lang = $( this ).data( 'lang' );
var persist = $overlay.find( '#lawrus-lang-remember' ).prop( 'checked' );
lawrusSetLangCookie( lang, persist );
// Zapisalismy preferencje w cookie -> przeladowujemy bez jawnego uselang,
// zeby zadecydowal serwer (LocalSettings.php): dla EN ustawi interfejs
// angielski I przekieruje polska strone statyczna na bliźniaka EN
// (Strona główna -> Main Page itd.) -- dokladnie jak przycisk PL/EN.
var url = new URL( window.location.href );
url.searchParams.delete( 'uselang' );
if ( url.toString() === window.location.href ) {
// URL bez zmian (np. PL na stronie PL) -> serwer i tak nic nie zmieni,
// wystarczy zamknac okienko. Dla EN URL tez sie nie zmieni, ale
// przeladowanie jest potrzebne by serwer zadzialal -> wymuszamy nizej.
if ( lang === 'en' ) {
window.location.reload();
} else {
$overlay.remove();
}
} else {
window.location.href = url.toString();
}
} );
$( document.body ).append( $overlay );
}
function lawrusInitLangSwitch() {
var $entries = $( '.wpis-kroniki' );
if ( !$entries.length ) return;
var isEn = ( mw.config.get( 'wgUserLanguage' ) === 'en' );
$entries.each( function () {
var $entry = $( this );
if ( !$entry.find( '.lawrus-lang-pl, .lawrus-lang-en' ).length ) return;
if ( isEn ) {
$entry.addClass( 'lang-en' );
}
var $sw = $(
'<div class="lawrus-lang-switch">' +
'<button data-lang="pl"' + ( !isEn ? ' class="active"' : '' ) + '>PL</button>' +
'<button data-lang="en"' + ( isEn ? ' class="active"' : '' ) + '>EN</button>' +
'</div>'
);
$entry.prepend( $sw );
$sw.on( 'click', 'button', function () {
var lang = $( this ).data( 'lang' );
var url = new URL( window.location.href );
// Jawny uselang (takze 'pl') zostawiamy w URL, zeby wygral z cookie
// preferencji ustawionym przez okienko wyboru jezyka.
url.searchParams.set( 'uselang', lang === 'en' ? 'en' : 'pl' );
window.location.href = url.toString();
} );
} );
}
function lawrusInitDrilldownLangSwitch() {
if ( mw.config.get( 'wgCanonicalSpecialPageName' ) !== 'Drilldown' ) return;
var isEn = ( mw.config.get( 'wgUserLanguage' ) === 'en' );
var $sw = $(
'<div class="lawrus-lang-switch" style="margin-bottom:1em;">' +
'<button data-lang="pl"' + ( !isEn ? ' class="active"' : '' ) + '>PL</button>' +
'<button data-lang="en"' + ( isEn ? ' class="active"' : '' ) + '>EN</button>' +
'</div>'
);
$( '#mw-content-text' ).prepend( $sw );
$sw.on( 'click', 'button', function () {
var lang = $( this ).data( 'lang' );
var url = new URL( window.location.href );
// Jawny uselang (takze 'pl') wygrywa z cookie preferencji jezyka.
url.searchParams.set( 'uselang', lang === 'en' ? 'en' : 'pl' );
window.location.href = url.toString();
} );
}
/* -- Dodawanie wpisu: duplikat nazwy + propozycja nowej nazwy ----------------
Na Specjalna:FormStart przed wysłaniem sprawdza, czy wpis o tej nazwie już
istnieje. Jeśli tak — pyta: otworzyć istniejący czy utworzyć nowy. Dla nowego
proponuje nazwę (wiodąca liczba +1, a gdy brak liczby — prefiks "0_") i wstawia
ją do pola JAKO PROPOZYCJĘ — użytkownik może ją zmienić; nic nie dzieje się
automatycznie. */
function lawrusEscapeRegex( s ) {
return s.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );
}
/* Propozycja nazwy nowego wpisu na podstawie nazwy wpisanej i listy wszystkich
tytułów (NS_MAIN). Reguły:
- nazwa bez wiodącej liczby (np. "test") lub z prefiksem licznika i spacją
(stare "0 test"): baza = nazwa bez prefiksu; szukamy najwyższego istniejącego
"N-baza"/"N baza" i proponujemy (max+1)-baza (gdy brak — "0-baza"). Dzięki
temu przy istniejących "test" i "0-test" propozycją jest "1-test".
Separator dodajemy jako MYŚLNIK "-" — MediaWiki NIE zamienia go na spację
(w przeciwieństwie do "_"), więc pozostaje widoczny w tytule.
- nazwa "rocznikowa"/z wiodącą liczbą (np. "1022-Rus-Prawda", "0-test"):
wiodąca liczba +1 (liczba znacząca = rok lub kolejny numer). */
function lawrusProposeEntryName( name, titles ) {
// MediaWiki traktuje "_" i spację w tytułach równoważnie i zwraca formę ze
// spacjami (allpages: "0_test" -> "0 test"). Normalizujemy "_" do spacji.
var norm = function ( s ) { return String( s ).replace( /_/g, ' ' ).trim(); };
var nName = norm( name );
var base;
var pm = nName.match( /^\d+\s+([\s\S]+)$/ ); // stara forma "N baza" (separator: spacja/_)
if ( pm ) {
base = pm[ 1 ];
} else if ( /^\d/.test( nName ) ) {
// wiodąca liczba (rocznik "1022-Rus-Prawda" lub licznik "0-test") -> +1
var ym = nName.match( /^(\d+)([\s\S]*)$/ );
return ( parseInt( ym[ 1 ], 10 ) + 1 ) + ym[ 2 ];
} else {
base = nName;
}
// Najwyższe istniejące "N-baza" / "N baza" (separator: myślnik lub spacja/_).
var re = new RegExp( '^(\\d+)[\\s-]+' + lawrusEscapeRegex( base ) + '$', 'i' );
var max = -1;
( titles || [] ).forEach( function ( t ) {
var m = norm( t ).match( re );
if ( m ) { max = Math.max( max, parseInt( m[ 1 ], 10 ) ); }
} );
return ( max + 1 ) + '-' + base;
}
function lawrusInitFormStartGuard() {
if ( mw.config.get( 'wgCanonicalSpecialPageName' ) !== 'FormStart' ) { return; }
var $form = $( '.pfFormInputWrapper' ).closest( 'form' );
if ( !$form.length ) { return; }
function askDuplicate( name, $input ) {
var safe = mw.html.escape( name );
var $overlay = $(
'<div class="lawrus-lang-modal-overlay" role="dialog" aria-modal="true">' +
'<div class="lawrus-lang-modal">' +
'<p class="lawrus-lang-modal-title">' +
'Wpis „' + safe + '” już istnieje.<br>' +
'An entry named “' + safe + '” already exists.' +
'</p>' +
'<div class="lawrus-lang-modal-buttons">' +
'<button type="button" data-act="existing">Otwórz istniejący / Open existing</button>' +
'<button type="button" data-act="new">Utwórz nowy / Create new</button>' +
'</div>' +
'<label class="lawrus-lang-modal-remember">' +
'<a href="#" data-act="cancel">Anuluj / Cancel</a>' +
'</label>' +
'</div>' +
'</div>'
);
$overlay.on( 'click', '[data-act]', function ( e ) {
e.preventDefault();
var act = $( this ).data( 'act' );
$overlay.remove();
if ( act === 'existing' ) {
$form[ 0 ].submit(); // natywny submit pomija ten handler -> edycja istniejącego
} else if ( act === 'new' ) {
// tylko propozycja — pobierz wszystkie tytuły, policz rodzeństwo
// "N_baza" i wstaw propozycję do pola (użytkownik może ją zmienić).
var applyProposal = function ( titles ) {
$input.val( lawrusProposeEntryName( name, titles ) )
.trigger( 'input' ).trigger( 'change' ).trigger( 'focus' );
};
new mw.Api().get( {
action: 'query', list: 'allpages', apnamespace: 0,
aplimit: 'max', formatversion: 2
} ).done( function ( d ) {
var titles = ( ( d.query && d.query.allpages ) || [] )
.map( function ( p ) { return p.title; } );
applyProposal( titles );
} ).fail( function () {
applyProposal( [] );
} );
}
} );
$( document.body ).append( $overlay );
}
$form.on( 'submit', function ( e ) {
var $input = $form.find( 'input[name="page_name"]' );
var name = $.trim( $input.val() || '' );
if ( name === '' ) { return; } // puste — niech obsłuży PHP
e.preventDefault();
mw.loader.using( 'mediawiki.api' ).done( function () {
new mw.Api().get( {
action: 'query', titles: name, formatversion: 2
} ).done( function ( data ) {
var pages = ( data.query && data.query.pages ) || [];
var exists = pages.length && !pages[ 0 ].missing && !pages[ 0 ].invalid;
if ( exists ) {
askDuplicate( name, $input );
} else {
$form[ 0 ].submit(); // wolna nazwa — twórz nowy
}
} ).fail( function () {
$form[ 0 ].submit(); // błąd API — nie blokuj użytkownika
} );
} );
} );
}
function lawrusReorderParticipants() {
/* PageForms wymaga, zeby bloki {{{for template|...|multiple}}} byly poza
glownym szablonem -- przez to div#lawrus-uczestnicy-* laduje na dole
formularza. Przenosimy je bezposrednio pod odpowiednie sekcje 3/4.
Uzywamy detach()+insertAfter() zeby zachowac event-handlery jQuery.
v2 -- wywolanie przez setTimeout(0) gwarantuje uruchomienie po PageForms. */
var $sec3 = $( '#lawrus-sec3' );
var $sec4 = $( '#lawrus-sec4' );
var $krajowa = $( '#lawrus-uczestnicy-krajowa' );
var $miedz = $( '#lawrus-uczestnicy-miedz' );
if ( $sec3.length && $krajowa.length ) {
$krajowa.detach().insertAfter( $sec3 );
}
if ( $sec4.length && $miedz.length ) {
$miedz.detach().insertAfter( $sec4 );
}
}
/* -- LawRusWorkflow: CSRF token injection ------------------------------------
Wypelnia pole wptoken w formularzach .lawrus-action-form tokenem sesji.
Musi dzialac przed wyslaniem formularza -- ladowanie synchroniczne z mw.loader. */
mw.loader.using( 'mediawiki.user' ).done( function () {
var token = mw.user.tokens.get( 'csrfToken' );
$( document ).on( 'submit', '.lawrus-action-form', function () {
$( this ).find( 'input[name="wptoken"]' ).val( token );
} );
// Wypelnij od razu przy ladowaniu (dla formularzy juz widocznych)
$( '.lawrus-action-form input[name="wptoken"]' ).val( token );
} );
$( function () {
console.log( '[LawRus] Common.js: document.ready, ns=' + mw.config.get( 'wgNamespaceNumber' ) );
lawrusSyncLangCookie();
lawrusInitLangPrompt();
lawrusInitFormStartGuard();
lawrusInitPdfButton();
lawrusInitAttachmentLightbox();
lawrusInitLangSwitch();
lawrusInitDrilldownLangSwitch();
if ( mw.config.get( 'wgUserName' ) ) {
$( 'body' ).addClass( 'lawrus-zalogowany' );
}
if ( $( '#lawrus-uczestnicy-krajowa' ).length ) {
setTimeout( lawrusReorderParticipants, 0 );
}
/* Timeouty -- pokrywaja rozne scenariusze async ladowania Cargo/DataTables */
window.lawrusTruncateAll();
setTimeout( window.lawrusTruncateAll, 300 );
setTimeout( window.lawrusTruncateAll, 800 );
setTimeout( window.lawrusTruncateAll, 2000 );
/* -- Walidacja przed zapisem (tylko formularz WpisKroniki) -- */
var $form = $( '#pfForm' );
if ( !$form.length ) return;
var REQUIRED_AT_4 = [
{ id: 'input_datacja_rok_lacinski', label: 'Rok AD' },
{ id: 'input_jezyk_oryginalu', label: 'Jezyk oryginalu' },
{ id: 'input_kraj', label: 'Kraj' },
{ id: 'input_tekst_zrodlowy', label: 'Tekst zrodlowy' },
{ id: 'input_bibliografia', label: 'Bibliografia' },
{ id: 'input_streszczenie_pl', label: 'Streszczenie PL' },
{ id: 'input_streszczenie_en', label: 'Streszczenie EN' },
{ id: 'input_tlumaczenie_pl', label: 'Tlumaczenie PL' },
{ id: 'input_tlumaczenie_en', label: 'Tlumaczenie EN' }
];
var HIGH_STATUS = [ '4-do-publikacji', '5-opublikowane' ];
$form.on( 'submit', function ( e ) {
var status = $( '#input_status_wpisu' ).val() || '';
if ( HIGH_STATUS.indexOf( status ) === -1 ) return;
var missing = REQUIRED_AT_4.filter( function ( f ) {
return ( $( '#' + f.id ).val() || '' ).trim() === '';
} );
if ( $( '[id^="input_typ_wpisu_"]:checked' ).length === 0 ) {
missing.push( { id: null, label: 'Typ wpisu' } );
}
if ( missing.length === 0 ) return;
e.preventDefault();
var names = missing.map( function ( f ) { return f.label; } ).join( ', ' );
mw.loader.using( 'mediawiki.notification' ).then( function () {
mw.notify(
'Przy statusie "' + status + '" wymagane sa: ' + names + '. Uzupelnij przed zapisem.',
{ type: 'error', autoHide: false, tag: 'lawrus-validation' }
);
} );
missing.forEach( function ( f ) {
if ( f.id ) { $( '#' + f.id ).css( 'border-color', '#d33' ); }
} );
missing.forEach( function ( f ) {
if ( f.id ) {
$( '#' + f.id ).one( 'input', function () {
$( this ).css( 'border-color', '' );
} );
}
} );
} );
} );
