MediaWiki:Gadget-sel t.js
Appearance
Uwaga: aby zobaczyć zmiany po opublikowaniu, może zajść potrzeba wyczyszczenia pamięci podręcznej przeglądarki.
- Firefox / Safari: Przytrzymaj Shift podczas klikania Odśwież bieżącą stronę, lub naciśnij klawisze Ctrl+F5, lub Ctrl+R (⌘-R na komputerze Mac)
- Google Chrome: Naciśnij Ctrl-Shift-R (⌘-Shift-R na komputerze Mac)
- Internet Explorer / Edge: Przytrzymaj Ctrl, jednocześnie klikając Odśwież, lub naciśnij klawisze Ctrl+F5
- Opera: Naciśnij klawisze Ctrl+F5.
/* global sel_t, mw, ve, $, WikEdUpdateFrame, WikEdUpdateTextarea, wikEdUseWikEd */
/* ------------------------------------------------------------------------ *\
copyright: (C) 2008-2024 Maciej Jaros (pl:User:Nux, en:User:EcceNux)
licence: GNU General Public License v2,
http://opensource.org/licenses/gpl-license.php
version: (see below) = sel_t.version
Modified by user:Wargo to use jquery.textSelection & VE surface
https://phabricator.wikimedia.org/source/mediawiki/browse/master/resources/src/jquery/jquery.textSelection.js
Note! Technical documentation is on a talk page (function descriptions etc).
\* ------------------------------------------------------------------------ */
if ( !window.sel_t ) {
window.sel_t = {};
sel_t.version = '2.0.2';
sel_t.getEditor = function ()
{
var editorType = 'textarea';
// code editor 2010 (also for syntax highlighter)
if(mw.user.options.get('usebetatoolbar') === 1) editorType = 'WikiEd';
// VE based code editor 2017
if(mw.user.options.get('visualeditor-newwikitext') === "1" && typeof ve.init != 'undefined') editorType = '2017';
return editorType;
};
sel_t.getSelStr = function (input, nonempty)
{
sel_t.noSelection = true;
sel_t.isWikEdOn = false;
var editorType = sel_t.getEditor();
// check for wikEd (always choose whole area)
if (typeof wikEdUseWikEd != 'undefined' && wikEdUseWikEd)
{
sel_t.isWikEdOn = true;
WikEdUpdateTextarea(); // update before get
return input.value;
}
else if (editorType == 'WikiEd' || editorType == 'textarea')
{
// Proofread (Wikiźródła) nie obsługuje poprawnie textselection
if(mw.config.get('wgPageContentModel') == 'proofread-page') $(input).select();
sel_t.sel_s = input.selectionStart;
sel_t.sel_e = input.selectionEnd;
var selected_text = $(input).textSelection('getSelection');
if(selected_text.length > 0)
{
sel_t.noSelection = false;
return selected_text;
}
else if(nonempty)
{
return $(input).textSelection('getContents');
}
}
else if (editorType == '2017')
{
var surfacem = ve.init.target.getSurface().model;
sel_t.sel_s = surfacem.selection.range.start;
sel_t.sel_e = surfacem.selection.range.end;
let start = sel_t.sel_s;
let end = sel_t.sel_e;
let isFull = start == end;
let str = isFull ? surfacem.getDom() : surfacem.getFragment().getText(true);
// On Windows `getFragment().getText(true)` might return double `\n` so... we might need to take care of this...
if (!isFull) {
sel_t.noSelection = false;
let fullByDom = surfacem.getDom();
let fullByRange = surfacem.getLinearFragment(new ve.Range(1, surfacem.getDocument().data.getLength())).getText(true);
if (fullByDom != fullByRange) {
console.log('ve_sk: getSelection', {fullByDom, fullByRange});
str = str.replace(/\n\n/g, '\n');
}
}
if(!isFull || nonempty)
{
return str;
}
}
// other cases then above
return (nonempty) ? input.value : '';
};
// for quick set after getSelStr (same selection)
sel_t.qsetSelStr = function (input, str, nonempty)
{
var editorType = sel_t.getEditor();
if (sel_t.noSelection)
{
if (nonempty)
{
if(editorType == 'WikiEd') $(input).textSelection('setContents', str);
if(editorType == '2017')
{
const surfacem = ve.init.target.getSurface().model;
// note: ve.Range starts at 1
const range = new ve.Range(1, surfacem.getDocument().data.getLength());
surfacem.getLinearFragment(range).insertContent(str);
}
if(editorType == 'textarea') input.value = str;
}
else
{
input.value += str;
input.scrollTop = input.scrollHeight;
}
}
else if (sel_t.sel_s !== undefined)
{
//input.value = input.value.substring(0, sel_t.sel_s) + str + input.value.substring(sel_t.sel_e);
//sel_t.ScrollIntoView(input, sel_t.sel_s, sel_t.sel_e);
if(editorType == 'WikiEd')
{
$(input).textSelection('replaceSelection', str);
}
if(editorType == '2017')
{
const surfacem = ve.init.target.getSurface().model;
const range = new ve.Range(sel_t.sel_s, sel_t.sel_e);
surfacem.getLinearFragment(range).insertContent(str);
}
}
// IE...
/*else if (document.selection && sel_t.range !== undefined)
{
sel_t.range.text = str;
sel_t.range.scrollIntoView(false);// at bottom
}*/
// WikEd frame update
if (sel_t.isWikEdOn)
{
WikEdUpdateFrame();
}
};
/*
Set selection for current range.
Note! only works with a plain code editor.
Consider using this combination instead:
sel_t.getSelStr(input, nonempty);
sel_t.qsetSelStr(input, str, nonempty);
*/
sel_t.setSelStr = function (input, str, nonempty)
{
// fox/opera
if (input.selectionStart !== undefined)
{
var sTop=input.scrollTop;
var sel_s = input.selectionStart;
var sel_e = input.selectionEnd;
if (sel_s!=sel_e)
{
input.value = input.value.substring(0, sel_s) + str + input.value.substring(sel_e);
input.selectionStart=sel_s;
input.selectionEnd=sel_s + str.length;
input.scrollTop=sTop;
return;
}
else if (sel_s==sel_e && !nonempty)
{
input.value = input.value.substring(0, sel_s) + str + input.value.substring(sel_e);
input.selectionEnd=sel_s + str.length;
input.selectionStart=input.selectionEnd;
input.scrollTop=sTop;
sel_t.ScrollIntoView(input, sel_s, sel_e);
return;
}
}
// other cases then above
if (nonempty)
input.value = str;
else
{
input.value += str;
input.scrollTop = input.scrollHeight;
}
};
sel_t.ScrollIntoView = function(input, sel_start, sel_end)
{
//
// quick checks
//
if (sel_start<20)
{
input.scrollTop = 0;
return;
}
var text_len = input.value.length; // in chars
var text_height = input.scrollHeight; // in pixels
if (text_len - sel_start<20)
{
input.scrollTop = text_height;
return;
}
// put pre-selection text into clone
var fake;
fake = input.cloneNode(false);
fake.style.height = '50px'; // have to be bigger then about 40px so that scrolls can be rendered
fake.style.visibility = 'hidden'; // display=none doesn't seem to set scrollHeight, hidden does
fake.style.position='absolute';
fake.style.bottom='0';
input.parentNode.appendChild(fake);
fake.value = input.value.substr(0,sel_start);
var pre_h = fake.scrollHeight;
input.parentNode.removeChild(fake);
// get line height to scroll-back two lines
var line_h = 15;
try
{
line_h = document.defaultView.getComputedStyle(input, null).lineHeight.replace(/[a-z]+/, ''); // assuming px...
if (line_h<10) // something probably went wrong...
{
line_h = 15;
}
}
catch(e){}
input.scrollTop = pre_h - 2*line_h;
};
sel_t.getSelBound = function (input)
{
var sel_s = 0; // defaults to "nothing is selected"
var sel_e = 0;
if (input.selectionStart != undefined)
{
sel_s = input.selectionStart;
sel_e = input.selectionEnd;
}
// IE...
else if (document.selection)
{
input.focus(); // only way for it to work if nothing is selected (i.e. get caret position)
var range = document.selection.createRange();
if (range.parentElement()==input)
{
// duplicate range to select from start to end
var tmp_range = range.duplicate();
tmp_range.moveToElementText(input);
tmp_range.setEndPoint('EndToEnd', range);
// calculate
sel_e = tmp_range.text.length;
sel_s = sel_e - range.text.length;
}
}
// return values
var sel_boundaries = {
start : sel_s,
end : sel_e
};
return sel_boundaries;
};
// parts borrowed from PD code by Fred Jounters and Martin Honnen
sel_t.setSelBound = function (input, sel_boundaries, scroll)
{
if (input.setSelectionRange)
{
input.setSelectionRange(sel_boundaries.start, sel_boundaries.end);
if (scroll)
{
input.focus();
sel_t.ScrollIntoView(input, sel_boundaries.start, sel_boundaries.end);
}
}
else if (input.createTextRange)
{
var range = input.createTextRange();
range.collapse(true);
// re-calculate boundaries as \r\n are treated as one character for moveEnd/moveStart
var tmp;
tmp = input.value.substr(0, sel_boundaries.start).match(/\r\n/g);
tmp = (tmp ? tmp.length : 0);
// ups... would change this outside of a scope of this function!
//sel_boundaries.start -= tmp;
var sel_start = sel_boundaries.start - tmp;
tmp = input.value.substr(0, sel_boundaries.end).match(/\r\n/g);
tmp = (tmp ? tmp.length : 0);
//sel_boundaries.end -= tmp;
var sel_end = sel_boundaries.end - tmp;
// move
range.moveEnd('character', sel_end);
range.moveStart('character', sel_start);
range.select();
if (scroll)
{
range.scrollIntoView(true); // at top
input.focus();
}
}
};
// for backward compatibility only
sel_t.setSelRange = function(input, sel_s, sel_e)
{
var sel_boundaries = {
start : sel_s,
end : sel_e
};
sel_t.setSelBound (input, sel_boundaries, true);
};
}