3 /* Show theme to the user */
4 function selectTheme(themeId){
5 var selection = window.getSelection();
6 selection.removeAllRanges();
8 var range = document.createRange();
9 var s = $("[x-node='motyw'][theme-class='" + themeId + "']")[0];
10 var e = $("[x-node='end'][theme-class='" + themeId + "']")[0];
13 range.setStartAfter(s);
14 range.setEndBefore(e);
15 selection.addRange(range);
19 /* Verify insertion port for annotation or theme */
20 function verifyTagInsertPoint(node){
21 if (node.nodeType == Node.TEXT_NODE) {
22 node = node.parentNode;
25 if (node.nodeType != Node.ELEMENT_NODE) {
30 if (node.attr('id') == 'caret') {
33 while (node.attr('x-pass-thru')) {
36 var xtype = node.attr('x-node');
38 if (!xtype || (xtype.search(':') >= 0) ||
48 function verifyThemeBoundaryPoint(node) {
49 if (!verifyTagInsertPoint(node)) return false;
51 // don't allow themes inside annotations
52 if (node.closest('[x-node="pe"]').length > 0)
58 /* Convert HTML fragment to plaintext */
59 var ANNOT_FORBIDDEN = ['pt', 'pa', 'pr', 'pe', 'ptrad', 'begin', 'end', 'motyw'];
61 function html2plainText(fragment){
64 $(fragment.childNodes).each(function(){
65 if (this.nodeType == Node.TEXT_NODE)
66 text += this.nodeValue;
68 if (this.nodeType == Node.ELEMENT_NODE &&
69 $.inArray($(this).attr('x-node'), ANNOT_FORBIDDEN) == -1) {
70 text += html2plainText(this);
79 /* Insert annotation using current selection */
80 function addAnnotation(){
81 var selection = window.getSelection();
82 var n = selection.rangeCount;
84 if (selection.isCollapsed) {
85 window.alert("Nie zaznaczono żadnego obszaru");
89 var range = selection.getRangeAt(n - 1);
91 if (!verifyTagInsertPoint(range.endContainer)) {
92 window.alert("Nie można wstawić w to miejsce przypisu.");
97 for (let i = 0; i < n; ++ i) {
98 let rangeI = selection.getRangeAt(i);
99 if (verifyTagInsertPoint(rangeI.startContainer) &&
100 verifyTagInsertPoint(rangeI.endContainer)) {
101 text += html2plainText(rangeI.cloneContents());
104 var tag = $('<span></span>');
105 range.collapse(false);
106 range.insertNode(tag[0]);
109 xml: '<pe><slowo_obce>' + text + '</slowo_obce> --- </pe>',
110 success: function(text){
117 alert('Błąd przy dodawaniu przypisu:' + errors);
124 /* Insert theme using current selection */
127 var selection = window.getSelection();
128 var n = selection.rangeCount;
131 window.alert("Nie zaznaczono żadnego obszaru");
135 // for now allow only 1 range
137 window.alert("Zaznacz jeden obszar.");
141 // remember the selected range
142 var range = selection.getRangeAt(0);
144 if ($(range.startContainer).is('.html-editarea') ||
145 $(range.endContainer).is('.html-editarea')) {
146 window.alert("Motywy można oznaczać tylko na tekście nie otwartym do edycji. \n Zamknij edytowany fragment i spróbuj ponownie.");
150 // verify if the start/end points make even sense -
151 // they must be inside a x-node (otherwise they will be discarded)
152 // and the x-node must be a main text
153 if (!verifyThemeBoundaryPoint(range.startContainer)) {
154 window.alert("Motyw nie może się zaczynać w tym miejscu.");
158 if (!verifyThemeBoundaryPoint(range.endContainer)) {
159 window.alert("Motyw nie może się kończyć w tym miejscu.");
163 var date = (new Date()).getTime();
164 var random = Math.floor(4000000000 * Math.random());
165 var id = ('' + date) + '-' + ('' + random);
167 var createPoint = function(container, offset) {
168 var offsetBetweenCommas = function(text, offset) {
169 if(text.length < 2 || offset < 1 || offset > text.length)
171 return text[offset-1] === ',' && text[offset] === ',';
173 var point = document.createRange();
174 offset = offsetBetweenCommas(container.textContent, offset) ? offset - 1 : offset;
175 point.setStart(container, offset);
179 var spoint = createPoint(range.startContainer, range.startOffset);
180 var epoint = createPoint(range.endContainer, range.endOffset);
182 var mtag, btag, etag, errors;
187 xml: '<end id="e' + id + '" />',
188 success: function(text){
189 etag = $('<span></span>');
190 epoint.insertNode(etag[0]);
191 etag.replaceWith(text);
193 xml: '<motyw id="m' + id + '"></motyw>',
194 success: function(text){
195 mtag = $('<span></span>');
196 spoint.insertNode(mtag[0]);
197 mtag.replaceWith(text);
199 xml: '<begin id="b' + id + '" />',
200 success: function(text){
201 btag = $('<span></span>');
202 spoint.insertNode(btag[0])
203 btag.replaceWith(text);
204 selection.removeAllRanges();
205 openForEdit($('[x-node="motyw"][theme-class="' + id + '"]'));
214 function addSymbol(caret) {
218 editArea = $("textarea", caret.element)[0];
220 editArea = $('div.html-editarea textarea')[0];
224 var specialCharsContainer = $("<div id='specialCharsContainer'><a href='#' id='specialCharsClose'>Zamknij</a><table id='tableSpecialChars' style='width: 600px;'></table></div>");
227 ' ', 'Ą','ą','Ć','ć','Ę','ę','Ł','ł','Ń','ń','Ó','ó','Ś','ś','Ż','ż','Ź','ź','Á','á','À','à',
228 'Â','â','Ä','ä','Å','å','Ā','ā','Ă','ă','Ã','ã',
229 'Æ','æ','Ç','ç','Č','č','Ċ','ċ','Ď','ď','É','é','È','è',
230 'Ê','ê','Ë','ë','Ē','ē','Ě','ě','Ġ','ġ','Ħ','ħ','Í','í','Î','î',
231 'Ī','ī','Ĭ','ĭ','Ľ','ľ','Ñ','ñ','Ň','ň','Ó','ó','Ö','ö',
232 'Ô','ô','Ō','ō','Ǒ','ǒ','Œ','œ','Ø','ø','Ř','ř','Š',
233 'š','Ş','ş','Ť','ť','Ţ','ţ','Ű','ű','Ú','ú','Ù','ù',
234 'Ü','ü','Ů','ů','Ū','ū','Û','û','Ŭ','ŭ',
235 'Ý','ý','Ž','ž','ß','Ð','ð','Þ','þ','А','а','Б',
236 'б','В','в','Г','г','Д','д','Е','е','Ё','ё','Ж',
237 'ж','З','з','И','и','Й','й','К','к','Л','л','М',
238 'м','Н','н','О','о','П','п','Р','р','С','с',
239 'Т','т','У','у','Ф','ф','Х','х','Ц','ц','Ч',
240 'ч','Ш','ш','Щ','щ','Ъ','ъ','Ы','ы','Ь','ь','Э',
241 'э','Ю','ю','Я','я','ѓ','є','і','ї','ј','љ','њ',
242 'Ґ','ґ','Α','α','Β','β','Γ','γ','Δ','δ','Ε','ε',
243 'Ζ','ζ','Η','η','Θ','θ','Ι','ι','Κ','κ','Λ','λ','Μ',
244 'μ','Ν','ν','Ξ','ξ','Ο','ο','Π','π','Ρ','ρ','Σ','ς','σ',
245 'Τ','τ','Υ','υ','Φ','φ','Χ','χ','Ψ','ψ','Ω','ω','–',
246 '—','¡','¿','$','¢','£','€','©','®','°','¹','²','³',
247 '¼','½','¾','†','§','‰','•','←','↑','→','↓',
248 '„','”','„”','«','»','«»','»«','’','[',']','~','|','−','·',
249 '×','÷','≈','≠','±','≤','≥','∈',
252 '\u05d0', '\u05d1', '\u05d2', '\u05d3', '\u05d4', '\u05d5', '\u05d6', '\u05d7',
253 '\u05d8', '\u05d9', '\u05da', '\u05db', '\u05dc', '\u05dd', '\u05de', '\u05df',
254 '\u05e0', '\u05e1', '\u05e2', '\u05e3', '\u05e4', '\u05e5', '\u05e6', '\u05e7',
255 '\u05e8', '\u05e9', '\u05e0', '\u05ea',
257 '\u0591', '\u0592', '\u0593', '\u0594', '\u0595', '\u0596', '\u0597',
258 '\u0598', '\u0599', '\u059a', '\u059b', '\u059c', '\u059d', '\u059e', '\u059f',
259 '\u05a0', '\u05a1', '\u05a2', '\u05a3', '\u05a4', '\u05a5', '\u05a6', '\u05a7',
260 '\u05a8', '\u05a9', '\u05aa', '\u05ab', '\u05ac', '\u05ad', '\u05ae', '\u05af',
261 '\u05b0', '\u05b1', '\u05b2', '\u05b3', '\u05b4', '\u05b5', '\u05b6', '\u05b7',
262 '\u05b8', '\u05b9', '\u05ba', '\u05bb', '\u05bc', '\u05bd', '\u05be', '\u05bf',
263 '\u05c0', '\u05c1', '\u05c2', '\u05c3', '\u05c4', '\u05c5', '\u05c6', '\u05c7',
265 '\ufb1d', '\ufb1e', '\ufb1f',
266 '\ufb20', '\ufb21', '\ufb22', '\ufb23', '\ufb24', '\ufb25', '\ufb26', '\ufb27',
267 '\ufb28', '\ufb29', '\ufb2a', '\ufb2b', '\ufb2c', '\ufb2d', '\ufb2e', '\ufb2f',
268 '\ufb30', '\ufb31', '\ufb32', '\ufb33', '\ufb34', '\ufb35', '\ufb36',
269 '\ufb38', '\ufb39', '\ufb3a', '\ufb3b', '\ufb3c', '\ufb3e',
270 '\ufb40', '\ufb41', '\ufb43', '\ufb44', '\ufb46', '\ufb47',
271 '\ufb48', '\ufb49', '\ufb4a', '\ufb4b', '\ufb4c', '\ufb4d', '\ufb4e', '\ufb4f',
273 var tableContent = "<tr>";
275 for(var i in specialChars) {
276 if(i % 14 == 0 && i > 0) {
277 tableContent += "</tr><tr>";
279 tableContent += "<td><input type='button' class='specialBtn' value='"+specialChars[i]+"'/></td>";
282 tableContent += "</tr>";
283 $("body").append(specialCharsContainer);
286 // localStorage for recently used characters - reading
287 if (typeof(localStorage) != 'undefined') {
288 if (localStorage.getItem("recentSymbols")) {
289 var recent = localStorage.getItem("recentSymbols");
290 var recentArray = recent.split(";");
292 for(var i in recentArray.reverse()) {
293 recentRow += "<td><input type='button' class='specialBtn recentSymbol' value='"+recentArray[i]+"'/></td>";
295 recentRow = "<tr>" + recentRow + "</tr>";
298 $("#tableSpecialChars").append(recentRow);
299 $("#tableSpecialChars").append(tableContent);
303 $('.specialBtn').click(function(){
304 var insertVal = $(this).val();
306 // if we want to surround text with quotes
307 // not sure if just check if value has length == 2
310 caret.insertChar(insertVal);
313 if (insertVal.length == 2) {
314 var startTag = insertVal[0];
315 var endTag = insertVal[1];
316 var textAreaOpened = editArea;
318 if (document.selection) {
319 textAreaOpened.focus();
320 sel = document.selection.createRange();
321 sel.text = startTag + sel.text + endTag;
323 //MOZILLA/NETSCAPE support
324 else if (textAreaOpened.selectionStart || textAreaOpened.selectionStart == '0') {
325 var startPos = textAreaOpened.selectionStart;
326 var endPos = textAreaOpened.selectionEnd;
327 textAreaOpened.value = textAreaOpened.value.substring(0, startPos)
328 + startTag + textAreaOpened.value.substring(startPos, endPos) + endTag + textAreaOpened.value.substring(endPos, textAreaOpened.value.length);
331 insertAtCaret(editArea, insertVal);
335 // localStorage for recently used characters - saving
336 if (typeof(localStorage) != 'undefined') {
337 if (localStorage.getItem("recentSymbols")) {
338 var recent = localStorage.getItem("recentSymbols");
339 var recentArray = recent.split(";");
340 var valIndex = $.inArray(insertVal, recentArray);
343 // value not present in array yet
344 if(recentArray.length > 13){
346 recentArray.push(insertVal);
348 recentArray.push(insertVal);
351 // value already in the array
352 for(var i = valIndex; i < recentArray.length; i++){
353 recentArray[i] = recentArray[i+1];
355 recentArray[recentArray.length-1] = insertVal;
357 localStorage.setItem("recentSymbols", recentArray.join(";"));
359 localStorage.setItem("recentSymbols", insertVal);
362 $(specialCharsContainer).remove();
364 $('#specialCharsClose').click(function(){
365 $(specialCharsContainer).remove();
369 window.alert('Najedź na fragment tekstu, wybierz "Edytuj" i ustaw kursor na miejscu gdzie chcesz wstawić symbol.');
373 function insertAtCaret(txtarea,text) {
374 /* http://www.scottklarr.com/topic/425/how-to-insert-text-into-a-textarea-where-the-cursor-is/ */
375 var scrollPos = txtarea.scrollTop;
378 var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? "ff" : (document.selection ? "ie" : false ) );
381 var range = document.selection.createRange();
382 range.moveStart ('character', -txtarea.value.length);
383 strPos = backStart = range.text.length;
384 } else if (br == "ff") {
385 strPos = txtarea.selectionStart;
386 backStart = txtarea.selectionEnd;
388 var front = (txtarea.value).substring(0,strPos);
389 var back = (txtarea.value).substring(backStart,txtarea.value.length);
390 txtarea.value=front+text+back;
391 strPos = strPos + text.length;
394 var range = document.selection.createRange();
395 range.moveStart ('character', -txtarea.value.length);
396 range.moveStart ('character', strPos);
397 range.moveEnd ('character', 0);
399 } else if (br == "ff") {
400 txtarea.selectionStart = strPos;
401 txtarea.selectionEnd = strPos;
404 txtarea.scrollTop = scrollPos;
407 /* open edition window for selected fragment */
408 function openForEdit($origin){
411 // annotations overlay their sub box - not their own box //
412 if ($origin.is(".annotation-inline-box")) {
413 $box = $("*[x-annotation-box]", $origin);
418 var x = $box[0].offsetLeft;
419 var y = $box[0].offsetTop;
421 var w = $box.outerWidth();
422 var h = $box.innerHeight();
424 if ($origin.is(".annotation-inline-box")) {
425 w = Math.max(w, 400);
427 if($('.htmlview div').offset().left + $('.htmlview div').width() > ($('.vsplitbar').offset().left - 480)){
428 x = -(Math.max($origin.offset().left, $origin.width()));
433 if ($origin.is('.reference-inline-box')) {
439 $('.htmlview div').offset().left + $('.htmlview div').width() - 400
443 // start edition on this node
444 var $overlay = $('<div class="html-editarea"><button class="accept-button">Zapisz</button><button class="delete-button">Usuń</button><button class="tytul-button akap-edit-button">tytuł dzieła</button><button class="wyroznienie-button akap-edit-button">wyróżnienie</button><button class="slowo-button akap-edit-button">słowo obce</button><button class="znak-button akap-edit-button">znak spec.</button><textarea></textarea></div>').css({
445 position: 'absolute',
450 }).appendTo($box[0].offsetParent || $box.parent()).show();
453 if ($origin.is('*[x-edit-no-format]')) {
454 $('.akap-edit-button').remove();
457 if ($origin.is('[x-node="motyw"]')) {
458 $.themes.autocomplete($('textarea', $overlay));
461 if ($origin.is('[x-node="motyw"]')){
462 $('.delete-button', $overlay).click(function(){
463 if (window.confirm("Czy jesteś pewien, że chcesz usunąć ten motyw?")) {
464 $('[theme-class="' + $origin.attr('theme-class') + '"]').remove();
466 $(document).unbind('click.blur-overlay');
471 else if($box.is('*[x-annotation-box]') || $origin.is('*[x-edit-attribute]') || $origin.is('*[x-node="uwaga"]')) {
473 switch ($origin.attr('x-node')) {
483 $('.delete-button', $overlay).click(function(){
484 if (window.confirm("Czy jesteś pewien, że chcesz usunąć " + q + "?")) {
487 $(document).unbind('click.blur-overlay');
493 $('.delete-button', $overlay).html("Anuluj");
494 $('.delete-button', $overlay).click(function(){
495 if (window.confirm("Czy jesteś pewien, że chcesz anulować zmiany?")) {
497 $(document).unbind('click.blur-overlay');
504 var serializer = new XMLSerializer();
506 if($box.attr("x-edit-attribute")) {
507 source = $('<span x-pass-thru="true"/>');
508 source.text($box.attr("x-a-wl-" + $box.attr("x-edit-attribute")));
517 success: function(text){
518 let ttext = $.trim(text);
519 $('textarea', $overlay).val(ttext);
521 setTimeout(function(){
522 $('textarea', $overlay).elastic().focus();
525 function save(argument){
526 var nodeName = $box.attr('x-node') || 'pe';
527 var insertedText = $('textarea', $overlay).val();
529 if ($origin.is('[x-node="motyw"]')) {
530 insertedText = insertedText.replace(/,\s*$/, '');
533 if($box.attr("x-edit-attribute")) {
534 xml = '<' + nodeName + ' ' + $box.attr("x-edit-attribute") + '="' + insertedText + '"/>';
536 xml = '<' + nodeName + '>' + insertedText + '</' + nodeName + '>';
541 success: function(element){
542 if (nodeName == 'out-of-flow-text') {
543 $(element).children().insertAfter($origin);
546 else if ($box.attr('x-edit-attribute')) {
547 $(element).insertAfter($origin);
551 $origin.html($(element).html());
554 $.wiki.activePerspective().flush();
556 error: function(text){
557 alert('Błąd! ' + text);
561 var msg = $("<div class='saveNotify'><p>Pamiętaj, żeby zapisać swoje zmiany.</p></div>");
562 $("#base").prepend(msg);
563 $('#base .saveNotify').fadeOut(3000, function(){
568 $('.akap-edit-button', $overlay).click(function(){
569 var textAreaOpened = $('textarea', $overlay)[0];
572 var buttonName = this.innerHTML;
574 if(buttonName == "słowo obce") {
575 startTag = "<slowo_obce>";
576 endTag = "</slowo_obce>";
577 } else if (buttonName == "wyróżnienie") {
578 startTag = "<wyroznienie>";
579 endTag = "</wyroznienie>";
580 } else if (buttonName == "tytuł dzieła") {
581 startTag = "<tytul_dziela>";
582 endTag = "</tytul_dziela>";
583 } else if(buttonName == "znak spec."){
588 var myField = textAreaOpened;
591 if (document.selection) {
592 textAreaOpened.focus();
593 sel = document.selection.createRange();
594 sel.text = startTag + sel.text + endTag;
596 //MOZILLA/NETSCAPE support
597 else if (textAreaOpened.selectionStart || textAreaOpened.selectionStart == '0') {
598 var startPos = textAreaOpened.selectionStart;
599 var endPos = textAreaOpened.selectionEnd;
600 textAreaOpened.value = textAreaOpened.value.substring(0, startPos)
601 + startTag + textAreaOpened.value.substring(startPos, endPos) + endTag + textAreaOpened.value.substring(endPos, textAreaOpened.value.length);
605 $('.accept-button', $overlay).click(function(){
607 $(document).unbind('click.blur-overlay');
610 $(document).bind('click.blur-overlay', function(event){
611 if ($(event.target).closest('.html-editarea, #specialCharsContainer').length > 0) {
615 $(document).unbind('click.blur-overlay');
619 error: function(text){
620 alert('Błąd! ' + text);
625 function createUwagaBefore(before) {
628 success: function(element){
629 let $element = $(element);
630 $element.insertBefore(before);
631 openForEdit($element);
636 class VisualPerspective extends $.wiki.Perspective {
637 constructor(options) {
640 var element = $("#html-view");
641 var button = $('<button class="edit-button active-block-button">Edytuj</button>');
642 var uwagaButton = $('<button class="uwaga-button active-block-button">Uwaga</button>');
644 if (!CurrentDocument.readonly) {
646 $('#html-view').bind('mousemove', function(event){
647 var editable = $(event.target).closest('*[x-editable]');
648 $('.active', element).not(editable).removeClass('active').children('.active-block-button').remove();
650 if (!editable.hasClass('active')) {
651 editable.addClass('active').append(button);
652 if (!editable.is('[x-edit-attribute]') &&
653 !editable.is('.annotation-inline-box') &&
654 !editable.is('[x-edit-no-format]')
656 editable.append(uwagaButton);
659 if (editable.is('.annotation-inline-box')) {
660 $('*[x-annotation-box]', editable).css({
663 if (editable.is('.reference-inline-box')) {
664 let preview = $('*[x-preview]', editable);
666 let link = $("a", preview);
667 let href = link.attr('href');
668 if (link.attr('title') == '?' && href.startsWith('https://www.wikidata.org/wiki/')) {
669 link.attr('title', '…');
670 let qid = href.split('/').reverse()[0];
672 url: 'https://www.wikidata.org/w/rest.php/wikibase/v1/entities/items/' + qid + '?_fields=labels',
674 success: function(data) {
677 data['labels']['pl'] || data['labels']['en']
685 self.caret = new Caret(element);
687 $('#insert-reference-button').click(function(){
693 $('#insert-annotation-button').click(function(){
699 $('#insert-theme-button').click(function(){
705 $(".insert-inline-tag").click(function() {
707 self.insertInlineTag($(this).attr('data-tag'));
711 $(".insert-char").click(function() {
713 addSymbol(caret=self.caret);
717 $(document).on('click', '.edit-button', function(event){
719 event.preventDefault();
720 openForEdit($(this).parent());
723 $(document).on('click', '.uwaga-button', function(event){
725 event.preventDefault();
726 createUwagaBefore($(this).parent());
730 $(document).on('click', '[x-node="motyw"]', function(){
731 selectTheme($(this).attr('theme-class'));
734 element.on('click', '.annotation', function(event) {
736 event.preventDefault();
737 event.redakcja_caret_ignore = true;
738 $('[x-annotation-box]', $(this).parent()).toggleClass('editing');
743 onEnter(success, failure) {
747 message: 'Uaktualnianie widoku...'
750 function _finalize(callback){
759 base: this.doc.getBase(),
760 success: function(element){
762 var htmlView = $('#html-view');
763 htmlView.html(element);
765 if ('PropertiesPerspective' in $.wiki.perspectives)
766 $.wiki.perspectives.PropertiesPerspective.enable();
770 error: function(text, source){
771 let err = '<p class="error">Wystąpił błąd:</p><p>'+text+'</p>';
773 err += '<pre>'+source.replace(/&/g, '&').replace(/</g, '<')+'</pre>'
774 $('#html-view').html(err);
782 return new Promise((resolve, reject) => {
783 if ($('#html-view .error').length > 0) {
786 //return _finalize(failure);
788 element: $('#html-view').get(0),
791 self.doc.setText(text);
796 //$('#source-editor').html('<p>Wystąpił błąd:</p><pre>' + text + '</pre>');
803 onExit(success, failure) {
808 if ('PropertiesPerspective' in $.wiki.perspectives)
809 $.wiki.perspectives.PropertiesPerspective.disable();
811 self.flush().then(() => {
812 success && success();
815 console.log('REJECTED!', e);
816 failure && failure();
820 insertInlineTag(tag) {
824 let selection = window.getSelection();
825 var n = selection.rangeCount;
826 if (n != 1 || selection.isCollapsed) {
827 window.alert("Nie zaznaczono obszaru");
830 let range = selection.getRangeAt(0);
833 // Both ends are in the same x-node container.
834 // Both ends are set to text nodes.
835 // TODO: That the container is a inline-text container.
836 let commonNode = range.endContainer;
838 if (commonNode.nodeType == Node.TEXT_NODE) {
839 commonNode = commonNode.parentNode;
841 let node = range.startContainer;
842 if (node.nodeType == Node.TEXT_NODE) {
843 node = node.parentNode;
845 if (node != commonNode) {
846 window.alert("Zły obszar.");
851 if (range.endContainer.nodeType == Node.TEXT_NODE) {
852 end = range.endContainer.splitText(range.endOffset);
854 end = document.createTextNode('');
855 let cont = $(range.endContainer).contents();
856 if (range.endOffset < cont.length) {
857 range.endContainer.insertBefore(end, cont[range.endOffset])
859 range.endContainer.append(end);
864 if (range.startContainer.nodeType == Node.TEXT_NODE) {
865 current = range.startContainer.splitText(range.startOffset);
867 current = document.createTextNode('');
868 let cont = $(range.startContainer).contents();
869 if (range.startOffset < cont.length) {
870 range.startContainer.insertBefore(current, cont[range.startOffset])
872 startNode.append(current);
876 // We will construct a HTML element with the range selected.
877 let div = $("<span x-pass-thru='true'>");
878 while (current != end) {
879 n = current.nextSibling;
880 $(current).appendTo(div);
886 success: function(d) {
888 xml: d = '<' + tag + '>' + d + '</' + tag + '>',
889 success: function(html) {
891 node.insertBefore($(html)[0], end);
896 error: function(a, b) {
902 insertAtRange(range, elem) {
904 let $end = $(range.endContainer);
905 if ($end.attr('id') == 'caret') {
906 self.caret.insert(elem);
908 range.insertNode(elem[0]);
914 var selection = window.getSelection();
915 var n = selection.rangeCount;
917 // TODO: if no selection, take caret position..
919 window.alert("Nie zaznaczono żadnego obszaru");
923 var range = selection.getRangeAt(n - 1);
924 if (!verifyTagInsertPoint(range.endContainer)) {
925 window.alert("Nie można wstawić w to miejsce referencji.");
929 var tag = $('<span></span>');
931 range.collapse(false);
932 self.insertAtRange(range, tag);
935 xml: '<ref href=""/>',
936 success: function(text){
943 alert('Błąd przy dodawaniu referncji:' + errors);
950 $('#html-view *').each((i, e) => {
952 if ($e.closest('[x-node="abstrakt"]').length) return;
953 if ($e.closest('[x-node="nota_red"]').length) return;
954 let node = $e.attr('x-node');
955 if (node == 'numeracja') {
957 } else if (['werset', 'akap', 'wers'].includes(node)) {
959 $e.attr('x-number', number);
965 $.wiki.VisualPerspective = VisualPerspective;