c997bc792f12b6da36a579b5380ffdebc6042eac
[chloro.git] / chloro / phyll / static / js / chloro.js
1 $(function() {
2   $('div[contenteditable]').on('input', function(event) {
3     if (event.originalEvent.inputType == "insertParagraph") {
4       var sel = document.getSelection();
5       var anchorNode = sel.anchorNode;
6       var prev_p = sel.anchorNode.previousSibling;
7       if (prev_p.tagName != 'P') {
8         prev_p = $(prev_p).parents('p')[0];
9       }
10       var title_match = prev_p.innerText.match(/^(h[1-6]). /);
11       if (title_match) {
12         var title = document.createElement(title_match[1]);
13         title.innerHTML = prev_p.innerHTML;
14         title.textContent = title.textContent.slice(4);
15         prev_p.replaceWith(title);
16       }
17     }
18     return true;
19   });
20
21   $('#save').on('click', function() {
22     var text = $('div[contenteditable]')[0].innerHTML;
23     var csrf = $('[name=csrfmiddlewaretoken]').val();
24     $.post('api-save/',
25       { text: text, csrfmiddlewaretoken: csrf}
26     ).fail(function() {
27       $('#save').css('background', 'red');
28     });
29     return false;
30   });
31
32   var style_popup = null;
33   function update_style() {
34     var action = $(this).data('action');
35     var param = null;
36     if (action == 'code') {
37       action = 'insertHTML';
38       param = $('<code></code>', {text: window.getSelection().toString()})[0].outerHTML;
39     }
40     if (action == 'createLink') {
41       var sel = window.getSelection();
42       var $input = $('input[name=link-target]');
43       $input[0]._range = sel.getRangeAt(0);
44       if (sel.anchorNode instanceof Element) {
45         var elem = sel.anchorNode.childNodes[sel.anchorOffset];
46         if (elem.tagName == 'A') {
47           $input.val(elem.href);
48         }
49       }
50       $input.addClass('shown');
51       $input.focus();
52       return;
53     }
54     document.execCommand(action, false, param);
55   }
56   function validate_link(ev) {
57     var charCode = typeof ev.which == "number" ? ev.which : ev.keyCode;
58     if (ev.key == "Enter") {
59       var $input = $(this);
60       var range = this._range;
61       var url = $input.val();
62       $input.removeClass('shown');
63       var sel = window.getSelection();
64       sel.addRange(this._range);
65       if (url) {
66         document.execCommand('createLink', false, url);
67       } else {
68         document.execCommand('unlink', false, null);
69       }
70       sel.empty();
71       $input.val('');
72     }
73   }
74   function focusout_link(ev) {
75     var $input = $(this);
76     $input.removeClass('shown');
77     var range = this._range;
78     var sel = window.getSelection();
79     sel.addRange(this._range);
80   }
81
82   function show_style_popup(sel) {
83     if (style_popup === null) {
84       style_popup = $('<div id="style-popup">' +
85                       '<button data-action="italic"><i>i</i></button>' +
86                       '<button data-action="bold"><b>b</b></button>' +
87                       '<button data-action="code">#</button>' +
88                       '<button data-action="removeFormat">×</button>' +
89                       '<button data-action="createLink">a</button>' +
90                       '<input name="link-target"/>' +
91                       '</div>');
92       style_popup.hide();
93       style_popup.insertAfter($('.actions'));
94       style_popup.find('button').on('click', update_style);
95       style_popup.find('[name=link-target]').on('keypress', validate_link).on('focusout', focusout_link);
96     }
97     style_popup.css('position', 'absolute');
98     var pos = sel.getRangeAt(0).getClientRects()[0];
99     style_popup.css('top', pos.top + window.scrollY - 33);
100     style_popup.css('left', pos.left + window.scrollX);
101     style_popup.show();
102   };
103   $(document).on('selectionchange', function(event) {
104     if ($('input[name=link-target].shown').length) {
105       return;
106     }
107     var sel = window.getSelection();
108     if ($(sel.anchorNode).parents('div[contenteditable]').length && sel.toString()) {
109       show_style_popup(sel);
110     } else if (style_popup) {
111       $(style_popup).hide();
112     }
113   });
114 });