(function(window, document, undefined) {
var Phylly = {
BLOCKS: [
{name: 'code', tag: 'PRE', klass: 'screen'},
{name: 'figure', special: 'img', tag: 'DIV', subtag: true, klass: 'figure'},
{name: 'note', tag: 'DIV', subtag: true, klass: 'note'},
{name: 'quote', tag: 'BLOCKQUOTE', subtag: true, klass: 'quote'},
],
input_event: function(event) {
var sel = document.getSelection();
var anchorNode = sel.anchorNode;
if (sel.anchorNode.contentEditable === 'true' && (
sel.anchorNode.innerHTML == '
' || !sel.anchorNode.innerHTML)) {
// when everything has been removed, add back
var empty_p = document.createElement('P');
empty_p.appendChild(document.createElement('BR'));
var empty_div = sel.anchorNode;
empty_div.replaceWith(empty_p);
var range = document.createRange();
range.setStart(empty_p, 0);
sel.removeAllRanges();
sel.addRange(range);
}
if (sel.anchorNode.tagName == "LI" && sel.anchorNode.innerHTML == "
") {
// new empty li got inserted, insert a
within
var empty_p = document.createElement('P');
empty_p.appendChild(document.createElement('BR'));
var empty_li = anchorNode;
if (empty_li.childNodes.length) { // lone
empty_li.removeChild(empty_li.childNodes[0]);
}
empty_li.appendChild(empty_p);
var range = document.createRange();
range.setStart(empty_p, 0);
sel.removeAllRanges();
sel.addRange(range);
}
var prev_p = sel.anchorNode.previousSibling;
if (! prev_p) return;
if (prev_p.tagName != 'P') {
prev_p = $(prev_p).parents('p')[0];
if (! prev_p || prev_p.tagName != 'P') return;
}
var title_match = prev_p.innerText.match(/^(h[1-6]). /);
if (title_match) {
var title = document.createElement(title_match[1]);
title.innerHTML = prev_p.innerHTML;
title.textContent = title.textContent.slice(4);
prev_p.replaceWith(title);
}
return true;
},
init: function() {
$(document).on('selectionchange', function(event) {
if ($('input[name=link-target].shown').length) {
return;
}
var sel = window.getSelection();
if ($(sel.anchorNode).parents('div[contenteditable]').length && sel.toString()) {
show_inline_style_toolbar(sel);
} else if (inline_style_toolbar) {
$(inline_style_toolbar).hide();
}
});
var $image_upload = $('');
$image_upload.on('change', upload_image);
$image_upload.appendTo(document.body);
var $document_upload = $('');
$document_upload.on('change', upload_document);
$document_upload.appendTo(document.body);
document.execCommand('defaultParagraphSeparator', false, 'p');
$(document).on('click', 'div.figure span.empty', function() {
window.active_figure = this.parentNode;
$('#image-upload').trigger('click');
return true;
});
$(document).on('click', 'div.document span.empty', function() {
window.active_document = this.parentNode;
$('#document-upload').trigger('click');
return true;
});
},
off: function() {
$('#image-upload').remove();
$('#document-upload').remove();
if (block_style_toolbar) { block_style_toolbar.hide(); }
if (inline_style_toolbar) { inline_style_toolbar.hide(); }
$(document).off('selectionchange');
},
window_keypress: function(ev) {
if (inline_style_toolbar && inline_style_toolbar.is(':visible')) {
if (event.ctrlKey || event.metaKey) {
var key = String.fromCharCode(event.which).toLowerCase();
var button = inline_style_toolbar.find('[data-accel="' + key + '"]').first();
if (button.length) {
button.trigger('click');
ev.preventDefault();
}
}
}
},
bind_events: function(elem) {
$(elem).on('input', Phylly.input_event);
$(elem).on('keyup click', update_block_style_toolbar);
$(window).on('keydown', this.window_keypress);
},
unbind_events: function(elem) {
$(elem).off('input');
$(elem).off('keyup click');
$(window).off('keydown', this.window_keypress);
},
}
window.Phylly = Phylly;
function upload_image() {
if ($(this).prop('files').length > 0) {
var file = $(this).prop('files')[0];
var params = new FormData();
params.append('upload', file);
$.post({url: '/ajax/upload/', processData: false, data: params, contentType: false}).success(function(data) {
var img = document.createElement('IMG');
img.src = data.url;
if (data.orig_url) {
img.setAttribute('data-orig-url', data.orig_url);
}
$(window.active_figure).empty().append(img);
});
}
}
function upload_document() {
if ($(this).prop('files').length > 0) {
var file = $(this).prop('files')[0];
var params = new FormData();
params.append('upload', file);
$.post({url: '/ajax/upload/', processData: false, data: params, contentType: false}).success(function(data) {
var doc_link = document.createElement('A');
doc_link.className = 'button';
doc_link.textContent = 'Télécharger ' + data.filename;
doc_link.href = data.url;
$(window.active_document).empty().append(doc_link);
});
}
}
function get_contenteditable_subnode(node) {
if (node === null) return null;
if (node.contentEditable === 'true') return node; // but we shouldn't arrive at root
if (node.parentNode.contentEditable === 'true') return node;
return get_contenteditable_subnode(node.parentNode);
}
function get_parent(node, type) {
if (node === null) return null;
if (node.tagName == type) return node;
return get_parent(node.parentNode, type);
}
function get_active_block(node) {
var main_node = get_contenteditable_subnode(node);
if (main_node === null) return null;
for (const block of Phylly.BLOCKS) {
if (main_node.tagName === block.tag && main_node.classList.contains(block.klass))
return block;
}
return null;
}
var block_style_toolbar = null;
function block_style() {
var sel = window.getSelection();
var current_anchor = sel.anchorNode;
if (this.action_block.special == 'img') {
action = 'insertHTML';
param = '
', {text: window.getSelection().toString()})[0].outerHTML;
}
if (action == 'wiki') {
action = 'insertHTML';
var text = window.getSelection().toString();
var $new_link = $('', {text: text, href: '#tbd'});
var request_id = Math.floor(Math.random() * 10000);
$new_link.attr('data-request-id', request_id);
var params = {};
params.title = text;
params.request_id = request_id;
$.post('/wiki/ajax/newpage/', params).success(function(data) {
$('a[data-request-id=' + data.request_id + ']').attr('href', data.url).removeAttr('data-request-id');
});
param = $new_link[0].outerHTML;
}
if (action == 'createLink') {
var sel = window.getSelection();
var selected_link = get_parent(sel.anchorNode, 'A');
if (sel.anchorNode.nodeType == Node.TEXT_NODE) {
if (sel.anchorNode.length == sel.anchorOffset && sel.anchorNode.nextSibling.nodeName == 'A') {
selected_link = sel.anchorNode.nextSibling;
}
}
var $input = $('input[name=link-target]');
$input[0]._range = sel.getRangeAt(0);
if (selected_link) {
$input[0]._selected_link = selected_link;
$input.val(selected_link.href);
}
$input.addClass('shown');
$input.focus();
return;
}
document.execCommand(action, false, param);
}
function validate_link(ev) {
var charCode = typeof ev.which == "number" ? ev.which : ev.keyCode;
if (ev.key == "Enter") {
var $input = $(this);
var range = this._range;
var url = $input.val();
$input.removeClass('shown');
var sel = window.getSelection();
sel.addRange(this._range);
var selected_link = $input[0]._selected_link;
if (url) {
if (selected_link) {
selected_link.href = url;
} else {
var $new_link = $('', {text: sel.toString(), href: url});
this._range.deleteContents();
this._range.insertNode($new_link[0]);
sel.empty();
sel.collapse($new_link[0]);
sel.empty();
}
} else {
if (selected_link) {
selected_link.replaceWith(document.createTextNode(selected_link.textContent));
}
}
$input.val('');
$input[0]._selected_link = null;
}
}
function focusout_link(ev) {
var $input = $(this);
$input.removeClass('shown');
var range = this._range;
var sel = window.getSelection();
sel.addRange(this._range);
}
function show_inline_style_toolbar(sel) {
if (inline_style_toolbar === null) {
inline_style_toolbar = $('