I'm working on a plugin for TinyMCE editor. The idea is very simple, basically the user can insert a product link from a dropdown selecter where a custom class and a link to the page of the product are automatically added.
I get data from an array like this one:
function products_list() {
return array(
array('product-tag-1' => 'Product 1', 'https://website.com/product1-page'),
array('product-tag-3' => 'Product 2', 'https://website.com/product2-page'),
array('product-tag-3' => 'Product 2', 'https://website.com/product3-page'),
);
}
and here is the plugin code:
(function() {
var _products_list = [];
for(var i = 0; i < products_list.length; i++){
var product = _products_list[i];
_products_list.push({ product: Object.values(product)[1], url: Object.values(product)[0], tag: Object.keys(product)[1]});
console.info(_products_list);
}
tinymce.PluginManager.add('product_link', function( editor, url ) {
editor.addButton( 'product_link', {
text: 'Product Link',
icon: false,
onclick: function() {
editor.windowManager.open( {
title: 'Select a Product',
body: [{
type: 'listbox',
name: 'productSelect',
values: _products_list,
onPostRender: function( ){
productSelect = this;
}
},
{type: 'textbox', name: 'linkText', label: 'anchor text'}
],
onsubmit: function( e ) {
link = editor.insertContent('' + e.data.linkText + '');
}
});
}
});
});
})();
But when I select something it returns this error in console : 'Uncaught Typerror: productSelect.url is not a function'.
Any hint?
Tried to debug code but nothing worked.
Related
I'm trying to develop a custom TinyMCE plugin which will load the items for a selectbox list based on the options of another selectbox list. However, I cannot figure out how to detect any even on the selectbox list.
The documentation is almost entirely useless, as it provides no mention of custom plugin options - only the boilerplate code to start off.
How can I detect an onchange event when the select lists's selection is altered?
tinymce.PluginManager.add('custom', function(editor, url) {
var openDialog = function () {
return editor.windowManager.open({
title: 'Custom',
body: {
type: 'panel',
items: [
{
type: 'selectbox',
name: 'options',
label: 'Options',
items: [
{text: 'Primary', value: 'primay style'},
{text: 'Success', value: 'success style'},
{text: 'Error', value: 'error style'}
],
onchange: function() {
alert('hi');
},
flex: true,
}, {
type: 'selectbox',
name: 'selection',
label: 'Selection',
items: [
],
flex:true,
}
]
},
buttons: [
{
type: 'cancel',
text: 'Close'
},
{
type: 'submit',
text: 'Save',
primary: true
},
],
onSubmit: function (api) {
var data = api.getData();
/* Insert content when the window form is submitted */
editor.insertContent(data);
api.close();
}
});
};
/* Add a button that opens a window */
editor.ui.registry.addButton('custom', {
text: 'Custom',
onAction: function () {
/* Open window */
openDialog();
}
});
/* Adds a menu item, which can then be included in any menu via the menu/menubar configuration
*/
editor.ui.registry.addMenuItem('custom', {
text: 'Custom',
onAction: function() {
/* Open window */
openDialog();
}
});
/* Return the metadata for the help plugin */
return {
getMetadata: function () {
return {
name: 'Example plugin',
url: 'http://exampleplugindocsurl.com'
};
}
};
});
I am not a Web developer, I have to do just a small task once, but I hate copy & paste.
Look at the code below, I'd like to avoid copy and paste (question1, question2 ,..., question[i]). I'd like to create a for statement but I should handle properties with a dynamic name. In c# I would use reflection or dynamic.
Is it possible in Javascript? Is it the correct approach? Should I dynamically generate the code and use Eval()?
tinymce.PluginManager.add('test_containers', function(editor, url) {
editor.addButton('test_containers2', {
title: 'Container 2',
text: 'Container 2',
onclick: function() {
editor.windowManager.open({
title: 'Test Container',
body: [{
type: 'container',
layout: 'stack',
columns: 2,
minWidth: 500,
minHeight: 500,
items: [{
type: 'textbox',
name: 'question1'
}, {
type: 'textbox',
name: 'question2'
}, ]
}],
onsubmit: function(e) {
ed.insertContent(e.data.question1 + e.data.question2);
}
});
}
});
});
tinymce.init({
selector: '#mytextarea',
plugins: 'colorpicker test_containers',
toolbar: 'test_containers2'
});
// Taken from core plugins
var editor = tinymce.activeEditor;
function createColorPickAction() {
var colorPickerCallback = editor.settings.color_picker_callback;
if (colorPickerCallback) {
return function() {
var self = this;
colorPickerCallback.call(
editor,
function(value) {
self.value(value).fire('change');
},
self.value()
);
};
}
}
<script src="https://cdn.tinymce.com/4/tinymce.min.js"></script>
<textarea id="mytextarea">Hello, World!</textarea>
See: https://jsfiddle.net/Revious/gm2phuva/3/
From my understanding, you need to add the items dynamically.
I have added two function on your code.
createArr -> will create the array of list of the specified number (n)
handleQuesData -> will concat the data of all the questions and pass it to onsubmit function
tinymce.PluginManager.add('test_containers', function(editor, url) {
// item creation dynamically
let createArr = (n) => {
let arr = []
for (let i = 0; i < n; i++) {
arr.push({
type: 'textbox',
name: `question{i+1}`
})
}
return arr;
}
// onsubmit handled dynamically
let handleQuesData = (data, n) => {
let quesdata = ''
for (let i = 0; i < n; i++) {
quesdata += data[`question{i+1}`]
}
return quesdata
}
let numItem = 2;
editor.addButton('test_containers2', {
title: 'Container 2',
text: 'Container 2',
onclick: function() {
editor.windowManager.open({
title: 'Test Container',
body: [{
type: 'container',
layout: 'stack',
columns: 2,
minWidth: 500,
minHeight: 500,
items: createArr(numItem)
}],
onsubmit: function(e) {
ed.insertContent(handleQuesData(e.data, numItem));
}
});
}
});
});
tinymce.init({
selector: '#mytextarea',
plugins: 'colorpicker test_containers',
toolbar: 'test_containers2'
});
// Taken from core plugins
var editor = tinymce.activeEditor;
function createColorPickAction() {
var colorPickerCallback = editor.settings.color_picker_callback;
if (colorPickerCallback) {
return function() {
var self = this;
colorPickerCallback.call(
editor,
function(value) {
self.value(value).fire('change');
},
self.value()
);
};
}
}
Here is the demo code : JSFiddle
Hope it helps :)
Yes, you can dynamically generate the list of items.
tinymce.PluginManager.add('test_containers', function(editor, url) {
const totalQuestions = 10;
let questions = [];
for (let i = 1; i < totalQuestions; i++) {
questions.push({
type: 'textbox',
name: 'question' + i
});
}
editor.addButton('test_containers2', {
title: 'Container 2',
text: 'Container 2',
onclick: function() {
editor.windowManager.open({
title: 'Test Container',
body: [{
type: 'container',
layout: 'stack',
columns: 2,
minWidth: 500,
minHeight: 500,
items: questions
}],
onsubmit: function(e) {
ed.insertContent(e.data.question1 + e.data.question2);
}
});
}});
});
//......
I have some store, which is formed data. On panel it looks how "fieldName" and text field (in depension from invoked form). For example, on one form is displayed "name document" and field, on another: date of selling and date field. Data is formed dynamicly
Here is store:
tableTempStore = new Ext.data.JsonStore({
url: objectUrlAddress,
baseParams: {
'objectID': objectID
},
root: 'Fields',
fields: [{
name: 'Type',
type: 'int'
}, {
name: 'Value'
}, {
name: 'IsRequired',
type: 'bool'
}, {
name: 'Identifier'
}, {
name: 'Data'
}],
listeners: {
load: function(obj, records) {
Ext.each(records, function(rec) {
var item = null;
switch (rec.get('Type')) {
case 0:
item = new Ext.form.NumberField();
item.id = rec.get('Identifier');
item.fieldLabel = rec.get('Hint');
var isRequired = rec.get('IsRequired');
item.anchor = '100%';
item.allowBlank = !isRequired;
item.disabled = editDisabled;
item.value = rec.get('Data');
break;
case 1:
item = new Ext.form.NumberField();
item.id = rec.get('Identifier');
item.fieldLabel = rec.get('Hint');
var isRequired = rec.get('IsRequired');
item.anchor = '100%';
item.allowBlank = !isRequired;
item.allowDecimals = true;
item.disabled = editDisabled;
item.value = rec.get('Data');
break;
}
if (item != null) {
grid.add(item);
tableValue = Ext.getCmp('propGrid').doLayout();
source[item.fieldLabel] = tableValue;
//grid.doLayout();
}
});
grid.setSource(source);
}
}
});
This code had worked in a form, but I need to use Grid (or Editor Grid). I know, how displayed field name ("document name" and etc.), but I don't understand, how displayed text field or etc. For form I had used doLayout. How can I do this?
Here is Grid:
var templateGrids = new Ext.grid.EditorGridPanel({
id: 'tableId',
height:300,
width: '100%',
clicksToEdit:1,
frame: true,
store: tableTempStore,
columns: [
{header: 'Value' dataIndex: typeValue},
{header: 'Name' dataIndex: ''}]
})
Please, help me! Thanks for answers in advance!
I need to update a variable on submit inside tinymce window.
Here the tinymce code:
tinymce.PluginManager.add('tc_button',function(editor,url){
editor.addButton('tc_button',{
title: 'Images',
onclick: function(){
editor.windowManager.open({
title: 'Images',
buttons: [{text: 'Add Shortcode', onclick: 'submit'}, {text: 'Cancel', onclick: 'close'}],
body: [
{type: 'container',
label : 'Image URL',
items: [
{type: 'textbox', id: 'image1', name : 'image1', style:'width:270px'},
{type: 'listbox', id: 'effect1', name: 'effect1', style:'margin-left:10px'},
]}
],
onsubmit: function(e) {
jQuery.post(ajax_url,
{
action: 'save_image',
image: imageData,
}
),
function ( data ){
var jsonData = tryParseJSON( data );
if ( jsonData !== false ) {
var new_url = jsonData.attachment_url;
jQuery('#image1').attr('src', new_url);
}
};
editor.insertContent('[shortcode image1="' + e.data.image1 + '"]' );
}
});
}
});
});
I need to run jQuery('#image1').attr('src', new_url) inside ajax call before editor.insertContent is added inside editor. How can i set it so to wait ajax call is ended and #image1 source is updated with ajax result value?
Thanks in advance.
You need to call editor.insertContent('[shortcode image1="' + e.data.image1 + '"]' ); inside call back function after jQuery('#image1').attr('src', new_url);
tinymce.PluginManager.add('tc_button', function(editor, url) {
editor.addButton('tc_button', {
title: 'Images',
onclick: function() {
editor.windowManager.open({
title: 'Images',
buttons: [{
text: 'Add Shortcode',
onclick: 'submit'
}, {
text: 'Cancel',
onclick: 'close'
}],
body: [
{
type: 'container',
label: 'Image URL',
items: [{
type: 'textbox',
id: 'image1',
name: 'image1',
style: 'width:270px'
},
{
type: 'listbox',
id: 'effect1',
name: 'effect1',
style: 'margin-left:10px'
},
]
}
],
onsubmit: function(e) {
jQuery.post(ajax_url, {
action: 'save_image',
image: imageData,
}),
function(data) {
var jsonData = tryParseJSON(data);
if (jsonData !== false) {
var new_url = jsonData.attachment_url;
jQuery('#image1').attr('src', new_url);
}
editor.insertContent('[shortcode image1="' + e.data.image1 + '"]');
};
}
});
}
});
});
I would like to create checkbox in popup window using tinymce. I can create listbox in popup window but cannot create checkbox in it.
var tempGroups = ['Group1', 'Group2', 'Group3', 'Group4'];
var temp = [{
group: 'Group1',
title: 'Title1',
content: '<p>Content1</p>',
}, {
group: 'Group1',
title: 'Title1-1',
content: '<p>Content11</p>',
}, {
group: 'Group2',
title: 'Title2',
content: '<p>Content2</p>'
}, {
group: 'Group2',
title: 'Title2-1',
content: '<p>Content22</p>'
}, {
group: 'Group3',
title: 'Title3-1',
content: '<p>Content33</p>'
}, {
group: 'Group4',
title: 'Title4',
content: '<p>Content4</p>'
}, {
group: 'Group4',
title: 'Title4-1',
content: '<p>Content44</p>'
}];
var tempGroupName;
var menuItems = [];
function createTempMenu(editor) {
for (i = 0; i < tempGroups.length; i++) {
var tempArray = [];
tempArray[i] = [];
tempGroupName = tempGroups[i];
for (j = 0; j < temp.length; j++) {
if (temp[j].group == tempGroupName) {
tempArray[i].push({
text: temp[j].title,
content: temp[j].content,
// type: 'checkbox',
onclick: function () {
alert(this.settings.content);
}
});
}
}
menuItems[i] = {
text: tempGroupName,
menu: tempArray[i],
};
}
return menuItems;
}
tinymce.init({
selector: "textarea",
setup: function (editor) {
editor.addButton('button', {
type: 'menubutton',
text: 'button',
icon: false,
menu: [
{
text: 'Customer List',
onclick: function () {
editor.windowManager.open({
title: 'Customer Name',
width: 200,
height: 100,
items: [
{
type: 'listbox',
value: 0,
label: 'Section: ',
values: createTempMenu(editor),
body: [
{
type: 'checkbox',
label: 'Section: ',
// text: "new",
values: createTempMenu(editor),
}],
onsubmit: function (e) {
}
}]
});
}
}]
});
},
toolbar: " button "
});
Any help will be appreciated.
An old question just found it. If you're still looking for an answer you can refer to their reference Here it has further details
There's a type called checkbox in tinymce
{
type : 'checkbox',
name : 'choose the name',
label : 'choose a label',
text : 'the text near the checkbox',
checked : false
},