Add dynamic custom buttons as array in summernote - javascript

I use the wysiwyg editor "summernote" and codeigniter. I want add my own buttons to the toolbar that insert spezific text on click. That scenario is describes in the summernote documentation.
Summernote:
$('#model_txt').summernote({
height: 250,
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['font', ['strikethrough', 'superscript', 'subscript']],
['fontsize', ['fontsize']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['height', ['height']]
]
});
But i get the button names respectively the text that insert on click from a database. I get the data with an ajax call that call a PHP function that print the data from the query.
AJAX call:
var all_vars = null;
$.ajax({url: "get_vars", success: function(result){
all_vars = result.split(";");
});
Now i have an array that contains the names (example: all_vars[0]).
But i don't know how can i insert the names as buttons in the toolbar... can you help me?
Can't anybody help me? I try this with the JS function eval() and it works but i think its not the best solution...
The PHP function on "127.0.0.1/create_var_buttons" create the JS code dynamicly.
<script>
$(document).ready(function() {
var resturl = 'http://127.0.0.1/create_var_buttons';
$.ajax({
url: resturl,
success: function(data){
eval(data);
}
});
});

I faced the same need before and done this way:
I had to declare a variable to hold the summernote's toolbar array:
var toolbar = [
['style', ['bold', 'italic', 'underline', 'clear']],
['insert', ['picture', 'link']],
['misc', ['undo', 'redo', 'codeview']],
['para', ['ul', 'ol', 'paragraph']],
['fontsize', ['fontsize', 'height']],
['color', ['color']],
['forecolor', ['forecolor']],
['custom', ['forcarJustificar']]
];
Another to hold the data to summernotes's "buttons" property:
var opt_btns_custom = {
forcarJustificar: forcarJustificar
};
Another variable to hold the entire summernote's options:
var sm_options = {
height: altura,
toolbar: toolbar,
buttons: opt_btns_custom,
callbacks: {}
}
Then I wrote the function below that I call into the Ajax's .done() for each button that need to be created:
function addBtnText(b_content, b_tooltip, text) {
var sm_botao_custom = function (context) {
var ui = $.summernote.ui;
options = {
contents: b_content,
tooltip: b_tooltip,
click: function () {
context.invoke('editor.insertText', text);
}
}
var button = ui.button(options);
return button.render();
}
i = Math.floor(Math.random() * (1000 - 1 + 1)) + 1;
toolbar.push(['custom', ['sm_botao_custom_'+i]]);
opt_btns_custom['sm_botao_custom_'+i] = sm_botao_custom;
//Restart SM to apply the created buttons
$('#d_summernote').summernote('destroy');
$('#d_summernote').summernote(sm_options);
}
OBS: I use a random number (i) to avoid conflict problems with the buttons inside the SM.

Related

liverwire summernote not triggering changes in the textarea

could someone please assist, I am trying to use livewire components and summer note and I have the functionality working when its a normal input field, but as soon as I change the class to summer note, the values no longer update as I type. Any help would be much appreciated!
The livelier form:
<div>
<p>{{ $note }}</p>
<textarea class="summernote" id="kt_summernote_1" name="note" wire:model="note"></textarea>
</div>
The php file:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class LessonContentForm extends Component
{
public $note;
public function render()
{
return view('livewire.lesson-content-form');
}
}
Finally the JS for SummerNote:
<script type="text/javascript">
"use strict";
// Class definition
var KTSummernoteDemo = function () {
// Private functions
var demos = function () {
$('.summernote').summernote({
height: 400,
tabsize: 2,
});
}
return {
// public functions
init: function() {
demos();
}
};
}();
// Initialization
jQuery(document).ready(function() {
KTSummernoteDemo.init();
});
</script>
The best way to go will be to use a callback function.
<div wire:ignore>
<textarea wire:model.defer="description" id="summernote"></textarea>
</div>
/////////////////////////////////////////////////////////////////////////////////////
<script>
$('#summernote').summernote({
placeholder: 'Type something cool',
tabsize: 2,
height: 400,
focus: true,
toolbar: [
['font', ['bold', 'underline', 'clear']],
['para', ['paragraph']],
['insert', ['picture', 'video']],
],
callbacks: {
onChange: function(e) {
#this.set('description', e);
},
}
});
</script>
This uses jQuery and also if your livewire property still isn't in sync with your editor then you need to dispatch a browser event from your livewire component for this editor script above.

How to render <style> tag using DOMPurify

In our application for a very specific scenario (at only one place) we need to bypass the tag and render it on the DOM using DOMPurify.
var htmlScript = "<style>*{color: red}</style>"; // something like this
var clean = dompurify.sanitize(htmlScript, { ADD_TAGS: ['style']});
return clean;
Does anyone know how to achieve it ?
I believe you can do that with these 3 options: FORCE_BODY, ALLOWED_TAGS, and ALLOWED_ATTR.
Example:
outHtml = domPurify.sanitize(outHtml, {
FORCE_BODY: true,
ALLOWED_ATTR: ['style', 'class', 'type', 'href', 'rel'],
// must add these tag manually if use this option.
ALLOWED_TAGS: [
'link',
'figure',
'table',
'caption',
'thead',
'tr',
'th',
'tbody',
'td',
],
});

Create a custom button plugin in Summernote

I'm trying to create a custom button plugin in Summernote, but the ui.button creates of course, a button. Is there any way to make that a div for example?
context.memo('button', function() {
return ui.buttonGroup([
ui.button({
className: 'someClass',
tooltip: 'tooltipInfo',
data: {
toggle: 'dropdown'
},
click: function() {}
}),
What I tried is to do:
var buttonGroup = ui.buttonGroup([ ... ]);
buttonGroup.changeTag('div');
return buttonGroup;
Then update manually the button and change its tag to div. It "works" but for instance, the click event in the buttonGroup that I set doesn't work in this case.
Even tried attaching an on('click') event to buttonGroup variable, and still, the click isn't triggering.
Any ideas on how I can achieve this in another way?
The process of creating a button for summernote is relatively simple, you should first create a variable for your button.
In this variable you will assign a function that collects the summernote UI and then assign it a button with the desired properties inside it.
Already when loading summernote you will pass as the parameter of UI the variable used to create your button, as you can see in the example below
var btnAttch = function (context) {
var ui = $.summernote.ui;
var button = ui.button({
contents:
'<label class="custom-file-upload"> <input type="file" class="input-file" id="input-file-' + id + '" multiple/>' +
'<i class="glyphicon glyphicon-paperclip"></i> </label>',
tooltip: 'Attach file',
});
}
$(".txtInstrucoes-" + id).summernote({
height: 300,
toolbar: [
['style', ['bold', 'italic', 'underline']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['fontsize', ['fontsize']],
['btn-anexar', ['btnAnexar']]
],
buttons: {
btnAttch: btnAttch
},
disableDragAndDrop: true,
disableResizeEditor: true,
callbacks: {
onInit: function () {
$.EmpresaAPI.Events.OnChangeInputFile(id);
},
}
})

Dijit Dialog in JSFiddle launching immediately - not onClick

I'm struggling to get a Dijit dialog to work for a reproducible example. I took the working code from this JSfiddle and simply tried to turn this into a named function to use throughout the example.
The author uses:
new Button({label: 'Show dialog', onClick: function() {
//Create dialog programmatically here
}
});
but I've changed this to be slightly different:
function launchSelectDialog(selectOptions) {
//Create dialog programmatically here
}
registry.byId("default-launch", "onClick", launchSelectDialog(allOpts));
Here is my version. Unfortunately, this just launches the dialog immediately upon loading the page, and never again when clicking on the button.
I have checked the NoWrap option in JSFiddle. I have no other clues about what's going on.
Please help if you have any ideas.
There are couple of issue.
1) Like others a have pointed out, you are invoking the function not setting up the event with function. hence the dialog is visible onload.
2) You need to wait till the html has been parse. or you need to use parser.parse()
Here is the updated fiddler: http://jsfiddle.net/49y3rxzg/9/
() is an invocation operator. You are calling the function yourself and the returned value of the function is set as the event handler. If you want to reuse the function, use a closure:
function launchSelectDialog(selectOptions) {
// the returned function will be used as the event handler
return function() {
// the passed `selectOptions` is remembered in this context
}
}
Another option is:
registry.byId("default-launch", "onClick", function() {
launchSelectDialog(allOpts);
});
You need to initiate your Button widget before retrieving with registry.byId().
In your code actually registry.byId("default-launch") was returning undefined;
Also registry.byId() function accept only an id so additional parameters will be ignored.
To fix it you should initiate a Button instance properly and declare launchSelectDialog(allOpts) withinonClick, as:
var myButton = new Button({
label: "Default Options",
onClick: function() {
launchSelectDialog(allOpts);
}
}, "default-launch");
Below fixed version for your script.
http://jsfiddle.net/usm829jq/
require([
"dojo/dom",
"dijit/Dialog",
"dijit/form/Button",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dijit/registry",
"dojo/domReady!"
], function(dom, DijitDialog, Button, BorderContainer, ContentPane, registry) {
var allOpts = [{
label: "Foo",
value: "foo"
}, {
label: "Bar",
value: "bar"
}]
var myButton = new Button({
label: "Default Options",
onClick: function() {
launchSelectDialog(allOpts);
}
}, "default-launch");
function launchSelectDialog(SelectOptions) {
var layout = new BorderContainer({
design: "headline",
style: "width: 400px; height: 400px; background-color: yellow;"
});
var centerPane = new ContentPane({
region: "center",
style: "background-color: green;",
content: "center"
});
var actionPane = new ContentPane({
region: "bottom",
style: "background-color: blue;"
});
(new Button({
label: "OK"
})).placeAt(actionPane.containerNode);
(new Button({
label: "Cancel"
})).placeAt(actionPane.containerNode);
layout.addChild(centerPane);
layout.addChild(actionPane);
layout.startup();
var dialog = new DijitDialog({
title: 'dialog title',
style: {
//width: '400px',
//height: '400px',
},
content: layout
});
dialog.containerNode.style.backgroundColor = "red";
dialog.startup();
dialog.show();
}
})

Summernote custom dialog and button

I try to implement Summertnote editor. Here is the JS code:
$(document).ready(function() {
//Summernote
//var te_markdown = document.getElementById("code-markdown");.
var textarea = document.getElementById("code");
var HelloButton = function (context) {
var ui = $.summernote.ui;
// create button
var button = ui.button({
contents: '<i class="fa fa-child"/> Hello',
tooltip: 'Ciao!',
click: function () {
// invoke insertText method with 'hello' on editor module.
context.invoke('editor.insertText', 'hello');
}
});
return button.render(); // return button as jquery object
}
function autoFormat() {
var totalLines = editor.lineCount();
editor.autoFormatRange({line:0, ch:0}, {line:totalLines});
}
$('#st-editor').summernote({
lang: 'it-IT', // set italian language
height: 350, // set editor height
width: 350, // set editor width
minHeight: null, // set minimum height of editor
maxHeight: null, // set maximum height of editor
dialogsFade: true, // set fade on dialog
prettifyHtml: false,
toolbar: [
['mybutton', ['hello']]
],
buttons: {
hello: HelloButton
},
codemirror: { // codemirror options
mode: "text/html",
lineNumbers: true,
lineWrapping: true,
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
foldGutter: true,
theme: 'monokai',
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
}
},
focus: true set focus to editable area after initializing summernote
});
I get the code here: http://summernote.org/deep-dive/#custom-button
So, In this example I want to simply put a "Hello" string clicking the button but it gives me an error "TypeError: context is undefined". Can someone help me?
Thanks
Instead of
context.invoke('editor.insertText', 'hello');
use
$('#st-editor').summernote('editor.insertText', 'hello');
works only if you have one editor of course. I'm still searching how to get this context thingy passed. Maybe something with onInit, but I couldn't get it working yet.
#wessel code works, for multiple ids I do an iteration using jQuery each:
Make sure oyu attach an id attribute to all editors:
if ($('.summernote').length) {
var blockQuoteButton = function(itemId) {
var ui = $.summernote.ui;
var button = ui.button({
className: 'note-btn-blockquote',
contents: '<i class="fa fa-quote-right">Quo</i>',
tooltip: 'Blockquote',
click: function() {
$('#' + itemId).summernote('editor.formatBlock', 'blockquote');
}
});
return button.render();
}
$('.summernote').each(function(k, item) {
let itemId = $(item).attr('id');
$('#' + itemId).summernote({
height: 100,
toolbar: [
['style', ['style']],
['font', ['bold', 'italic', 'underline']],
['para', ['ul', 'ol']],
['mybutton', ['blq']]
],
buttons: {
blq: blockQuoteButton(itemId)
}
});
});
}
This issue appeared in version 0.8.12. Reverting back to 0.8.10 fixes it
Inside package.json specify
"dependencies": {
...
"ngx-summernote": "0.7.0",
"summernote": "0.8.10",
...
},
and run npm install afterwards. It works after that

Categories

Resources