Load a TinyMCE editor inside a TinyMCE modal in wordpress - javascript

I'm using TinyMCE to open a modal. And inside that modal i would want to add an instance of tinyMCE. I'm opening the modal passing some objects. I followed this guide
editor.windowManager.open(
// Properties of the window.
{
title: "TDSK's Dumb Shortcode Creator", // The title of the dialog window.
file: url + '/tinymce-dialog.html', // The HTML file with the dialog contents.
width: 1000, // The width of the dialog
height: 600, // The height of the dialog
inline: 1 // Whether to use modal dialog instead of separate browser window.
},
// Parameters and arguments we want available to the window.
{
editor: editor, // This is a reference to the current editor. We'll need this to insert the shortcode we create.
jquery: $, // If you want jQuery in the dialog, you must pass it here.
tinymce: tinymce
}
);
In the tinymce-dialog.html
var passed_arguments = top.tinymce.activeEditor.windowManager.getParams();
var $ = passed_arguments.jquery;
var jq_context = document.getElementsByTagName("body")[0];
$( function() {
passed_arguments.tinymce.execCommand( 'mceAddEditor', false, $( '#sectionContent_1', jq_context )[0] );
} );
This actually creates an instance of TinyMce which is not working though
probably the reason is an error
TypeError: elm is undefined
which points to
aria: function(name, value) {
var self = this, elm = self.getEl(self.ariaTarget);
if (typeof value === "undefined") {
return self._aria[name];
}
self._aria[name] = value;
if (self.state.get('rendered')) {
elm.setAttribute(name == 'role' ? name : 'aria-' + name, value);
}
return self;
},
what could be causing this?

In the end, I had to stop using TinyMce modal and use bootstrap modals.

Related

How to wrap a container div around a Ckeditor table onOk

When a user enters a table on the Ckeditor, I want to wrap a div around it with a class but I can't find a way to get this table HTML element. What is the best way to go about it?
I've tried creating a plugin to extend the table dialog onOk function (see code). This gives me all the properties from the table dialog but I don't want to have to create the whole table element again with all the properties as I don't want to re-write the existing table plugin.
I just need to get the code this plugin adds and wrap it in a div.
I thought about doing it in my projects javascript, when page loads, get all tables and wrap it in a div. However, this doesn't seem like the best way to do it at all. I thought there must be a way via ckeditor?
CKEDITOR.plugins.add( 'responsivetables', {
// The plugin initialization logic
init: function(editor) {
vsAddResponsiveTables(editor);
}
});
function vsAddResponsiveTables(editor){
CKEDITOR.on( 'dialogDefinition', function( ev ) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if ( dialogName == 'table') {
addTableHandler(dialogDefinition, editor);
}
});
}
function addTableHandler(dialogDefinition, editor){
dialogDefinition.onOk = function (a) {
// get table element and wrap in div?
}
}
I found the answer so for anyone else that needs it, this is what I did:
I used the insertElement event instead of when dialog was closed, only doing what I need if its a table that's being added.
// Register the plugin within the editor.
CKEDITOR.plugins.add( 'responsivetables', {
// The plugin initialization logic goes inside this method.
init: function(editor) {
vsAddResponsiveTables(editor);
}
});
function vsAddResponsiveTables(editor){
// React to the insertElement event.
editor.on('insertElement', function(event) {
if (event.data.getName() != 'table') {
return;
}
// Create a new div element to use as a wrapper.
var div = new CKEDITOR.dom.element('div').addClass('table-scroll');
// Append the original element to the new wrapper.
event.data.appendTo(div);
// Replace the original element with the wrapper.
event.data = div;
}, null, null, 1);
}
To the previous answer by 'gemmalouise' need to add one more line of code
CKEDITOR.editorConfig = function( config ) {
config.extraPlugins = 'responsivetables';
}
Otherwise it will not work (I cannot indicate this in the comment, because lack of 50 reputation).
And more compact code of this fuctional:
CKEDITOR.plugins.add('responsivetables', {
init: function (editor) {
editor.on('insertElement', function (event) {
if (event.data.getName() === 'table') {
var div = new CKEDITOR.dom.element('div').addClass('table-scroll'); // Create a new div element to use as a wrapper.
div.append(event.data); // Append the original element to the new wrapper.
event.data = div; // Replace the original element with the wrapper.
}
}, null, null, 1);
}
});

Button dont work after adding a pop up javascript

So I have a button on my HTML code that I have set to hide a certain content. However; when I added a popup feature to my code it makes the button not work.
JS for the popup:
$ = function(id) {
return document.getElementById(id);
}
var show = function(id) {
$(id).style.display ='block';
}
var hide = function(id) {
$(id).style.display ='none';
}
JS for the hide content button:
$(document).ready(function() {
$('#hideshow').click(function() {    
if ($(this).text() == '▼ VIEW CONFIGURATION ▼') {      
$(this).html('▲ HIDE CONFIGURATION ▲')
} else {
$(this).html('▼ VIEW CONFIGURATION ▼');
}
$('#topContainers').slideToggle(400);
});
});
I cant figure out what in the popup JS code is causing the button not to work.
you are using the jquery library which uses the symbol $ and then in your popup.js you are overwriting that symbol and assigning it to a shortcut to the getElementById function, losing the reference to the jquery library.
This:
$ = function(id) { return document.getElementById(id); }
overrides the jQuery method and thus your code using the default $() doesn't work any more.

CKEDITOR: Disable plugin button when text is not highlighted

I have a CKEDITOR plugin that I'm having trouble disabling when there is no selected copy in the editor. Right now, the user can click the button without any highlighted text in the editor. I would like to modify it so that the plugin button is only active when there is copy highlighted in the editor. I've followed the suggestion here, but it isn't working.
Main Plugin Code:
CKEDITOR.plugins.add('cta', {
icons: 'cta',
init: function (editor) {
// Funciton depending on editor selection (taken from the scope) will set the state of our command.
function RefreshState() {
console.log('RefreshState');
var editable = editor.editable(),
// Command that we want to control.
command = editor.getCommand('source'),
range,
commandState;
if (!editable) {
// It might be a case that editable is not yet ready.
console.log("editable not ready yet");
return;
}
// We assume only one range.
range = editable.getDocument().getSelection().getRanges()[0];
console.log(`range: `);
console.log(range);
// The state we're about to set for the command.
commandState = (range && !range.collapsed) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;
console.log('commandState');
console.log(commandState);
command.setState(commandState);
}
// We'll use throttled function calls, because this event can be fired very, very frequently.
var throttledFunction = CKEDITOR.tools.eventsBuffer(250, RefreshState);
// Now this is the event that detects all the selection changes.
editor.on('selectionCheck', throttledFunction.input);
// You'll most likely also want to execute this function as soon as editor is ready.
editor.on('instanceReady', function (evt) {
// Also do state refresh on instanceReady.
RefreshState();
});
editor.addCommand('ctabtn', new CKEDITOR.dialogCommand('ctaDialog'));
editor.ui.addButton('cta', {
label: 'Insert Call to Action button',
command: 'ctabtn',
toolbar: 'insert'
});
CKEDITOR.dialog.add('ctaDialog', this.path + 'dialogs/cta.js');
}
});
My dialog code is here:
CKEDITOR.dialog.add('ctaDialog', function (editor) {
return {
// Basic properties of the dialog window: title, minimum size.
title: 'Call to Action',
minWidth: 400,
minHeight: 200,
// Dialog window content definition.
contents: [{
// Definition of the Basic Settings dialog tab (page).
id: 'tab-basic',
label: 'Basic Settings',
// The tab content.
elements: [{
// Text input field for the Call to Action text.
type: 'text',
id: 'cta',
label: 'Call to Action',
// Validation checking whether the field is not empty.
validate: CKEDITOR.dialog.validate.notEmpty("Call to Action field cannot be empty.")
},
{
// Text input field for the link text.
type: 'text',
id: 'url',
label: 'URL',
// Validation checking whether the field is not empty.
validate: CKEDITOR.dialog.validate.notEmpty("URL field cannot be empty.")
}
]
}],
// method invoked when the dialog button is clicked
onShow: function () {
var element = editor.getSelection();
var link = CKEDITOR.plugins.link;
var _this = this.getParentEditor();
var CTAhref = link.getSelectedLink(_this);
this.setValueOf('tab-basic', 'cta', element.getSelectedText().toString());
if (CTAhref != '' && CTAhref !== null) {
this.setValueOf('tab-basic', 'url', CTAhref.$.href);
}
},
// This method is invoked once a user clicks the OK button, confirming the dialog.
onOk: function () {
var dialog = this;
var CTA = editor.document.createElement('a');
CTA.setAttribute('href', dialog.getValueOf('tab-basic', 'url'));
CTA.setAttribute('class', 'btn btn-special--lg');
CTA.setText(dialog.getValueOf('tab-basic', 'cta'));
editor.insertElement(CTA);
}
};
});
Any ideas on why the plugin icon button on the toolbar doesn't become inactive when there is no copy highlighted in the editor? I can see in the console that CKEDITOR.dom.range.collapsed is toggling between TRUE/FALSE depending upon whether text is highlighted or not. It's just not disabling the button.
As stated, the suggested way of handling this was not working for me. What was working was using range.collapsed in returning a true value if a selection was made in the editor. With that, I turned to using Jquery to handle the rest.
// Hacky. But it gets the job done.
// a.cke_button.cke_button__cta.cke_button_off is the selector for my toolbar button.
// The onclick function listed was pulled from looking at the CKeditor functions
// to initiate my plugins modal.
// The setting of the "onclick" prop to null is needed to override the modal onclick
// binding when there is no selection.
range = editable.getDocument().getSelection().getRanges()[0];
if (range.collapsed === false) {
$('a.cke_button.cke_button__cta.cke_button_off').attr("onclick", 'CKEDITOR.tools.callFunction(83,this);return false;');
$('a.cke_button__cta').toggleClass('cta_button_disabled');
} else {
$('a.cke_button.cke_button__cta.cke_button_off').prop("onclick", null);
}

Ext JS Cannot read property 'getItems' of null

I have an Ext 4.2.1 application with an Ext.form.Panel, and when trying to send the form field values to the server, I need to first determine one of the values to do a switch on. Sorry I can't provide a complete example, but the trouble I have is with this command:
form.getForm().findField('TASK_ID')
In my application if throws:
TypeError: Cannot read property 'getItems' of null
at Ext.define.getFields (ext-all-debug.js:89221)
at Ext.define.findField (ext-all-debug.js:89471)
at Ext.Ajax.request.success
Line 89221 is as follows:
getFields: function() {
return this.monitor.getItems();
},
I'm not sure what monitor is, so I'm a little out of my depth debugging this. Does anyone have any insight as to what might be wrong or what I can check?
When creating form in Ext.window.Window after window.close() I got the same error. Debugging my source code, I found out window handles autoRender again, it actually conflicts at my singleton window effect, as follow code:
getUpdateGroupWindow: function(){
var me = this;
if(me.updateGroupWindow == null){
me.updateGroupWindow = Ext.create('MyApp.view.groupEditWindow');
}
return me.updateGroupWindow;
},
read api: http://extjs-doc-cn.github.io/ext4api/#!/api/Ext.window.Window-cfg-closeAction window closeAction defaults to "destroy", remove the window from the DOM and destroy it and all descendant components. The window will not be available to be re-displayed via the show method, another value 'hide': hide the window by setting visibility to hidden and applying negative offsets. The window will be available to be re-displayed via the show method.
My final code for example:
Ext.define('MyApp.view.groupEditWindow',{
extend:'Ext.window.Window',
title:'修改信息',
width: 400,
closeAction: 'hide', //fix error config
modal: true,
groupForm:null,
getGroupForm:function(){
var me = this;
if(me.groupForm == null){
me.groupForm = Ext.create('MyApp.view.EditGroupForm');
}
return me.groupForm;
},
initComponent: function(){
var me = this;
Ext.applyIf(me, {
items: [me.getGroupForm()],
buttons: [{
text: '取消',
handler: function() {
me.close();
}
}]
});
me.callParent(arguments);
}
});

jQuery UI dialog title task

How would you override jQuery UI's default functionality so that whenever I set a new title for a dialog - it adds xxx in front of it? So $("#any_dialog_id").dialog("option", "title", "yyy") would set title to xxxyyy.
$().ready(function(){
$("#dialog").dialog();
$(".ui-dialog-title").before("xxx");
// I add the line //
$("#any_dialog_id").dialog("option", "title", "yyy");
});
But he show yyyxxx not xxxyyy
What I have to do, to make it work??
Thanks...
There are many ways you could do this.
The very simplest is to run your line $(".ui-dialog-title").before("xxx"); AFTER each call to opening a dialog. You cannot merely run it once and expect it to re-run on later dialog calls.
Another way to do this is to modify the jquery code. But I HIGHLY disrecommend doing that.
If I were to really want to systematically apply a prefix, I would make a helper function or wrapper that do this for me and call it instead of the jquery dialog directly.
Here is an example of what you might do and I have included a jsfiddle link as well (http://jsfiddle.net/stdw6j5q/1/):
HTML:
<div id="idDiv_MyDialog">Hi 1!</div>
<div id="idDiv_MyDialog2">Hi 2!</div>
<div id="idDiv_MyDialog3">Hi 3!</div>
<div id="idDiv_MyDialog4">Hi 4!</div>
JAVASCRIPT:
jDialog = function(options) {
// THE WRAPPER TAKES TWO EXTRA OPTIONS TO IDENTIFY THE DIALOG AND THE TITLE PREFIX TO USE
// I SET A DEFAULT SELECTOR IF NOTHING IS PASSED IN
var _dialog = options && options.dialog ? options.dialog : '#idDiv_MyDialog';
// HERE YOU CAN SET A DEFAULT PREFIX
var _titlePrefix = options && options.titlePrefix ? options.titlePrefix : 'XYZ: ';
// UPDATE THE TITLE OPTION
options.title = _titlePrefix + options.title;
// PASS THROUGH ALL YOUR NORMAL OPTIONS TO THE DIALOG
$(_dialog).dialog(options);
// THIS RETURNS A HANDLE/REFERENCE TO THE DIALOG CREATED
return $(_dialog);
}
$(function() {
// CALL YOUR WRAPPER WHEN YOU NEED TO CREATE/MOD THE DIALOG
$myDialog1 = jDialog({
title: 'Hey Jude',
close: function(event, ui) { $myDialog2.dialog('open'); }
});
$myDialog2 = jDialog({
dialog: '#idDiv_MyDialog2',
title: 'Don\'t let me down',
autoOpen: false,
close: function(event, ui) { $myDialog3.dialog('open'); }
});
$myDialog3 = jDialog({
dialog: '#idDiv_MyDialog3',
title: 'Take a sad song',
autoOpen: false,
close: function(event, ui) { $myDialog4dialog('open'); }
});
$myDialog4 = jDialog({
dialog: '#idDiv_MyDialog4',
title: 'And make it better',
autoOpen: false
});
});
You can set an event to run whenever a dialog is created that adds the title.
$(document).on('dialogcreate', function(){ // let it bubble up
$(".ui-dialog-title", this).before("xxx"); // add "xxx" before the title of this dialog
});

Categories

Resources