How to reset a custom plugin dialog in CKEditor 4 - drupal

My problem is I have a plugin which works fine when there is only 1 CKEditor in the page. You can open and close the custom plugin dialog as many times as you want, and make all your changes.
However, as soon as you open the plugin on any of the other CKEditors on the page, the values from the previous CKEditor instance are still present, and a lot of quirks happen.
I tried using the dialog.destroy() function, which "fixes" the issue - meaning you can now use it fine on all the different CKEditor instances. But it breaks the current instance, meaning if you try to open any you already used again, it doesn't work (since the dialog has been destroyed). I tried using reset() and replace() to no avail.
Maybe it has something to do with the fields themselves... here is a sample from the dialogs/my_plugin.js file:
contents: [
{
id: 'tab-basic',
label: 'Basic Settings',
elements: [
{
type: 'html',
id: 'icon_with_options',
html: '<div id="selected-icon"></div>',
},
{
type: 'html',
id: 'osu_icon_color',
html: '<div class="osu-colors"><label>Click on a color <input id="osu-icon-color" type="text" value="osu" readonly/></label>' +
'<p class="osu color-active"></p>' +
'<p class="sand"></p>' +
'<p class="stratosphere"></p>' +
'<p class="moondust"></p>' +
'<p class="dark"></p>' +
'<p class="pine-stand"></p>' +
'<p class="luminance"></p>' +
'<p class="reindeer-moss"></p>' +
'</div>',
onLoad: function () {
(function ($) {
var colors = $('.osu-colors p');
colors.click(function (e) {
colors.removeClass('color-active');
var className = e.currentTarget.className;
document.getElementById('osu-icon-color').value = className;
icon_preview();
$(this).addClass('color-active');
});
})(jQuery);
},
},
I wonder if the problem is that most HTML is decoration.
I did samples with the plugin using regular type:text and type:select and these worked fine. But somehow the type:'html' does not clear the same way and is causing issues. Unfortunately all examples online are of simple text elements or other prebuilt elements.
Any help is appreciated. This is a plugin inside a Drupal 7 module, but it should apply regardless.

I am sure there are better ways of doing this, but what I ended up doing was:
Since CKEditor gives unique names to every instance of the editor, I used: CKEDITOR.currentInstance.name as an ID that wraps around all the html in the plugin.
Modified my javascript to target everything based on the CKEDITOR.currentInstance.name and any particular ID or class I needed to make it happen.
Now since each instance is differentiated by that ID, all the CKEditor instances in a page work fine.

Related

wp_enqueue_scripts in TinyMCE Modal

I'm creating a simple WordPress plugin that requires wp_enqueue_media() to be called from a TinyMCE pop up in order to upload and/or select an image.
The issue im having is wp_enqueue_media() and wp_enqueue_script() don't appear to work with the TinyMCE pop up modal.
I am including wp-load.php in my modal window.
Is there a way to utilize native WordPress script loading within a TinyMCE modal?
Here is an example of what I am doing.
http://return-true.com/adding-tinymce-button-to-wordpress-via-plugin-part-2/
Like I already said in my comment, I think the best approach is to use an inline modal (no iframe).
It is very simple: using the 1st part of the article (http://return-true.com/adding-tinymce-button-to-wordpress-via-a-plugin/) as a basis, just replace the JavaScript with the following (copied from TinyMCE guidelines):
(function() {
tinymce.PluginManager.add('example', function(editor) {
// Add a button that opens a window
editor.addButton('example', {
text: 'Example',
icon: false,
onclick: function() {
// Open window
editor.windowManager.open({
title: 'Example plugin',
body: [
{type: 'textbox', name: 'title', label: 'Title'}
],
onsubmit: function(e) {
// Insert content when the window form is submitted
editor.insertContent('Title: ' + e.data.title);
}
});
}
});
});
})();
After that, you have a simple modal, with no iframe, thus using the native Wordpress script loading.
If the content must be in an iframe (which I doubt), one option is to create a 'blank' page in Wordpress with a page template of its own and use that page as the modal content. I actually tested that it works, but it is clearly more complicated (requires something like a blog post to explain).
The issue was that I was not including wp_head() and wp_footer() in the modal window html.
Adding these functions solved the enqueue issues.

Open/Access WP Media library from tinymce plugin popup window

I'm building a tinymce button plugin for the Wordpress (4) editor. The popup window that my button opens displays a form with several fields. One of them is for selecting an image inside the WP media library. I can't figure how to achieve this.
If that's not possible, what would be the best way to allow the user to select an image stored in the WP media library from a tinymce plugin popup window ?
FYI, the tinymce plugin inserts a shortcode with an image src as an attribute.
thanks !
I had the same problem just now and found the solution so I'm sharing it here. I hope it's not too late.
First to be able to use WP Add Media button you would have to enqueue the needed script. This is easy, just call the wp_enqueue_media() function like so:
add_action('admin_enqueue_scripts', 'enqueue_scripts_styles_admin');
function enqueue_scripts_styles_admin(){
wp_enqueue_media();
}
This call ensures you have the needed libraries to use the WP Media button.
Of course you should also have the HTML elements to hold the uploaded/selected media file URL, something like this:
<input type="text" class="selected_image" />
<input type="button" class="upload_image_button" value="Upload Image">
The first text field will hold the URL of the media file while the second is a button to open the media popup window itself.
Then in your jscript, you'd have something like this:
var custom_uploader;
$('.upload_image_button').click(function(e) {
e.preventDefault();
var $upload_button = $(this);
//Extend the wp.media object
custom_uploader = wp.media.frames.file_frame = wp.media({
title: 'Choose Image',
button: {
text: 'Choose Image'
},
multiple: false
});
//When a file is selected, grab the URL and set it as the text field's value
custom_uploader.on('select', function() {
var attachment = custom_uploader.state().get('selection').first().toJSON();
$upload_button.siblings('input[type="text"]').val(attachment.url);
});
//Open the uploader dialog
custom_uploader.open();
});
Now I'm not going to explain every line because it's not that hard to understand. The most important part is the one that uses the wp object to make all these to work.
The tricky part is making all these work on a TinyMCE popup(which is the problem I faced). I've searched hi and lo for the solution and here's what worked for me. But before that, I'll talk about what problem I encountered first. When I first tried to implement this, I encountered the "WP is undefined" problem on the popup itself. To solve this, you just have to pass the WP object to the script like so:
(function() {
tinymce.create('tinymce.plugins.someplugin', {
init : function(ed, url) {
// Register commands
ed.addCommand('mcebutton', function() {
ed.windowManager.open(
{
file : url + '/editor_button.php', // file that contains HTML for our modal window
width : 800 + parseInt(ed.getLang('button.delta_width', 0)), // size of our window
height : 600 + parseInt(ed.getLang('button.delta_height', 0)), // size of our window
inline : 1
},
{
plugin_url : url,
wp: wp
}
);
});
// Register buttons
ed.addButton('someplugin_button', {title : 'Insert Seomthing', cmd : 'mcebutton', image: url + '/images/some_button.gif' });
}
});
// Register plugin
// first parameter is the button ID and must match ID elsewhere
// second parameter must match the first parameter of the tinymce.create() function above
tinymce.PluginManager.add('someplugin_button', tinymce.plugins.someplugin);
})();
What we're interested in is this line => "wp: wp" . This line ensures that we are passing the wp object to the popup window (an iframe really...) that is to be opened when we click the tinymce button. You can actually pass anything to the popup window via this object (the 2nd parameter of the ed.windowManager.open method)!
Last but not the least you'd have to reference that passed wp object on your javascript like so:
var args = top.tinymce.activeEditor.windowManager.getParams();
var wp = args.wp;
Make sure you do that before calling/using the WP object.
That's all you have to do to make this work. It worked for me, I hope it works for you :)
I took the code of Paolo and simplified it in order not to have many files to manage. Also, I didn't manage to make it work like this.
So this solution has less code and uses only one single file.
Just put this in your tinyMCE plugins js file:
(function(){
tinymce.PluginManager.add('myCustomButtons', function(editor, url){
editor.addButton('btnMedia', {
icon: 'image',
tooltip: 'Add an image',
onclick: function() {
editor.windowManager.open({
title: 'Add an image',
body: [{
type: 'textbox',
subtype: 'hidden',
name: 'id',
id: 'hiddenID'
},
{
type: 'textbox',
name: 'text',
label: 'Text',
id: 'imageText'
},
{
type: 'button',
text: 'Choose an image',
onclick: function(e){
e.preventDefault();
var hidden = jQuery('#hiddenID');
var texte = jQuery('#imageText');
var custom_uploader = wp.media.frames.file_frame = wp.media({
title: 'Choose an image',
button: {text: 'Add an image'},
multiple: false
});
custom_uploader.on('select', function() {
var attachment = custom_uploader.state().get('selection').first().toJSON();
hidden.val(attachment.id);
if(!texte.val()){
if(attachment.alt)
texte.val(attachment.alt);
else if(attachment.title)
texte.val(attachment.title);
else
texte.val('See the image');
}
});
custom_uploader.open();
}
}],
onsubmit: function(e){
var image = '<button data-id="'+e.data.id+'">'+e.data.text+'</button>';
editor.insertContent(image);
}
});
}
});
});
})();
The result in the frontend html is a button which has the ID of the image in a data-id attribute, and a text to display (the alt of the image, by default, or its title or a text the user can write).
Then, with my frontend js, I will get the corresponding image with its ID and show it in an ajax popup.
With this solution, you have all of your js functions in one single file, and you don't need to enqueue any script nor to create a php file.
I know it's old but in case anyone else facing the same situation, The Paolo's solution above is working fine but no need to enqueue wp_enqueue_media(); this will load a bunch of scripts, you can load only 2 scripts:
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'media-lib-uploader-js' );

full calendar truncate title

I am using fullcalendar 1.6.0, with qtip2, building an array in php and using this as the events list
$('#calendar').fullCalendar({
// put your options and callbacks here
events: [
<?php echo $eventlist; ?>
],
It is working fine, but I would now like to use the calendar in a 'mobile friendly' layout.
What I want to do is, at resolutions below a certain breakpoint, remove some or all of the event information from displaying within the calendar itself, (so a colored block appears on the calendar, but little or nothing else) but still appear in the qtip.
Can I use eventrender to do this ?
Yes. I think you can do this.
Below is the sample code. You have to use two events eventRender and eventAfterAllRender. or you can also hide the elements inside eventAfterAllRender.
eventRender: function (event, element, view) {
if( window.screen.width < 300 ) {
$('.fc-event-title').hide();
$('.fc-event-time').hide();
}
},
eventAfterAllRender: function( view ) {
$('.fc-event-inner').each(function(){
$(this).qtip(
{
content: $(this).children('.fc-event-time').html() + '' + $(this).children('.fc-event-title').html()
});
}
}
NOTE: This code is not tested. Change it according to your needs. Something like above will work for you.

In a plugin, how to add a html page to ckeditor dialog

I'm working on upgrading a old fckeditor to ckeditorv3. I found most of APIs been updated.
There is a internal used plugin ,its content is a aspx page,and this page will provide dynmic list.
I want to upgrade that plugin to make it work in new ckeditorv3.
Can anyone show me a tutorial link about how to add a html page to a ckedirot dialog ?
I found that one http://www.kusog.org/articles/OtherJavaScriptLibraries_WritingCustomCKEditorPlugins/ , but it is just some basic info. What i want to do is embed a html page into a plugin's dialog.
Ok, I found the solution. You need to load the page in a dialog iframe.
CKEDITOR.plugins.add('customfields',
{
init: function(editor) {
editor.addCommand('customfields', new CKEDITOR.dialogCommand('customfields'));
editor.ui.addButton('Customfields',
{
label: 'Custom Fields',
command: 'customfields',
icon: this.path + 'CustomFields.gif'
});
CKEDITOR.dialog.addIframe(
'customfields',
'Custom Fields',
this.path + 'CustomFields2.aspx', null, null,
function() { alert('aaaa'); }, function() { alert('bbbb'); }
);
}
});

Using jQuery UI dialog in Wordpress

I know there is at least 1 other post on SO dealing with this but the answer was never exactly laid out.
I am working in a WP child theme in the head.php document. I have added this in the head:
<link type="text/css" href="http://www.frontporchdeals.com/wordpress/wp-includes/js/jqueryui/css/ui-lightness/jquery-ui-1.8.12.custom.css" rel="Stylesheet" />
<?php
wp_enqueue_style('template-style',get_bloginfo('stylesheet_url'),'',version_cache(),'screen');
wp_enqueue_script('jquery-template',get_bloginfo('template_directory').'/js/jquery.template.js',array('jquery'),version_cache(), true);
wp_enqueue_style('jquery-style', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/themes/smoothness/jquery-ui.css');
wp_enqueue_script('jq-ui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.js ');
wp_enqueue_script('jq-ui-min', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.12/jquery-ui.min.js' );
?>
and I added this in the body:
<script>
jQuery(function() {
$( "#dialog" ).dialog();
});
</script>
<div id="dialog" title="Basic dialog">
<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>
</div>
but no dice. My div shows as standard div.
Any ideas at all? I know that top stylesheet should be called with enqueue but that shouldn't stop this from working.
WordPress jQuery is called in no-conflict mode:
jQuery(document).ready(function($) {
$('#dialog' ).dialog();
});
Also jQuery UI is loading before jQuery. You're getting 2 javascript errors:
Uncaught ReferenceError: jQuery is not defined
103Uncaught TypeError: Property '$' of object [object DOMWindow] is not a function
The first error is from jQuery UI loading before jQuery and the second is because the $ is not recognized in no-conflict mode.
Remove any of the inline <script src= tags and the call to the custom.css in header php and add this function to your child theme functions.php file to load the scripts. WordPress will put them in the right order for you.
add_action( 'init', 'frontporch_enqueue_scripts' );
function frontporch_enqueue_scripts() {
if (!is_admin() ) {
wp_enqueue_script( 'jquery' );
wp_register_script( 'google-jquery-ui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.12/jquery-ui.min.js', array( 'jquery' ) );
wp_register_script( 'jquery-template', get_bloginfo('template_directory').'/js/jquery.template.js',array('jquery'),version_cache(), true);
wp_register_style( 'jquery-style', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/themes/smoothness/jquery-ui.css', true);
wp_register_style( 'template-style', 'http://www.frontporchdeals.com/wordpress/wp-includes/js/jqueryui/css/ui-lightness/jquery-ui-1.8.12.custom.css', true);
wp_enqueue_style( 'jquery-style' );
wp_enqueue_style( ' jquery-template' );
wp_enqueue_script( 'google-jquery-ui' );
wp_enqueue_script( 'jquery-template' );
}
}
I'm building a custom plugin on WP admin to insert data on custom MySQL tables. For nearly a week I was trying to do a confirmation dialog for a delete item event on a Wordpress table. After I almost lost all my hair searching for an answer, it seemed too good and simple to be true. But worked. Follows the code.
EDIT: turns out that the wp standard jquery wasn't working properly, and the Google hosted jQuery included in another class was making the correct calls for the JS. When I removed the unregister/register added below, ALL the other dialog calls stopped working. I don't know why this happened, or the jQuery version included in this particular WP distribution, but when I returned to the old registrations, using Google hosted scripts as seen below, everything went back to normality.
On PHP (first, register and call the script):
add_action('admin_init', 'init_scripts_2');
function init_scripts_2(){
///deregister the WP included jQuery and style for the dialog and add the libs from Google
wp_deregister_script('jquery-ui');
wp_register_script('jquery-ui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js');
wp_deregister_style('jquery-ui-pepper-grinder');
wp_register_style('jquery-ui-pepper-grinder', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/pepper-grinder/jquery-ui.min.css');
wp_enqueue_script('jquery-ui'); ///call the recently added jquery
wp_enqueue_style('jquery-ui-pepper-grinder'); ///call the recently added style
wp_deregister_script('prevent_delete'); ///needed the deregister. why? don't know, but worked
///register again, localize and enqueue your script
wp_register_script('prevent_delete', WP_PLUGIN_URL . '/custom_plugin/js/prevent_delete.js', array('jquery-ui'));
wp_localize_script('prevent_delete', 'ajaxdelete', array('ajaxurl' => admin_url('admin-ajax.php')));
wp_enqueue_script('prevent_delete');
}
Next, if you're opening the dialog on a click event, like me, make sure you ALWAYS use class instead of id to identify the button or link later, on jQuery.
<a class="delete" href="?page=your_plugin&action=delete">Delete</a>
We also need to use a tag that holds the dialog text. I needed to set the style to hide the div.
<div id="dialog_id" style="display: none;">
Are you sure about this?
</div>
Finally, the jQuery.
/*jslint browser: true*/
/*global $, jQuery, alert*/
jQuery(document).ready(function ($) {
"use strict";
///on class click
$(".delete").click(function (e) {
e.preventDefault(); ///first, prevent the action
var targetUrl = $(this).attr("href"); ///the original delete call
///construct the dialog
$("#dialog_id").dialog({
autoOpen: false,
title: 'Confirmation',
modal: true,
buttons: {
"OK" : function () {
///if the user confirms, proceed with the original action
window.location.href = targetUrl;
},
"Cancel" : function () {
///otherwise, just close the dialog; the delete event was already interrupted
$(this).dialog("close");
}
}
});
///open the dialog window
$("#dialog_id").dialog("open");
});
});
EDIT: The call for the standard wp dialog style didn't work after all. The "pepper-grinder" style made the dialog appear correctly in the center of the window. I know the looks for the dialog are not very easy on the eye, but i needed the confirmation dialog and this worked just fine for me.
The dialog div is created AFTER when you're trying to act upon it. Instead, you should use:
$(document).ready(function() {
$( "#dialog" ).dialog();
});

Resources