Adds a button to Summernote that inserts HTML snippets required by Marketplace themes.
// ==UserScript==
// @name [Deprecated] Kanka Marketplace Plugin HTML Inserter for Summernote
// @namespace http://tampermonkey.net/
// @version 4
// @description Adds a button to Summernote that inserts HTML snippets required by Marketplace themes.
// @author Salvatos
// @match https://kanka.io/*
// @icon https://www.google.com/s2/favicons?domain=kanka.io
// @grant none
// @run-at document-end
// ==/UserScript==
// Wait for Summernote to initialize
$('#entry').on('summernote.init', function() {
// Prepare to check for supported themes in the campaign
var rootFlags = getComputedStyle(document.documentElement);
// Define our supported code snippets
let snippets = [];
// Build list items for our supported code snippets
let themes = [];
// Figure Box and Floats by Ornstein
if (rootFlags.getPropertyValue('--summernote-insert-figure-box') || 1 === 1) { // Temporary bypass for initial release
snippets.push('<div class="figure">Insert image and caption here</div>');
snippets.push('<div class="figure r clear">Insert image and caption here</div>');
themes.push('<li aria-label="Figure Box and Floats (no float)"><a href="#">Figure Box (no float)</a></li>');
themes.push('<li aria-label="Figure Box and Floats (float right + clear)"><a href="#">Figure Box (float right + clear)</a></li>');
}
// Responsive Image Gallery by Salvatos
if (rootFlags.getPropertyValue('--summernote-insert-autogallery') || 1 === 1) { // Temporary bypass for initial release
snippets.push('<div class="autogallery">Insert gallery images here</div>');
themes.push('<li aria-label="Responsive Image Gallery"><a href="#">Responsive Image Gallery</a></li>');
}
// Simple Tooltips by KeepOnScrollin
if (rootFlags.getPropertyValue('--summernote-insert-simple-tooltip') || 1 === 1) { // Temporary bypass for initial release
snippets.push('<span class="simple-tooltip">Tooltip trigger<span class="simple-tooltip-text top">Tooltip content</span></span>');
themes.push('<li aria-label="Simple Tooltip (top)"><a href="#">Simple Tooltip (top)</a></li>');
}
// Tip Box by Critter
if (rootFlags.getPropertyValue('--summernote-insert-tip-box') || 1 === 1) { // Temporary bypass for initial release
snippets.push('<div class="tipbox-small">Small Tip Box text.</div>');
snippets.push('<div class="tipbox-big">Big Tip Box text.</div>');
themes.push('<li aria-label="Tip Box (small)"><a href="#">Tip Box (small)</a></li>');
themes.push('<li aria-label="Tip Box (big)"><a href="#">Tip Box (big)</a></li>');
}
var themeList = themes.join("");
// Locate toolbar and insert our dropdown button
const toolbar = document.getElementsByClassName('note-toolbar')[0];
var customButton = `
<div class="note-btn-group btn-group note-style">
<div class="note-btn-group btn-group">
<button type="button" class="note-btn btn btn-default btn-sm dropdown-toggle note-codeview-keep" tabindex="-1" data-toggle="dropdown" title="Marketplace theme HTML snippets" aria-expanded="false">
<i class="fas fa-puzzle-piece"></i> <span class="note-icon-caret"></span>
</button>
<ul class="note-dropdown-menu dropdown-menu dropdown-snippets" aria-label="Marketplace theme HTML snippets">
` + themeList + `
</ul>
</div>
</div>`;
toolbar.insertAdjacentHTML("beforeend", customButton);
// Grab our completed dropdown
const dropdown = document.getElementsByClassName('dropdown-snippets')[0];
// Make sure we have at least one supported theme enabled
if (dropdown.children[0]) {
// Add click events to editor
for (let i = 0; i < dropdown.children.length; i++) {
var currentButton = dropdown.children[i];
currentButton.addEventListener('click', ()=>{
// Code editor, not supported by Summernote functions so we're making our own
if ($('#entry + div').hasClass('codeview')) {
const codeEditor = $('#entry + div').find('.note-codable');
var cursorPos = codeEditor.prop('selectionStart');
var editorValue = codeEditor.val();
var textBefore = editorValue.substring(0, cursorPos);
var textAfter = editorValue.substring(cursorPos, editorValue.length);
var newPos = cursorPos + snippets[i].length + 1;
codeEditor.val(textBefore + '\n' + snippets[i] + textAfter);
// Return focus to textarea and select newly inserted string to make it clear to the user
codeEditor[0].focus();
codeEditor[0].setSelectionRange(cursorPos, newPos);
// Update Summernote’s hidden textarea in case of immediate saving
$('#entry').val(codeEditor.val());
}
// Visual editor, API has us covered here
else {
var insertNode = $.parseHTML(snippets[i])[0];
$('#entry').summernote('insertNode', insertNode);
}
});
}
}
else {
dropdown.insertAdjacentHTML("beforeend", "<li><a href='#'><em>No supported theme found</em></a></li>");
}
});
/*
* TODO: A different script (or button + function) should be used for themes that only need to add classes to any element, such as Redacted Text, Context-Aware Classes and .boxquote.
* Those would only work in the visual editor since there I can target those elements as objects and manipulate their classes.
* The question is how we would identify the node that corresponds to the cursor position.
*/
/* Reference for a single button (consider using the API instead: https://summernote.org/deep-dive/#custom-button )
// Wait for Summernote to initialize
$('#entry').on('summernote.init', function() {
const toolbar = document.getElementsByClassName('note-toolbar')[0];
var customButton = `
<div class="note-btn-group btn-group note-extensions custom-summernote-button">
<button type="button" class="note-btn btn btn-default btn-sm note-codeview-keep" tabindex="-1" title="Custom button">
<i class="fas fa-file-import" aria-hidden="true"></i>
</button>
</div>`;
toolbar.insertAdjacentHTML("beforeend", customButton);
// Add input event to code editor
customButton = document.getElementsByClassName('custom-summernote-button')[0];
customButton.addEventListener('click', ()=>{
// your actions here
});
}*/