How to change enter behaviour in summernote - summernote

I have get this old code
// myenter.js, enter key is binded to insertParagraph command.
$.summernote.addPlugin({
name : 'myenter',
events : {
// redefine insertParagraph
'insertParagraph' : function(event, editor, layoutInfo) {
//you can use summernote enter
//layoutInfo.holder().summernote('insertParagraph');
// also you can use your enter key
layoutInfo.holder().summernote('insertNode', document.createTextNode("\r\n"));
// to stop enter key
//e.preventDefault();
}
}
});
$('.summernote').summernote({ height : 300 });
but now method of add plugin has changed and i want this functionality with new version by this code
$.extend($.summernote.plugins, {
'myenter': function (context) {
console.log('myenter');
}
});
but it is not called at all
I had tried to get same functionality by
summernote.onEnter
and
summernote.keyPress
but it gives error..

$.extend($.summernote.plugins, {
'brenter': function (context) {
this.events = {
'summernote.enter': function (we, e) {
// insert 2 br tags (if only one br tag is inserted the cursor won't go to the next line)
document.execCommand('insertHTML', false, '<br><br>');
e.preventDefault();
}
};
}
}

I managed to fix it like this:
$('#summernote').summernote('destroy');
$.extend($.summernote.plugins, {
'brenter': function (context) {
this.events = {
'summernote.enter': function (we, e) {
//get hold of the enter event and trigger a shift+enter keypress
e.trigger($.Event("keydown", {
keyCode: 13, // ENTER
shiftKey: true
}));
//stop the normal event from happening
e.preventDefault();
}
};
}
});
// then do summernote as normal...
$('#summernote').summernote({

Related

Pressing Tab while editing, control goes to browser .Expect to move to next cell while using : DHTMLX grid

Documentation : https://docs.dhtmlx.com/suite/grid__api__refs__grid.html
Here is my code to create grid
grid = new GridDHX(gridContainer.current, {columns: props.columns,data: props.data,adjust: true,
editable: true,
autoEmptyRow: true,
autoWidth: true,
selection: "cell",
enableEditEvents: true
});
And Modified click event for editing
grid.current.events.on("CellClick", function(
row,
column,
e
) {
grid.editCell(row.id, column.id);
});
}
I want tab should take next cell and become editable. I tried below code to end editing while pressing tab
grid.events.on("beforeKeyDown", function (e) {
if (e.key === "Tab") {
grid.editEnd()
}
})
I think u can try something like this:
grid.events.on("BeforeKeyDown", (e) => {
if (e.key === "Tab") {
grid.editEnd()
}
})
grid.events.on("AfterKeyDown", (e) => {
if (e.key === "Tab") {
var selected = grid.selection.getCell();
if (selected) {
grid.editCell(selected.row.id, selected.column.id);
}
}
})
https://snippet.dhtmlx.com/6bs7mh34

SPFX webpart property pane

I am trying to append sharepoint lists in dropdown of spfx webpart property pane. but its not getting appended. please help out.
export default class ScrollTickerWebPart extends BaseClientSideWebPart<IScrollTickerWebPartProps> {
private dropdownOptions: IPropertyPaneDropdownOption[];
private listsFetched: boolean;
private fetchLists(url: string) : Promise<any> {
return this.context.spHttpClient.get(url, SPHttpClient.configurations.v1).then((response: SPHttpClientResponse) => {
if (response.ok) {
return response.json();
} else {
console.log("WARNING - failed to hit URL " + url + ". Error = " + response.statusText);
return null;
}
});
}
private fetchOptions(): Promise<IPropertyPaneDropdownOption[]> {
var url = "https://abc.sharepoint.com/teams/SharepointPOC" + "/_api/web/lists?$filter=Hidden eq false";
return this.fetchLists(url).then((response) => {
var options: Array<IPropertyPaneDropdownOption> = new Array<IPropertyPaneDropdownOption>();
response.value.map((list: IODataList) => {
console.log("Found list with title = " + list.Title);
options.push( { key: list.Id, text: list.Title });
});
return options;
});
}
Wherever you call fetchOptions, make sure to call this.context.propertyPane.refresh() after the promise resolves. This is needed to force a re-render of the property pane with the new dropdownOptions.
As an example (somewhere other than onPropertyPaneConfigurationStart is fine as well):
protected onPropertyPaneConfigurationStart(): void {
this.fetchOptions().then(options => {
this.dropdownOptions = options;
this.context.propertyPane.refresh();
});
}
This is assuming that your PropertyPaneDropdown is setup something like below, where this.dropdownOptions are initially undefined, and you are wanting to asynchronously load them with fetchOptions():
PropertyPaneDropdown('someProperty', {
// ...
options: this.dropdownOptions,
// ...
})
Web part properties – dynamically populate Dropdown options in SPFX
we populate the dropdown with the SharePoint lists in the current site. We do this with an async REST call to SharePoint
/* need some imports e.g.:
import { IODataList } from '#microsoft/sp-odata-types';
import { SPHttpClient, SPHttpClientConfigurations,
SPHttpClientConfiguration, SPHttpClientResponse, ODataVersion,
ISPHttpClientConfiguration } from '#microsoft/sp-http';
*/
private dropdownOptions: IPropertyPaneDropdownOption[];
private listsFetched: boolean;
// these methods are split out to go step-by-step, but you could refactor
and be more direct if you choose..
private fetchLists(url: string) : Promise<any> {
return this.context.spHttpClient.get(url,
SPHttpClient.configurations.v1).then((response: SPHttpClientResponse) => {
if (response.ok) {
return response.json();
} else {
console.log("WARNING - failed to hit URL " + url + ". Error = " +
response.statusText);
return null;
}
});
}
private fetchOptions(): Promise<IPropertyPaneDropdownOption[]> {
var url = this.context.pageContext.web.absoluteUrl + `/_api/web/lists?
$filter=Hidden eq false`;
return this.fetchLists(url).then((response) => {
var options: Array<IPropertyPaneDropdownOption> = new
Array<IPropertyPaneDropdownOption>();
response.value.map((list: IODataList) => {
console.log("Found list with title = " + list.Title);
options.push( { key: list.Id, text: list.Title });
});
return options;
});
}
Then in the getPropertyPaneConfiguration method, we kick-off the call to fetch the data at the beginning, and then in the control declaration we simply set the options property to our variable holding the array:
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
if (!this.listsFetched) {
this.fetchOptions().then((response) => {
this.dropdownOptions = response;
this.listsFetched = true;
// now refresh the property pane, now that the promise has been
resolved..
this.onDispose();
});
}
return {
pages: [
{
header: {
description: "Basic settings"
},
groups: [
{
groupName: "COB dropdown field (PropertyPaneDropdown)",
groupFields: [
PropertyPaneDropdown('dropdownProperty', {
label: 'This is the label',
options: this.dropdownOptions
})
]
}
]
}
]
}
}
Refer this Web part properties – dynamically populate Dropdown
You can use PropertyFieldListPicker control which is really easy to use.
This control generates a list picker field that can be used in the property pane of your SharePoint Framework web parts.
The control can be configured as a single or multi-selection list picker. Please check the below link :
https://sharepoint.github.io/sp-dev-fx-property-controls/controls/PropertyFieldListPicker/
You can use PNP PropertyFieldListPicker,
https://pnp.github.io/sp-dev-fx-property-controls/controls/PropertyFieldListPicker/

Ckeditor plugin : how to unwrap text?

I have created a ckeditor plugin that wraps the selected text into a span.
I wonder how can I unwrap the selected when I apply this plugin on a text that has been previously wrapped into the span.
CKEDITOR.plugins.add('important', {
// Register the icons. They must match command names.
//trick to get a 16*16 icon : http://www.favicomatic.com
icons: 'important',
init: function (editor) {
editor.addCommand('important', {
// Define the function that will be fired when the command is executed.
exec: function (editor) {
var selected_text = editor.getSelection().getSelectedText();
console.log(editor.getSelection()) ;
var newElement = new CKEDITOR.dom.element("span");
newElement.setAttributes({class: 'important'});
newElement.setText(selected_text);
editor.insertElement(newElement);
//how to unwrap the selected text ?
});
// Create the toolbar button that executes the above command.
editor.ui.addButton('important', {
label: 'Set this as important',
command: 'important',
toolbar: 'insert'
});
}
});
Finally, using editor.getSelection().getStartElement(), I can check if the starting element has already been wrapped with the class and remove it if necessary.
CKEDITOR.plugins.add('important', {
//trick to get a 16*16 icon : http://www.favicomatic.com
icons: 'important',
init: function (editor) {
var className = 'important';
editor.addCommand('important', {
// Define the function that will be fired when the command is executed.
exec: function (editor) {
var editorSelection = editor.getSelection();
var selected_text = editorSelection.getSelectedText();
var startElement = editorSelection.getStartElement();
//if the element has already been wrapped, let's UNwrap it
if (className === startElement.$.className) {
var html = startElement.$.innerHTML;
editor.getSelection().getStartElement().remove();
editor.insertHtml(html);
} else {
//if the element has NOT already been wrapped, let's wrap it
var newElement = new CKEDITOR.dom.element("span");
newElement.setAttributes({class: 'important'});
newElement.setText(selected_text);
editor.insertElement(newElement);
}
}
});
// Create the toolbar button that executes the above command.
editor.ui.addButton('important', {
label: 'Set this as important',
command: 'important',
toolbar: 'insert'
});
}
});

How to trigger autocomplete on character - Ace Editor

How can I do the following with the Ace Editor.
User types the '#' character
Autocomplete pops up
User makes a selection from the dropdown
The '#' gets removed now that the selection has been made
I basically want the # as a trigger for the autocomplete, but I don't want it hanging around after.
Thank you
addAutoComplete() {
var me = this;
ace.require('./config').loadModule('ace/ext/language_tools', () => {
this.aceEditor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: false
});
me.include = /[a-z.]/i;
this.aceEditor.on('change', (obj, editor) => {
switch (obj.action) {
case 'insert':
let lines = obj.lines;
let char = lines[0];
if ((lines.length === 1) && (char.length === 1) && me.include.test(char)) {
setTimeout(() => {
me.aceEditor.commands.byName.startAutocomplete.exec(me.aceEditor);
}, 50);
}
break;
}
});
});
}
that's the demo. works fine
We can bind the '#' keyword and trigger the autocomplete:
editor.commands.addCommand({
name: "myCommand",
bindKey: { win: "#", mac: "#" },
exec: function (editor) {
autocomplete();
}
});
autocomplete: function () {
staticWordCompleter = {
var getWordList = function(editor, session, pos, prefix, callback, isRHSEditor) {
var wordList = []; // add your words to this list
callback(null, wordList.map(function(word) {
return {
caption: word,
value: word
};
}));
editor.completers = [staticWordCompleter];
}
None of the above approaches worked for me. I ended up rolling my own autocomplete/autosuggest for this to work. It's hard to contrive an example but in short the steps are:
Capture the onChange of the editor
If the editor action meets the criteria (i.e. the # symbol is pressed), display a box at the cursor position. This can be done by setting the box to position absolute, and setting the top/left attributes:
const {row, column} = window.editor.getCursorPosition();
const {pageX, pageY} = window.editor.renderer.textToScreenCoordinates(row, column)
const autosuggest = document.getElementById("ELEMENT_NAME")
autosuggest.style.left = pageX
autosuggest.style.top = pageY
Add commands to disable/redirect any actions such as the arrow keys/enter key, and re-enable when a selection is made.
function disableEnterKeyInEditor() {
editor.commands.addCommand(commmand_enter);
}
function enableEnterKeyInEditor() {
editor.commands.removeCommands(commmand_enter);
}
command_enter = {
name: "enterKeyPressedCommand",
bindKey: {win: "Enter", mac: "Enter"},
exec: function (editor) {
return true;
}
};
This was much easier than working with ace's autocomplete.
You can check with below code:
var getWordList = function(editor, session, pos, prefix, callback, isRHSEditor) {
var wordList = [];
if(prefix === '#') {
wordList.push('add you're name list here');
}
callback(null, wordList.map(function(word) {
return {
caption: word,
value: word
};
}));
}

Change switch position with draggable/droppable and save the new position in db

Got a nice solution for my project on stack but I test now some days for a solution to save data after switch in db.
The original post: change switch position behavior
$(function()
{
$(".swapable").
draggable({ revert: true }).
droppable(
{
drop:function(event,ui)
{
swapNodes($(this).get(0),$(ui.draggable).get(0));
}
});
});
function swapNodes(a, b)
{
var aparent= a.parentNode;
var asibling= a.nextSibling===b? a : a.nextSibling;
b.parentNode.insertBefore(a, b);
aparent.insertBefore(b, asibling);
}
http://jsfiddle.net/keGuN/1/
Now I want use the stop to save something after drop.
$(function() {
$(".swapable").
draggable(
{
revert: true,
stop:function()
{
// put new div combination in db
}
}).
droppable(
{
drop:function(event,ui)
{
swapNodes($(this).get(0),$(ui.draggable).get(0));
}
});
});
function swapNodes(a, b)
{
var aparent= a.parentNode;
var asibling= a.nextSibling===b? a : a.nextSibling;
b.parentNode.insertBefore(a, b);
aparent.insertBefore(b, asibling);
}
How to find a way to put new div combination put in database?
My problem is how to get the right way to show new div combination.

Resources