MediaWiki:Common.js: Porovnání verzí
MediaWiki interface page
More actions
Bez shrnutí editace |
Bez shrnutí editace |
||
| Řádek 6: | Řádek 6: | ||
}); | }); | ||
/* Mini-toolbar pro textarea ve VisualEditoru (robustní varianta) */ | |||
(function () { | (function () { | ||
// ---- util ---- | |||
function replaceRange(input, start, end, str) { | function replaceRange(input, start, end, str) { | ||
const v = input.value; | const v = input.value; | ||
input.value = v.slice(0, start) + str + v.slice(end); | input.value = v.slice(0, start) + str + v.slice(end); | ||
const pos = start + str.length; | const pos = start + str.length; | ||
input.focus(); | input.focus(); input.setSelectionRange(pos, pos); | ||
} | } | ||
function toggleWrap(input, before, after) { | function toggleWrap(input, before, after) { | ||
const s = input.selectionStart, e = input.selectionEnd | const s = input.selectionStart, e = input.selectionEnd, v = input.value; | ||
const hasBefore = s >= before.length && v.slice(s - before.length, s) === before; | const hasBefore = s >= before.length && v.slice(s - before.length, s) === before; | ||
const hasAfter = v.slice(e, e + after.length) === after; | const hasAfter = v.slice(e, e + after.length) === after; | ||
if (hasBefore && hasAfter) { | if (hasBefore && hasAfter) { | ||
const inner = v.slice(s, e); | const inner = v.slice(s, e); | ||
input.value = v.slice(0, s - before.length) + inner + v.slice(e + after.length); | input.value = v.slice(0, s - before.length) + inner + v.slice(e + after.length); | ||
const | const ns = s - before.length, ne = ns + inner.length; | ||
input.focus(); input.setSelectionRange(ns, ne); | |||
input.focus(); | |||
} else { | } else { | ||
input.value = v.slice(0, s) + before + v.slice(s, e) + after + v.slice(e); | input.value = v.slice(0, s) + before + v.slice(s, e) + after + v.slice(e); | ||
const pos = e + before.length + after.length; | const pos = e + before.length + after.length; | ||
input.focus(); | input.focus(); input.setSelectionRange(pos, pos); | ||
} | } | ||
} | } | ||
function getLineRange(input) { | function getLineRange(input) { | ||
const v = input.value | const v = input.value, s = input.selectionStart, e = input.selectionEnd; | ||
const start = v.lastIndexOf('\n', s - 1) + 1; | const start = v.lastIndexOf('\n', s - 1) + 1; | ||
const end = (v.indexOf('\n', e) + 1) || v.length; | const end = (v.indexOf('\n', e) + 1) || v.length; | ||
return { start, end, text: v.slice(start, end) }; | return { start, end, text: v.slice(start, end) }; | ||
} | } | ||
function setLines(input, range, newText) { | function setLines(input, range, newText) { replaceRange(input, range.start, range.end, newText); } | ||
function stripAnyHeading(line) { | |||
const m = line.match(/^\s*(=+)\s*(.*?)\s*(=+)\s*$/); | |||
return (m && m[1] && m[3]) ? m[2] : line; | |||
} | } | ||
function toggleHeading(input, level) { | |||
function | const r = getLineRange(input), open = '='.repeat(level)+' ', close = ' '+ '='.repeat(level); | ||
const r = getLineRange(input); | |||
const lines = r.text.replace(/\n$/, '').split('\n'); | const lines = r.text.replace(/\n$/, '').split('\n'); | ||
const | const out = lines.map(l=>{ | ||
if (l.trim()==='') return l; | |||
const isThis = l.startsWith(open) && l.trimEnd().endsWith(close); | |||
return | return isThis ? stripAnyHeading(l) : open + stripAnyHeading(l) + close; | ||
}).join('\n') + (r.text.endsWith('\n') ? '\n' : ''); | }).join('\n') + (r.text.endsWith('\n') ? '\n' : ''); | ||
setLines(input, r, | setLines(input, r, out); | ||
} | } | ||
function toggleBullets(input){ | |||
function | |||
const r = getLineRange(input); | const r = getLineRange(input); | ||
const lines = r.text.replace(/\n$/, '').split('\n'); | const lines = r.text.replace(/\n$/, '').split('\n'); | ||
const | const allBulleted = lines.filter(l=>l.trim()!=='').every(l=>l.startsWith('* ')); | ||
const out = lines.map(l=>{ | |||
if (l.trim()==='') return l; | |||
return allBulleted ? l.replace(/^\* /,'') : '* ' + l; | |||
if ( | |||
return | |||
}).join('\n') + (r.text.endsWith('\n') ? '\n' : ''); | }).join('\n') + (r.text.endsWith('\n') ? '\n' : ''); | ||
setLines(input, r, | setLines(input, r, out); | ||
} | } | ||
function insertLink(input){ | |||
function insertLink(input) { | const s = input.selectionStart, e = input.selectionEnd, v = input.value; | ||
const s = input.selectionStart, e = input.selectionEnd | |||
const sel = v.slice(s, e) || 'Cíl'; | const sel = v.slice(s, e) || 'Cíl'; | ||
input.value = v.slice(0, s) + '[[' + sel + '|' + sel + ']]' + v.slice(e); | input.value = v.slice(0,s) + '[['+sel+'|'+sel+']]' + v.slice(e); | ||
const pos = s + 4 + sel.length + 1 + sel.length + 2; | const pos = s + 4 + sel.length + 1 + sel.length + 2; // [[sel|sel]] | ||
input.focus(); | input.focus(); input.setSelectionRange(pos,pos); | ||
} | } | ||
function | function addToolbar($textarea){ | ||
if (!$textarea.length) return; | if (!$textarea.length) return; | ||
const input = $textarea.get(0); | const input = $textarea.get(0); | ||
if ($(input).data('pmtAttached')) return; | |||
$(input).data('pmtAttached', true); | |||
$ | // větší/roztahovatelné | ||
$(input).addClass('pmt-textarea'); | |||
const $bar = $('<div class="private-mini-toolbar" />'); | const $bar = $('<div class="private-mini-toolbar"/>'); | ||
function btn(label, title, h){ | |||
function btn(label, title, | $('<button type="button" class="pmt-btn"/>').text(label).attr('title',title).on('click',()=>h(input)).appendTo($bar); | ||
$('<button type="button" class="pmt-btn" />') | |||
} | } | ||
btn('B', "Tučné ('''…''')", el=>toggleWrap(el,"'''","'''")); | |||
btn('I', "Kurzíva (''…'')", el=>toggleWrap(el,"''","''")); | |||
btn('H2', 'Nadpis H2', el=>toggleHeading(el,2)); | |||
btn('H3', 'Nadpis H3', el=>toggleHeading(el,3)); | |||
btn('H4', 'Nadpis H4', el=>toggleHeading(el,4)); | |||
btn('H5', 'Nadpis H5', el=>toggleHeading(el,5)); | |||
btn('•', 'Seznam odrážek', el=>toggleBullets(el)); | |||
btn('[]', 'Odkaz [[…]]', el=>insertLink(el)); | |||
// vlož PŘED textarea | |||
$textarea.before($bar); | |||
} | |||
$textarea | |||
$ | function scan(root){ | ||
// vezmi první multiline textarea v otevřeném dialogu šablony | |||
$(root).find('.ve-ui-mwTemplateDialog:visible').each(function(){ | |||
const $ta = | |||
$(this).find('textarea.oo-ui-inputWidget-input').filter(function(){ | |||
// multiline widgety mívají tyto classy – necháme jen viditelné | |||
return $(this).is(':visible') && $(this).closest('.oo-ui-multilineTextInputWidget').length; | |||
}).first(); | |||
if ($ta.length) addToolbar($ta); | |||
}); | |||
} | } | ||
function init() { | function init(){ | ||
const mo = new MutationObserver( | const mo = new MutationObserver(m=>m.forEach(x=>scan(x.target))); | ||
mo.observe(document.body, { | mo.observe(document.body, { subtree:true, childList:true }); | ||
scan(document); | scan(document); | ||
} | } | ||
mw.loader.using('ext.visualEditor.desktopArticleTarget.init').then(init); | |||
})(); | })(); | ||
Verze z 9. 10. 2025, 23:12
mw.hook('wikipage.content').add(function ($c) {
var $ph = $c.find('.private-placeholder');
if ($ph.length > 1) {
$ph.slice(1).remove();
}
});
/* Mini-toolbar pro textarea ve VisualEditoru (robustní varianta) */
(function () {
// ---- util ----
function replaceRange(input, start, end, str) {
const v = input.value;
input.value = v.slice(0, start) + str + v.slice(end);
const pos = start + str.length;
input.focus(); input.setSelectionRange(pos, pos);
}
function toggleWrap(input, before, after) {
const s = input.selectionStart, e = input.selectionEnd, v = input.value;
const hasBefore = s >= before.length && v.slice(s - before.length, s) === before;
const hasAfter = v.slice(e, e + after.length) === after;
if (hasBefore && hasAfter) {
const inner = v.slice(s, e);
input.value = v.slice(0, s - before.length) + inner + v.slice(e + after.length);
const ns = s - before.length, ne = ns + inner.length;
input.focus(); input.setSelectionRange(ns, ne);
} else {
input.value = v.slice(0, s) + before + v.slice(s, e) + after + v.slice(e);
const pos = e + before.length + after.length;
input.focus(); input.setSelectionRange(pos, pos);
}
}
function getLineRange(input) {
const v = input.value, s = input.selectionStart, e = input.selectionEnd;
const start = v.lastIndexOf('\n', s - 1) + 1;
const end = (v.indexOf('\n', e) + 1) || v.length;
return { start, end, text: v.slice(start, end) };
}
function setLines(input, range, newText) { replaceRange(input, range.start, range.end, newText); }
function stripAnyHeading(line) {
const m = line.match(/^\s*(=+)\s*(.*?)\s*(=+)\s*$/);
return (m && m[1] && m[3]) ? m[2] : line;
}
function toggleHeading(input, level) {
const r = getLineRange(input), open = '='.repeat(level)+' ', close = ' '+ '='.repeat(level);
const lines = r.text.replace(/\n$/, '').split('\n');
const out = lines.map(l=>{
if (l.trim()==='') return l;
const isThis = l.startsWith(open) && l.trimEnd().endsWith(close);
return isThis ? stripAnyHeading(l) : open + stripAnyHeading(l) + close;
}).join('\n') + (r.text.endsWith('\n') ? '\n' : '');
setLines(input, r, out);
}
function toggleBullets(input){
const r = getLineRange(input);
const lines = r.text.replace(/\n$/, '').split('\n');
const allBulleted = lines.filter(l=>l.trim()!=='').every(l=>l.startsWith('* '));
const out = lines.map(l=>{
if (l.trim()==='') return l;
return allBulleted ? l.replace(/^\* /,'') : '* ' + l;
}).join('\n') + (r.text.endsWith('\n') ? '\n' : '');
setLines(input, r, out);
}
function insertLink(input){
const s = input.selectionStart, e = input.selectionEnd, v = input.value;
const sel = v.slice(s, e) || 'Cíl';
input.value = v.slice(0,s) + '[['+sel+'|'+sel+']]' + v.slice(e);
const pos = s + 4 + sel.length + 1 + sel.length + 2; // [[sel|sel]]
input.focus(); input.setSelectionRange(pos,pos);
}
function addToolbar($textarea){
if (!$textarea.length) return;
const input = $textarea.get(0);
if ($(input).data('pmtAttached')) return;
$(input).data('pmtAttached', true);
// větší/roztahovatelné
$(input).addClass('pmt-textarea');
const $bar = $('<div class="private-mini-toolbar"/>');
function btn(label, title, h){
$('<button type="button" class="pmt-btn"/>').text(label).attr('title',title).on('click',()=>h(input)).appendTo($bar);
}
btn('B', "Tučné ('''…''')", el=>toggleWrap(el,"'''","'''"));
btn('I', "Kurzíva (''…'')", el=>toggleWrap(el,"''","''"));
btn('H2', 'Nadpis H2', el=>toggleHeading(el,2));
btn('H3', 'Nadpis H3', el=>toggleHeading(el,3));
btn('H4', 'Nadpis H4', el=>toggleHeading(el,4));
btn('H5', 'Nadpis H5', el=>toggleHeading(el,5));
btn('•', 'Seznam odrážek', el=>toggleBullets(el));
btn('[]', 'Odkaz [[…]]', el=>insertLink(el));
// vlož PŘED textarea
$textarea.before($bar);
}
function scan(root){
// vezmi první multiline textarea v otevřeném dialogu šablony
$(root).find('.ve-ui-mwTemplateDialog:visible').each(function(){
const $ta =
$(this).find('textarea.oo-ui-inputWidget-input').filter(function(){
// multiline widgety mívají tyto classy – necháme jen viditelné
return $(this).is(':visible') && $(this).closest('.oo-ui-multilineTextInputWidget').length;
}).first();
if ($ta.length) addToolbar($ta);
});
}
function init(){
const mo = new MutationObserver(m=>m.forEach(x=>scan(x.target)));
mo.observe(document.body, { subtree:true, childList:true });
scan(document);
}
mw.loader.using('ext.visualEditor.desktopArticleTarget.init').then(init);
})();