X-Git-Url: https://git.0d.be/?p=chloro.git;a=blobdiff_plain;f=chloro%2Fphyll%2Fstatic%2Fjs%2Fchloro.js;h=6b831ac2588c7f92e10609c2a5b643512a0659a7;hp=9988be42a16aa8a95cf926979f2b5260465aa904;hb=1684cf04e518914a3266d7e57d48b68d6020d1b6;hpb=ed4760479d8f34e6d9acc1659141571ad7d3e790
diff --git a/chloro/phyll/static/js/chloro.js b/chloro/phyll/static/js/chloro.js
index 9988be4..6b831ac 100644
--- a/chloro/phyll/static/js/chloro.js
+++ b/chloro/phyll/static/js/chloro.js
@@ -1,11 +1,59 @@
-$(function() {
- $('div[contenteditable]').on('input', function(event) {
- if (event.originalEvent.inputType == "insertParagraph") {
+(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'},
+ ],
+ 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) {
@@ -14,12 +62,298 @@ $(function() {
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);
+
+ $(document).on('click', 'div.figure span.empty', function() {
+ window.active_figure = this.parentNode;
+ $('#image-upload').trigger('click');
+ return true;
+ });
+ },
+
+ off: function() {
+ $('#image-upload').remove();
+ if (block_style_toolbar) { block_style_toolbar.hide(); }
+ if (inline_style_toolbar) { inline_style_toolbar.hide(); }
+ $(document).off('selectionchange');
+ },
+
+ bind_events: function(elem) {
+ $(elem).on('input', Phylly.input_event);
+ $(elem).on('keyup click', update_block_style_toolbar);
+ },
+
+ unbind_events: function(elem) {
+ $(elem).off('input');
+ $(elem).off('keyup click');
+ },
+
+ }
+ window.Phylly = Phylly;
+
+ function upload_image() {
+ if ($(this).prop('files').length > 0) {
+ var file = $(this).prop('files')[0];
+ var params = new FormData();
+ params.append('image', file);
+ $.post({url: '/wiki/ajax/image/', 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 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 $input = $('input[name=link-target]');
+ $input[0]._range = sel.getRangeAt(0);
+ if (sel.anchorNode instanceof Element) {
+ var elem = sel.anchorNode.childNodes[sel.anchorOffset];
+ if (elem.tagName == 'A') {
+ $input.val(elem.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);
+ if (url) {
+ document.execCommand('createLink', false, url);
+ } else {
+ document.execCommand('unlink', false, null);
+ }
+ sel.empty();
+ $input.val('');
+ }
+ }
+ 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 = $('