Code migration from tinymce 4 to tinymce 5 - problem with action function (true / false) - tinymce

I have a problem with migrating the plugin from tinymce 4 to tinymka 5. The console tells me "Uncaught (in promise) TypeError: btn.active is not a function"
I can not find an equivalent for tinymce 5. Can someone replace it?
Code below:
tinymce.PluginManager.add('phonelink', function(editor, url) {
// Add a button that opens a window
var linkText = "";
var linkTitle = "";
var link = "";
// tinymce.DOM.loadCSS(url + '/css/phonelink.css');
editor.ui.registry.addButton('phonelink2', {
text: 'asddas',
icon: 'image-options',
onSetup: updateOnSelect,
onAction: onClickPhoneButton
});
// Adds a menu item to the tools menu
editor.ui.registry.addMenuItem('phonelink', {
text: 'asddas',
icon: 'image-options',
context: 'tools',
onAction: onClickPhoneButton,
onSetup: updateOnSelect
});
function onClickPhoneButton(){
editor.windowManager.open({
title: '123213123',
body: {
type: 'panel',
items: [
{type: 'input', name: 'phone', label: 'Teléfono', value: link},
{type: 'input', name: 'showtext', label: 'Texto a mostrar', value: linkText},
{type: 'input', name: 'title', label: 'Título', value: linkTitle}
]
},
buttons: [
{
text: 'Close',
type: 'cancel',
onclick: 'close'
},
{
type: 'submit',
name: 'submitButton',
text: 'Stwórz',
primary: true
}
],
onAction: function(e) {
alert('Toggle menu item clicked');
},
onSubmit: function(e) {
var data = e.getData();
var hrefLink = '<a title="' + data .title + '" href="tel:+34' + data .phone + '">' + data .showtext + '</a>';
if(link !== ''){
editor.setContent(hrefLink);
}else{
editor.insertContent(hrefLink);
}
e.close();
}
});
}
function updateOnSelect() {
var btn = this;
const editorEventCallback = function (e) {
var node = editor.selection.getNode();
var isTelLink = node.href !== undefined && node.href.indexOf('tel:+') !== -1
btn.active(isTelLink);
if(isTelLink){
link = node.href;
link = link.replace("tel:+34", "");
linkTitle = node.title;
linkText = node.text;
}
};
editor.on('NodeChange', editorEventCallback);
return function (btn) {
editor.off('NodeChange', editorEventCallback);
}
}
});
I searched the documentation for a replacement, but found nothing.

TinyMCE 5 no longer passes the button and menu instance via this. Instead it passes an API instance as the first parameter, so you'll want to change your updateOnSelect function to something like this:
function updateOnSelect(api) {
const editorEventCallback = function (e) {
var node = editor.selection.getNode();
var isTelLink = node.href !== undefined && node.href.indexOf('tel:+') !== -1
api.setActive(isTelLink);
if(isTelLink){
link = node.href;
link = link.replace("tel:+34", "");
linkTitle = node.title;
linkText = node.text;
}
};
editor.on('NodeChange', editorEventCallback);
return function (btn) {
editor.off('NodeChange', editorEventCallback);
}
}
You'll note var btn = this has been removed and that the API to set an item as active is setActive instead of active. This can be found in the documentation here: https://www.tiny.cloud/docs/ui-components/typesoftoolbarbuttons/#togglebutton and https://www.tiny.cloud/docs/ui-components/menuitems/#togglemenuitems (see the API section in both links).
In the above, you may have noticed both reference "Toggle" items. That's another change in TinyMCE 5, as different types of buttons/menu items have a separate registration API. So you'll also need to swap to using editor.ui.registry.addToggleButton and editor.ui.registry.addToggleMenuItem. More details about that can be found here if needed: https://www.tiny.cloud/docs/migration-from-4x/#customtoolbarbuttons
Here's an example fiddle showing the changes mentioned above: https://fiddle.tiny.cloud/B5haab.
Hopefully that helps!

Related

Popup in WFS layer Openlayers

Good Morning.
To work with wfs layer is it better to use leaflet or openlayers?
I have a code with openlayers that returns WFS from the geoserver. But I'm not able to show the attributes in popup. can anybody help me?
Thanks
You can try ol-ext ol/Overlay/PopupFeature to display feature attributes in a popup.
See example: https://viglino.github.io/ol-ext/examples/popup/map.popup.feature.html
Following the example of https://viglino.github.io/ol-ext/examples/popup/map.popup.feature.html, I have this code where my WFS layer contains the id and name attributes, however, it doesn't show anything in the popup
var vectorSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
return 'http://localhost:8080/geoserver/teste/wfs?service=WFS&' +
version=1.1.0&request=GetFeature&typename=teste:MYLAYER&' +
'outputFormat=application/json&srsname=EPSG:4326&' +
'bbox=' + extent.join(',') + ',EPSG:4326';
},
strategy: ol.loadingstrategy.bbox
});
var vector = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(0, 0, 255, 1.0)',
width: 2
})
})
});
var layers = [
new ol.layer.Tile({source: new ol.source.OSM()}),
vector,
];
var map = new ol.Map({
layers: layers,
interactions: ol.interaction.defaults({ altShiftDragRotate:false, pinchRotate:false }),
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([-46.444137, -23.713596]),
zoom: 12
})
});
var select = new ol.interaction.Select({
hitTolerance: 5,
multi: true,
condition: ol.events.condition.singleClick
});
map.addInteraction(select);
var popup = new ol.Overlay.PopupFeature({
popupClass: 'default anim',
select: select,
canFix: true,
template: {
title:
function(f) {
return f.get('nome')+' ('+f.get('id')+')';
},
attributes: // [ 'id', 'nome' ]
{
'nome': { title: 'Nome' },
'id': { title: 'Id' },
}
}
});
map.addOverlay (popup);
This is the popup code. I have 3 layers: layer1, layer2 and layer3.
For layer1, ID I want to show as ID. For layer2, I want to show ID as CODE and for other layers I don't want to show ID attribute.
How should I change the template? Thanks
var popup = new ol.Overlay.PopupFeature({
popupClass: 'default anim',
select: select_interaction,
canFix: true,
template: {
title:
function(f) {
return f.get('NAME')+' ('+f.get('ID')+')';
},
attributes:
{
'ID': { title: 'ID' },
// with prefix and suffix
'POP': {
title: 'População', // attribute's title
before: '', // something to add before
format: ol.Overlay.PopupFeature.localString(), // format as local string
after: ' hab.' // something to add after
},
}
}
});
#user12538529
You have to create a function and return the template for each case:
// Create templates
var templateID = { ... };
var templateCODE = { ... };
// Popup with a template function
var popup = new ol.Overlay.PopupFeature({
popupClass: 'default anim',
select: select_interaction,
canFix: true,
template: function(feature) {
var prop = feature.getProperties();
// Test if has property ID
if (prop.hasOwnProperty('ID')) return templateID;
// or property CODE
else if (prop.hasOwnProperty('CODE')) return templateCODE;
}
});

Rendering a menu in vue 3 after ajax method

I've gotten this menu to work without filtering it, but now I'm doing an ajax request to filter out menu items the user isn't supposed to see, and I'm having some trouble to figure out how to set the resulting menu data, the line that is not working is commented below:
<script>
import { ref } from 'vue';
import axios from 'axios';
var currentSelected = 'device_access';
var menuData = [
{
text: 'Device Access',
id: 'device_access',
children: [
{
text: 'Interactive',
link: '/connection_center'
},{
text: 'Reservation',
link: '/reserve_probe'
}, {
text: 'Reservation Vue',
link: '/reservation.html'
}
]
}, {
text: 'Automation',
id: 'automation',
show: ['is_mxadmin', 'can_schedule_scripts'],
children: [
{
text: 'Builder',
link: '/builder',
},{
text: 'Execution Results',
link: '/test_suite_execution_results'
},
]
}
];
function hasMatch(props, list) {
var match = false;
for (var i=0; i < list.length && !match; i++) {
match = props[list[i]];
}
return match;
}
export default {
name: 'Header',
setup() {
const cursorPosition = ref('0px');
const cursorWidth = ref('0px');
const cursorVisible = ref('visible');
//the menu is zero length until I get the data:
const menu = ref([]);
return {
menu,
cursorPosition,
cursorWidth,
cursorVisible
}
},
created() {
let that = this;
axios.get('navigation_props')
.then(function(res) {
var data = res.data;
var result = [];
menuData.forEach(function(item) {
if (!item.show || hasMatch(data, item.show)) {
var children = [];
item.children.forEach(function (child) {
if (!child.show || hasMatch(data, child.show)) {
children.push({ text: child.text, link: child.link });
}
});
if (children.length > 0) {
result.push({ text: item.text,
children: children, lengthClass: "length_" + children.length });
}
}
});
//continues after comment
this is probably the only thing wrong, I've run this in the debugger and I'm getting the
correct data:
that.$refs.menu = result;
since the menu is not being rebuilt, then this fails:
//this.restoreCursor();
})
.catch(error => {
console.log(error)
// Manage errors if found any
});
},
this.$refs is for template refs, which are not the same as the refs from setup().
And the data fetching in created() should probably be moved to onMounted() in setup(), where the axios.get() callback sets menu.value with the results:
import { onMounted, ref } from 'vue'
export default {
setup() {
const menu = ref([])
onMounted(() => {
axios.get(/*...*/).then(res => {
const results = /* massage res.data */
menu.value = results
})
})
return {
menu
}
}
}
I finally figured out the problem.
This code above will probably work with:
that.menu = result;
You don't need: that.$refs.menu
You can't do it in setup because for some reason "that" is not yet defined.
In my working code I added a new method:
methods: {
setMenuData: function() {
this.menu = filterMenu();
},
}
And "this" is properly defined inside them.

why is the code crashing when using jeditable?

The code crashes when html tags are entered as input when making fields editable by using jeditable.
It opens my custom error page in the text area itself with the error message "A potentially dangerous Request.Form value was detected from the client "
When user tries to normally save new information the call goes to EditData method at Controller but when user enters html tag and tries to save the code crashes and call does not go to EditData at Controller
$('.editArea').editable('../Data/EditData', {
cssclass: 'jeditForm',
tooltip: 'click to edit',
width: '100%',
height: '150',
type: 'textarea',
title: '',
placeholder: 'click to edit',
submit: 'save',
onsubmit: function (settings, original) {
oldValue = original.revert;
},
submitdata: function (value) {
return {
id: $(this).data('id'),
propertyName: $(this).data('propertyname')
}
},
callback: function (value, settings) {
var jsonData = $.parseJSON(value);
if (jsonData.status) {
this.innerText = jsonData.value;
}
else {
alert("not updated");
this.innerText = oldValue;// + "\n" + jsonData.msg;
}
}
});

is it possible to change button's text with $ionicPopup.confirm()?

I'm using $ionicPopup.confirm() but I would like to change "cancel's button" text. Is it possible to do so ?
I'm aware of .show() syntax:
buttons: [
{ text: 'Cancel' }
]
But it does not seem to work with .confirm() ...
Thank 4 the help
At least in the latest release of Ionic (1.0.0) you can do the following:
var confirmPopup = $ionicPopup.confirm({
title: 'Popup title',
template: 'Popup text',
cancelText: 'Custom cancel',
okText: 'Custom ok'
}).then(function(res) {
if (res) {
console.log('confirmed');
}
});
Here is the relative documentation.
UPDATE : on ionic 1.0.0, this is now possible, check here
showConfirm Options :
{
title: '', // String. The title of the popup.
cssClass: '', // String, The custom CSS class name
subTitle: '', // String (optional). The sub-title of the popup.
template: '', // String (optional). The html template to place in the popup body.
templateUrl: '', // String (optional). The URL of an html template to place in the popup body.
cancelText: '', // String (default: 'Cancel'). The text of the Cancel button.
cancelType: '', // String (default: 'button-default'). The type of the Cancel button.
okText: '', // String (default: 'OK'). The text of the OK button.
okType: '', // String (default: 'button-positive'). The type of the OK button.
}
Yes you can do wathever you want, using ionic popup.show and bind the Cancel event.
$ionicPopup.show({
template: msg,
title: titleConfirm,
buttons: [
{ text: "BTN_NO",
onTap:function(e){
return false;
}
},
{ text: "BTN_OK",
onTap:function(e){
return true;
}
},
]
});
After investigation on the ionic popover.confirm function this is
not possible to customize it. The value of popover.confirm are hardcoded line 446
function showConfirm(opts) {
return showPopup(extend({
buttons: [{
text: opts.cancelText || 'Cancel',
type: opts.cancelType || 'button-default',
onTap: function() { return false; }
}, {
text: opts.okText || 'OK',
type: opts.okType || 'button-positive',
onTap: function() { return true; }
}]
}, opts || {}));
}
It's possible to do, you have to use the "type" thing inside the button
buttons: [
{ text: 'Cancel' },
{
text: '<b>Save</b>',
type: 'button-assertive',
onTap: function(e) {
$scope.request_form.abc = "accepted";
}
}
]
in the type part you have to give the class name , and you can change the color of the button.

Extjs 4.0 MVC Add components to a form based on Store

I am ashamed to say I have spent most of today on this. I am trying to build a form based on the contents of an data store. I am using Ext.js and the MVC architecture. Here's what I have:
var myitems = Ext.create('Ext.data.Store', {
fields: ['name', 'prompt', 'type'],
data :
[
{"name":"name", "prompt":"Your name" , "type":"textfield"},
{"name":"addr", "prompt":"Your street address", "type":"textfield"},
{"name":"city", "prompt":"Your city" , "type":"textfield"}
]
});
function genwidget(name, prompt, type)
{
console.log("In genwidget with name=" + name + ", prompt=" + prompt + ", type=" + type + ".");
var widget = null;
if (type == "textfield")
{
// widget = Ext.create('Ext.form.field.Text',
widget = Ext.create('Ext.form.TextField',
{
xtype : 'textfield',
name : name,
fieldLabel: prompt,
labelWidth: 150,
width : 400, // includes labelWidth
allowBlank: false
});
}
else
{
// will code others later
console.log("Unrecongized type [" + type + '] in function mywidget');
}
return widget;
};
function genItems(myitems)
{
console.log("Begin genItems.");
var items = new Ext.util.MixedCollection();
var howMany = myitems.count();
console.log("There are " + howMany + " items.");
for (var i = 0; i < myitems.count(); i++)
{
var name = myitems.getAt(i).get('name');
var prompt = myitems.getAt(i).get('prompt');
var type = myitems.getAt(i).get('type');
var widget = genwidget(name, prompt, type) ;
items.add(widget);
console.log("items.toString(): " + items.toString());
}
return items;
};
Ext.define('MyApp.view.dynamicform.Form' ,{
extend: 'Ext.form.Panel',
alias : 'widget.dynamicformform',
// no store
title: 'Dynamic Form',
id: 'dynamicform.Form',
bodyPadding: 5,
autoScroll: true,
layout: 'auto',
defaults:
{
anchor: '100%'
},
dockedItems: [ ],
items: genItems(myitems),
// Reset and Submit buttons
buttons: [
{
text: 'Reset',
handler: function()
{
this.up('form').getForm().reset();
console.log('Reset not coded yet');
}
},
{
text: 'Submit',
formBind: true, //only enabled once the form is valid
disabled: true,
handler: function()
{
var form = this.up('form').getForm();
if (form.isValid())
{
form.submit({
success: function(form, action)
{
console.log('Success not coded yet');
}
});
}
}
} // end submit
], // end buttons
initComponent: function()
{
console.log("--> in dynamicform init");
this.callParent(arguments);
console.log("--> leaving dynamicform init");
}
}); // Ext.define
The error I am getting (I've had many throughout the day) is "my.items.push is not a function".
Thanks in advance for any help you can offer!
items is expected to be an array not MixedCollection. It is changed to MixedCollection later on if I remember good. So to fix your issue change:
var items = new Ext.util.MixedCollection();
// ...
items.add(widget);
to
var items = [];
// ...
items.push(widget);
Consider as well defining items of form as an empty array and then in initComponent make use of Ext.apply:
var me = this,
items = genItems(myitems);
Ext.apply(me, {
items:items
});