]> git.0d.be Git - chloro.git/blobdiff - chloro/phyll/static/js/chloro.js
do not include non-feed posts on homepage
[chloro.git] / chloro / phyll / static / js / chloro.js
index b5ae3134f5042660ba6f2f37282fedacc330491d..ecc6c97d031f59b2f6bcc777aa9352d9415cba83 100644 (file)
+// from django/contrib/admin/static/admin/js/urlify.js
+var LATIN_MAP = {
+    'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE',
+    'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I',
+    'Î': 'I', 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O',
+    'Õ': 'O', 'Ö': 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U',
+    'Ü': 'U', 'Ű': 'U', 'Ý': 'Y', 'Þ': 'TH', 'Ÿ': 'Y', 'ß': 'ss', 'à': 'a',
+    'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c',
+    'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i', 'î': 'i',
+    'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o',
+    'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u',
+    'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
+};
+
+function downcode(string) {
+  return string.toLowerCase().replace(/[^A-Za-z0-9\[\] ]/g,function(a){ return LATIN_MAP[a]||a }).replace(/[^-\w\s]/g, '').replace(/^\s+|\s+$/g, '').replace(/[-\s]+/g, '-');
+};
+
+function remove_auto_anchors() {
+  $('article .wiki-anchor-auto').each(function(idx, anchor) {
+          $(anchor).parent().removeAttr('id');
+          $(anchor).remove();
+  });
+}
+
+function auto_anchors() {
+  $('article h2, article h3, article h4').each(function(idx, elem) {
+    var $elem = $(elem);
+    if ($elem.attr('id')) return;
+    if ($elem.find('.wiki-anchor').length) return;
+    $elem.attr('id', downcode($elem.text()));
+    $('<a class="wiki-anchor wiki-anchor-auto" href="#' + $elem.attr('id') + '">¶</a>').appendTo($elem);
+  });
+}
+
+function create_toc() {
+  $('#toc').remove();
+  if ($('article h2').length == 0) return;
+  $div_toc = $('<div id="toc"><ul></ul></div>');
+  $div_toc_ul = $div_toc.find('ul');
+  var li_titles = Array();
+  $('article h2').each(function(idx, elem) {
+    var $elem = $(elem);
+    var slug = elem.id;
+    var $a_title = $('<a></a>', {href: '#' + slug, text: $elem.text().replace(/¶$/, '')});
+    var $li_title = $('<li></li>');
+    $li_title[0].related_position =  $(elem).position().top;
+    li_titles.push($li_title[0]);
+    $a_title.appendTo($li_title);
+    $li_title.appendTo($div_toc_ul);
+  });
+  $('article h1').first().after($div_toc);
+
+  li_titles = li_titles.reverse();
+
+  $(window).on('load', function() {
+    // update positions after images have been loaded
+    $('article h2').each(function(idx, elem) {
+      $('#toc li')[idx].related_position =  $(elem).position().top;
+    });
+    $(window).trigger('scroll');
+  });
+
+  var scroll_timeout_id = null;
+  $(window).on('scroll', function() {
+    if (scroll_timeout_id) clearTimeout(scroll_timeout_id);
+    scroll_timeout_id = setTimeout(function() {  // throttle
+      scroll_timeout_id = null;
+      var current_position = window.scrollY;
+      $('#toc li').removeClass('active');
+      for (const li_title of li_titles) {
+        if (li_title.related_position < current_position - 25) {
+          $(li_title).addClass('active');
+          break;
+        }
+      }
+    }, 50);
+  });
+};
+
 (function(window, document, undefined) {
   var Phylly = {
     BLOCKS: [
+          {name: 'intertitle', tag: 'H2', klass: 'intertitle'},
           {name: 'code', tag: 'PRE', klass: 'screen'},
-          {name: 'figure', tag: 'DIV', subtag: true, klass: 'figure'},
+          {name: 'list', special: 'list', tag: 'UL', klass: 'list'},
+          {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) {
-      if (event.originalEvent.inputType != "insertParagraph") return true;
       var sel = document.getSelection();
       var anchorNode = sel.anchorNode;
+      if (sel.anchorNode.contentEditable === 'true' && (
+              sel.anchorNode.innerHTML == '<br>' || !sel.anchorNode.innerHTML)) {
+        // when everything has been removed, add back <p><br></p>
+        var empty_p = document.createElement('P');
+        empty_p.appendChild(document.createElement('BR'));
+        if (anchorNode.childNodes.length) { // lone <br>
+          anchorNode.removeChild(anchorNode.childNodes[0]);
+        }
+        anchorNode.appendChild(empty_p);
+        var range = document.createRange();
+        range.setStart(empty_p, 0);
+        sel.removeAllRanges();
+        sel.addRange(range);
+        return;
+      }
+      if (event.originalEvent.inputType == "insertText") {
+        var main_node = get_contenteditable_subnode(sel.anchorNode);
+        if (main_node.tagName != 'PRE') {
+          var anchorNode = sel.anchorNode;
+          var offset = sel.anchorOffset;
+          var orig_text = sel.anchorNode.data;
+          var text = orig_text;
+          // typography
+          if (event.originalEvent.data === "'") {
+            text = text.slice(0, offset-1) + '’' + text.slice(offset);
+          }
+          if (text != orig_text) {
+            var new_text = document.createTextNode(text);
+            anchorNode.replaceWith(new_text);
+            sel.collapse(new_text, offset);
+          }
+        }
+        return;
+      }
+      if (event.originalEvent.inputType != "insertParagraph") return true;
+      if (sel.anchorNode.tagName == "DIV" && sel.anchorNode.innerHTML == "<br>") {
+        // new empty div got inserted, replace it with a <p>
+        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 == "<br>") {
+        // new empty li got inserted, insert a <p> within
+        var empty_p = document.createElement('P');
+        empty_p.appendChild(document.createElement('BR'));
+        var empty_li = anchorNode;
+        if (empty_li.childNodes.length) { // lone <br>
+          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 sel = window.getSelection();
         if ($(sel.anchorNode).parents('div[contenteditable]').length && sel.toString()) {
-          show_style_popup(sel);
-        } else if (style_popup) {
-          $(style_popup).hide();
+          show_inline_style_toolbar(sel);
+        } else if (inline_style_toolbar) {
+          $(inline_style_toolbar).hide();
+        }
+        if ($(sel.anchorNode).is('div.figure') && $(sel.anchorNode).find('img').length) {
+          show_figure_toolbar(sel);
+        } else if ($(sel.anchorNode).parents('.figure-toolbar').length == 0) {
+          $(figure_toolbar).hide();
         }
       });
+      var $image_upload = $('<input type="file" nam="image" id="image-upload">');
+      $image_upload.on('change', upload_image);
+      $image_upload.appendTo(document.body);
+
+      var $document_upload = $('<input type="file" nam="document" id="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_popup);
+      $(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}).done(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}).done(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;
     return null;
   }
 
-  var block_style_popup = 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 = '<div class="figure"><span class="empty"></span></div><p id="new-p"></p>';
+      document.execCommand(action, false, param);
+      current_anchor = $('#new-p')[0];
+      $(current_anchor).attr('id', null);
+      var range = document.createRange();
+      range.setStart(current_anchor, 0);
+      sel.removeAllRanges();
+      sel.addRange(range);
+      update_block_style_toolbar();
+      return;
+    }
+    if (this.action_block.special == 'doc') {
+      action = 'insertHTML';
+      param = '<div class="document"><span class="empty"></span></div><p id="new-p"></p>';
+      document.execCommand(action, false, param);
+      current_anchor = $('#new-p')[0];
+      $(current_anchor).attr('id', null);
+      var range = document.createRange();
+      range.setStart(current_anchor, 0);
+      sel.removeAllRanges();
+      sel.addRange(range);
+      update_block_style_toolbar();
+      return;
+    }
+    if (this.action_block.special == 'list') {
+      if (this.classList.contains('on')) { // toggle off
+        var main_node = get_contenteditable_subnode(sel.anchorNode);
+        var li = get_parent(sel.anchorNode, 'LI');
+        for (var i=li.childNodes.length; i>0; i--) {
+          var child = li.childNodes[i-1];
+          main_node.insertAdjacentElement('afterend', child);
+          var range = document.createRange();
+          range.setStart(child, 0);
+          sel.removeAllRanges();
+          sel.addRange(range);
+        }
+        li.remove();
+        update_block_style_toolbar();
+      } else {
+        var current_node = sel.anchorNode;
+        var ul = document.createElement('UL');
+        ul.className = 'list';
+        var li = document.createElement('LI');
+        ul.appendChild(li);
+        sel.anchorNode.parentNode.insertBefore(ul, current_node);
+        li.appendChild(current_node);
+        var range = document.createRange();
+        range.setStart(current_node, 0);
+        sel.removeAllRanges();
+        sel.addRange(range);
+      }
+      return;
+    }
     if (this.classList.contains('on')) { // toggle off
       if (this.action_block.subtag) {
         // unwrap
     range.setStart(current_anchor, 0);
     sel.removeAllRanges();
     sel.addRange(range);
-    update_block_style_popup();
+    update_block_style_toolbar();
   }
-  function update_block_style_popup() {
+  function update_block_style_toolbar() {
     var sel = window.getSelection();
     if (! ((sel.anchorNode instanceof Element && (sel.anchorOffset == 0 && sel.isCollapsed)) || get_active_block(sel.anchorNode))) {
-      if (block_style_popup) {
-        $(block_style_popup).hide();
+      if (block_style_toolbar) {
+        $(block_style_toolbar).hide();
       }
       return true;
     }
-    if (block_style_popup === null) {
-      block_style_popup = $('<div class="block-style-popup"></div>');
+    if (block_style_toolbar === null) {
+      block_style_toolbar = $('<div class="block-style-popup"></div>');
       for (const block of Phylly.BLOCKS) {
         var button = document.createElement('button');
         button.action_block = block;
         button.dataset.action = block.name;
         button.textContent = block.name;
-        block_style_popup.append(button);
+        block_style_toolbar.append(button);
       }
-      block_style_popup.hide();
-      block_style_popup.insertAfter(document.body);
-      block_style_popup.find('button').on('click', block_style);
+      block_style_toolbar.hide();
+      block_style_toolbar.insertAfter(document.body);
+      block_style_toolbar.find('button').on('click', block_style);
     }
-    block_style_popup.css('position', 'absolute');
+    block_style_toolbar.css('position', 'absolute');
     var block = get_active_block(sel.anchorNode);
-    block_style_popup.find('button').removeClass('on');
+    block_style_toolbar.find('button').removeClass('on');
     if (block) {
-      block_style_popup.find('[data-action=' + block.name + ']').addClass('on');
-      block_style_popup.addClass('selected');
+      block_style_toolbar.find('[data-action=' + block.name + ']').addClass('on');
+      block_style_toolbar.addClass('selected');
     } else {
-      block_style_popup.removeClass('selected');
+      block_style_toolbar.removeClass('selected');
     }
     var anchor = get_contenteditable_subnode(sel.anchorNode);
     var pos = $(anchor).offset();
-    block_style_popup.css('top', pos.top - 33);
-    block_style_popup.css('left', pos.left);
-    block_style_popup.show();
+    block_style_toolbar.css('top', pos.top - 33);
+    block_style_toolbar.css('left', pos.left);
+    block_style_toolbar.show();
     return true;
   }
 
-  var style_popup = null;
+  var inline_style_toolbar = null;
   function update_style() {
     var action = $(this).data('action');
     var param = null;
       action = 'insertHTML';
       param = $('<code></code>', {text: window.getSelection().toString()})[0].outerHTML;
     }
+    if (action == 'wiki') {
+      action = 'insertHTML';
+      var text = window.getSelection().toString();
+      var $new_link = $('<a></a>', {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('/ajax/newpage/', params).done(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 (sel.anchorNode instanceof Element) {
-        var elem = sel.anchorNode.childNodes[sel.anchorOffset];
-        if (elem.tagName == 'A') {
-          $input.val(elem.href);
-        }
+      if (selected_link) {
+        $input[0]._selected_link = selected_link;
+        $input.val(selected_link.href);
       }
       $input.addClass('shown');
       $input.focus();
       $input.removeClass('shown');
       var sel = window.getSelection();
       sel.addRange(this._range);
+      var selected_link = $input[0]._selected_link;
       if (url) {
-        document.execCommand('createLink', false, url);
+        if (selected_link) {
+          selected_link.href = url;
+        } else {
+          var $new_link = $('<a></a>', {text: sel.toString(), href: url});
+          this._range.deleteContents();
+          this._range.insertNode($new_link[0]);
+          sel.empty();
+          sel.collapse($new_link[0]);
+          sel.empty();
+        }
       } else {
-        document.execCommand('unlink', false, null);
+        if (selected_link) {
+          selected_link.replaceWith(document.createTextNode(selected_link.textContent));
+        }
       }
-      sel.empty();
       $input.val('');
+      $input[0]._selected_link = null;
     }
   }
   function focusout_link(ev) {
     sel.addRange(this._range);
   }
 
-  function show_style_popup(sel) {
-    if (style_popup === null) {
-      style_popup = $('<div class="inline-style-popup">' +
-                      '<button data-action="italic"><i>i</i></button>' +
-                      '<button data-action="bold"><b>b</b></button>' +
-                      '<button data-action="code">&lt;&gt;</button>' +
-                      '<button data-action="removeFormat">×</button>' +
+  function show_inline_style_toolbar(sel) {
+    if (inline_style_toolbar === null) {
+      inline_style_toolbar = $('<div class="inline-style-popup">' +
+                      '<button data-action="italic" data-accel="i"><i>i</i></button>' +
+                      '<button data-action="bold" data-accel="b"><b>b</b></button>' +
+                      '<button data-action="code" data-accel="<">&lt;&gt;</button>' +
+                      '<button data-action="removeFormat" data-accel="m">×</button>' +
+                      '<button data-action="wiki">W</button>' +
                       '<button data-action="createLink">a</button>' +
                       '<input name="link-target"/>' +
                       '</div>');
-      style_popup.hide();
-      style_popup.insertAfter(document.body);
-      style_popup.find('button').on('click', update_style);
-      style_popup.find('[name=link-target]').on('keypress', validate_link).on('focusout', focusout_link);
+      inline_style_toolbar.hide();
+      inline_style_toolbar.insertAfter(document.body);
+      inline_style_toolbar.find('button').on('click', update_style);
+      inline_style_toolbar.find('[name=link-target]').on('keypress', validate_link).on('focusout', focusout_link);
     }
-    style_popup.css('position', 'absolute');
+    inline_style_toolbar.css('position', 'absolute');
     var pos = sel.getRangeAt(0).getClientRects()[0];
-    style_popup.css('top', pos.top + window.scrollY - 33);
-    style_popup.css('left', pos.left + window.scrollX);
-    style_popup.show();
+    inline_style_toolbar.css('top', pos.top + window.scrollY - 33);
+    inline_style_toolbar.css('left', pos.left + window.scrollX);
+    inline_style_toolbar.show();
   };
+
+  var figure_toolbar = null;
+  function show_figure_toolbar(sel) {
+    if (figure_toolbar === null) {
+      figure_toolbar = $('<div class="figure-toolbar"><label>Alt: <input name="figure-alt"></label></div>')
+      figure_toolbar.hide();
+      figure_toolbar.insertAfter(document.body);
+      $('[name="figure-alt"]').on('change', function() {
+       $(this.img).attr('alt', $(this).val());
+      });
+    }
+    figure_toolbar.css('position', 'absolute');
+    var pos = sel.getRangeAt(0).getClientRects()[0];
+    figure_toolbar.css('top', pos.bottom + window.scrollY);
+    figure_toolbar.css('left', pos.left + window.scrollX);
+    figure_toolbar.show();
+    $('[name="figure-alt"]')[0].img = $(sel.anchorNode).find('img');
+    $('[name="figure-alt"]').val($('[name="figure-alt"]')[0].img.attr('alt') || '');
+  };
+
 }(window, document));
 
 $(function() {
-  Phylly.init(),
-  $('div[contenteditable]').each(function(i, elem) {Phylly.bind_events(elem)});
-  $('#save').on('click', function() {
-    var text = $('div[contenteditable]')[0].innerHTML;
-    var csrf = $('[name=csrfmiddlewaretoken]').val();
-    $.post('api-save/',
-      { text: text, csrfmiddlewaretoken: csrf}
-    ).fail(function() {
-      $('#save').css('background', 'red');
+  $('#quickedit input').on('change', function() {
+    var enable = $(this).is(':checked');
+    if (enable) {
+      remove_auto_anchors();
+      $('div[data-editable]').each(function(i, elem) {
+        $(elem).attr('contenteditable', 'true');
+        var $button = $('<button class="save">Enregistrer</button>');
+        $button[0].div_zone = elem;
+        $button.insertBefore($('#quickedit label'));
+      });
+      Phylly.init(),
+      $('div[data-editable]').each(function(i, elem) {
+        Phylly.bind_events(elem);
+      });
+      $('.save').on('click', function() {
+        var text = $('div[contenteditable]')[0].innerHTML;
+        var csrf = $('[name=csrfmiddlewaretoken]').val();
+        $.post('api-save/',
+          { text: text, csrfmiddlewaretoken: csrf}
+        ).fail(function() {
+          $('.save').addClass('error');
+        }).done(function() {
+          $('.save').removeClass('error');
+        });
+        return false;
+      });
+    } else {
+      auto_anchors();
+      if ($('main.phyll-toc').length) create_toc();
+      Phylly.off(),
+      $('button.save').remove();
+      $('div[data-editable]').each(function(i, elem) {
+        $(elem).attr('contenteditable', 'false');
+        Phylly.unbind_events(elem);
+      });
+    }
+  });
+  $('#quickedit input').trigger('change');
+  if ($('#quickedit input').length == 0) {
+    create_toc();
+  }
+  $('.search-results').empty();
+  $('#search-enable').on('change', function() {
+    if ($(this).is(':checked')) {
+      $('.search-field input').focus();
+    }
+  });
+  $('.search-field').on('submit', function() {
+    var value = $('input[name=q]').val();
+    $.ajax({url: '/ajax/search/', data: {q: value}}).done(function(data) {
+      $('.search-results').empty();
+      for (const hit of data.data) {
+        var $a_hit = $('<a>', {text: hit.title, href: hit.url});
+        var $li_hit = $('<li>');
+        $li_hit.append($a_hit);
+        $('.search-results').append($li_hit);
+      }
     });
     return false;
   });