ckeditor change button icon dynamically - button

I am trying to write a plugin for ckeditor, like in the link below
CKEditor Custom Plugins Button
the problem is, I want the button to change once I click it, and change back, so the users knows something happened. how can i change the path to the icon after the button is added? is there something like editor.ui.editButton?
Thanks!

$('.cke_button__BUTTONNAME_icon').css('background-position', '0 0').css('background-image', 'url(pathtoimage)').css('background-repeat','no-repeat');
Where BUTTONNAME is all in small letters and pathtoimage is relative to html file.
To chance image path to relative to the plugin.js by using this.path. Important thing this.path should be outside the scope of function as shown below:
var _p = this.path;
editor.addCommand('toggleAutocorrect',
{
exec : function()
{
$('.cke_button__toggleautocorrect_icon').css('background-position', '0 0').css('background-image', 'url("' + _p + '/images/autocorrectOff.png")').css('background-repeat','no-repeat');
}
}
});
editor.ui.addButton('ToggleAutocorrect',
{
label: 'Toggle Autocorrect',
command: 'toggleAutocorrect',
icon: this.path + 'images/toggleAutocorrect.png'
});

i have a dirty hack: (with jQuery)
$('.cke_button_COMMANDNAME.cke_icon').css('backgroundImage', 'url('+thisPath+'imageOff.gif)');
Where Commandname the name of the Button is and this path is a var wich i initiate in the plugin with
var thisPath = this.path;

Related

How do you add a custom button to the Elementor Text Editor widget toolbar?

I'm trying to add a custom button into the Elementor text widget toolbar next to other buttons like Bold, Italic, Underline etc. It seems that the ability to customize the instance using PHP may be disabled but that it is possible to do so using JavaScript instead.
I can get back the view by using the following code but I'm unable to get back the editor instance.
elementor.hooks.addAction( 'panel/open_editor/widget/text-editor', function( panel, model, view ) {}
I've tried the following suggestions but none seem to return anything after that.
// get active instances of the editor
let editor = tinymce.activeEditor;
var editor = elementor.editors.get(0).getEditModel().get('editor');
var activeEditor = view.getOption('editor');
The rest of the suggested code after getting the editor instance is as follows but I don't get this far.
// add a button to the editor buttons
editor.addButton('tooltip', {
text: 'tooltip',
icon: false,
onclick: (editor) => {
tooltipCallback(editor);
}
});
// the button now becomes
let button=editor.buttons['tooltip'];
// find the buttongroup in the toolbar found in the panel of the theme
let bg=editor.theme.panel.find('toolbar buttongroup')[0];
// without this, the buttons look weird after that
bg._lastRepaintRect=bg._layoutRect;
// append the button to the group
bg.append(button);

Wordpress tinymce dialog box Body Element & Attribute Formal Documentation

I am new to the tinymce. I have been trying to figure out all of the attributes I need to use to create decent looking dialog that the user fills out and create shortcode output. In the code example below the label and the textbox are butted against each other with no margin or padding and any trailing spaces in the label text are trimmed, this is just one change that I would like to make. I have looked at the documentation to tinymce and all I find are simple brief code examples.
My Question 1: Where can I find the formal full documentation of this windowManager.open method and all of the possible attributes and methods associated with it?
My Question 2&3: Are these attribute actually native javascript? If so where can I find the formal full documentation to it?
Thanks for any help you can give me to retrieve the documentation or possibly formatting with a css sytle sheet (w/.mce-widget or .mce-textbox) and where and how to register this style sheet in Wordpress.
(function() {
tinymce.create("tinymce.plugins.youtube_plugin", {
//url argument holds the absolute url of our plugin directory
init : function(ed, url) {
alert('in youtube');
//add new button
ed.addButton("youtube_button", {
title : "Youtube Video Responsive Embed",
cmd : "youtube_command",
image : "https://cdn0.iconfinder.com/data/icons/social-flat-rounded-rects/512/youtube_v2-32.png"
});
//button functionality.
ed.addCommand("youtube_command", function() {
//alert('hello youtube');
ed.windowManager.open({
title: "YouTube Video Settings", // The title of the dialog window.
//file : url + '/../html/youtube.html',
width : 800,
height : 300,
inline : 1,
body: [{
type: 'container',
//label : 'flow',
//layout: 'flow',
items: [
{type: 'label', text: 'Youtube ServerPath:'},
{type: 'textbox', size: '80', name: 'title', value: 'http://www.youtube.com/embed/'},
//{type: 'label', text: 'and two labels'}
]
}],
buttons: [{
text: 'Submit',
onclick: 'submit'
}, {
text: 'Cancel',
onclick: 'close'
}],
onsubmit: function(e) {
//form = $('#youtube_plugin_id iframe').contents().find('form');
alert('hello');
ed.insertContent('Title: ' + e.data.title);
}
});
//var selected_text = ed.selection.getContent();
// var return_text = "<span style='color: green'>" + selected_text + "</span>";
//ed.execCommand("mceInsertContent", 0, return_text);
});
} // end init
}); // end tinymce.create
tinymce.PluginManager.add("youtube_button_plugin", tinymce.plugins.youtube_plugin);
})();
Although I didn't find any formal documentation to create a nice looking mce dialog box specifically, I did figure out how to format the dialog title and then embed an external html file that you can add a link tag to a css style sheet and the sky is the limit.
Here is the JavaScript code for the mce, it's up to you to create the external html and css files.
(function($) {
/**
This tinymce plugin provides the editor button and the modal dialog used to embed.
*/
// Extract data stored in the global namespace in tinymce-dev-starter.php.
var passed_data = lgrriw_data;
var php_version = passed_data.php_version;
var valid_domains = passed_data.valid_domains;
var dialogTitle = 'My Dialog Title';
// Define the TinyMCE plugin and setup the button.
// The last property in the first tinymce.create paramenter below must be the same
// as the plugin you defined in tinymce-dev-starter.php. In this case, it is
// lgrriw_plugin. If we called it my_cool_plugin, the first parameter would change
// to 'tinymce.plugins.my_cool_plugin'.
tinymce.create('tinymce.plugins.lgrriw_plugin', {
init: function(editor, url) {
/**
* The editor parameter contains the TinyMCE editor instance. The url
* parameter contains the absolute url to the directory containing the
* TinyMCE plugin file (this file's directory).
*
* We will be using editor to talk to the TinyMCE instance. And we
* will be using url to tell TinyMCE where files are (e.g. button
* images).
*/
// Specify button properties and commands.
// The first parameter of editor.addButton must be the button ID
// given in tinymce-dev-starter.php. In this case, it is lgrriw_button.
editor.addButton('lgrriw_button', {
title: dialogTitle, // Tooltip when hovering over button.
image: url + '/../../assets/tinymce-button_32.png', // The image for the button.
cmd: 'lgrriw_command' // The editor command to execute on button click.
});
// Define the "command" executed on button click.
editor.addCommand('lgrriw_command', function() {
editor.windowManager.open(
{
title: dialogTitle, // The title of the dialog window.
file: url + '/../html/tinymce_dialog.html', // The HTML file with the dialog contents links to css style sheet(s).
width: 810, // The width of the dialog
height: 505, // 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,
jquery: $,
valid_domains: valid_domains
}
);
$('.mce-title').each(function(index,item){
// Iterate through the mce titles until you find
// the dialog for this dialog before formatting, otherwise
// the formatting will change the Wordpress
// Theme globally. Be Careful!
if($(item).text() == dialogTitle){
// Format the dialog title using css
$(item).css('text-align', 'center');
$(item).css('color', '#336999');
$(item).css('background-color', '#add9ff');
}
});
});
}
});
// Add the plugin to TinyMCE
// Documentation: http://www.tinymce.com/wiki.php/api4:method.tinymce.AddOnManager.add
tinymce.PluginManager.add('lgrriw_plugin', tinymce.plugins.lgrriw_plugin);
})(jQuery);

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' );

Bootboxjs: how to render a Meteor template as dialog body

I have the following template:
<template name="modalTest">
{{session "modalTestNumber"}} <button id="modalTestIncrement">Increment</button>
</template>
That session helper simply is a go-between with the Session object. I have that modalTestNumber initialized to 0.
I want this template to be rendered, with all of it's reactivity, into a bootbox modal dialog. I have the following event handler declared for this template:
Template.modalTest.events({
'click #modalTestIncrement': function(e, t) {
console.log('click');
Session.set('modalTestNumber', Session.get('modalTestNumber') + 1);
}
});
Here are all of the things I have tried, and what they result in:
bootbox.dialog({
message: Template.modalTest()
});
This renders the template, which appears more or less like 0 Increment (in a button). However, when I change the Session variable from the console, it doesn't change, and the event handler isn't called when I click the button (the console.log doesn't even happen).
message: Meteor.render(Template.modalTest())
message: Meteor.render(function() { return Template.modalTest(); })
These both do exactly the same thing as the Template call by itself.
message: new Handlebars.SafeString(Template.modalTest())
This just renders the modal body as empty. The modal still pops up though.
message: Meteor.render(new Handlebars.SafeString(Template.modalTest()))
Exactly the same as the Template and pure Meteor.render calls; the template is there, but it has no reactivity or event response.
Is it maybe that I'm using this less packaging of bootstrap rather than a standard package?
How can I get this to render in appropriately reactive Meteor style?
Hacking into Bootbox?
I just tried hacked into the bootbox.js file itself to see if I could take over. I changed things so that at the bootbox.dialog({}) layer I would simply pass the name of the Template I wanted rendered:
// in bootbox.js::exports.dialog
console.log(options.message); // I'm passing the template name now, so this yields 'modalTest'
body.find(".bootbox-body").html(Meteor.render(Template[options.message]));
body.find(".bootbox-body").html(Meteor.render(function() { return Template[options.message](); }));
These two different versions (don't worry they're two different attempts, not at the same time) these both render the template non-reactively, just like they did before.
Will hacking into bootbox make any difference?
Thanks in advance!
I am giving an answer working with the current 0.9.3.1 version of Meteor.
If you want to render a template and keep reactivity, you have to :
Render template in a parent node
Have the parent already in the DOM
So this very short function is the answer to do that :
renderTmp = function (template, data) {
var node = document.createElement("div");
document.body.appendChild(node);
UI.renderWithData(template, data, node);
return node;
};
In your case, you would do :
bootbox.dialog({
message: renderTmp(Template.modalTest)
});
Answer for Meteor 1.0+:
Use Blaze.render or Blaze.renderWithData to render the template into the bootbox dialog after the bootbox dialog has been created.
function openMyDialog(fs){ // this can be tied to an event handler in another template
<! do some stuff here, like setting the data context !>
bootbox.dialog({
title: 'This will populate with content from the "myDialog" template',
message: "<div id='dialogNode'></div>",
buttons: {
do: {
label: "ok",
className: "btn btn-primary",
callback: function() {
<! take some actions !>
}
}
}
});
Blaze.render(Template.myDialog,$("#dialogNode")[0]);
};
This assumes you have a template defined:
<template name="myDialog">
Content for my dialog box
</template>
Template.myDialog is created for every template you're using.
$("#dialogNode")[0] selects the DOM node you setup in
message: "<div id='dialogNode'></div>"
Alternatively you can leave message blank and use $(".bootbox-body") to select the parent node.
As you can imagine, this also allows you to change the message section of a bootbox dialog dynamically.
Using the latest version of Meteor, here is a simple way to render a doc into a bootbox
let box = bootbox.dialog({title:'',message:''});
box.find('.bootbox-body').remove();
Blaze.renderWithData(template,MyCollection.findOne({_id}),box.find(".modal-body")[0]);
If you want the dialog to be reactive use
let box = bootbox.dialog({title:'',message:''});
box.find('.bootbox-body').remove();
Blaze.renderWithData(template,function() {return MyCollection.findOne({_id})},box.find(".modal-body")[0]);
In order to render Meteor templates programmatically while retaining their reactivity you'll want to use Meteor.render(). They address this issue in their docs under templates.
So for your handlers, etc. to work you'd use:
bootbox.dialog({
message: Meteor.render(function() { return Template.modalTest(); })
});
This was a major gotcha for me too!
I see that you were really close with the Meteor.render()'s. Let me know if it still doesn't work.
This works for Meteor 1.1.0.2
Assuming we have a template called changePassword that has two fields named oldPassword and newPassword, here's some code to pop up a dialog box using the template and then get the results.
bootbox.dialog({
title: 'Change Password',
message: '<span/>', // Message can't be empty, but we're going to replace the contents
buttons: {
success: {
label: 'Change',
className: 'btn-primary',
callback: function(event) {
var oldPassword = this.find('input[name=oldPassword]').val();
var newPassword = this.find('input[name=newPassword]').val();
console.log("Change password from " + oldPassword + " to " + newPassword);
return false; // Close the dialog
}
},
'Cancel': {
className: 'btn-default'
}
}
});
// .bootbox-body is the parent of the span, so we can replace the contents
// with our template
// Using UI.renderWithData means we can pass data in to the template too.
UI.insert(UI.renderWithData(Template.changePassword, {
name: "Harry"
}), $('.bootbox-body')[0]);

Add the link 'Add to favorite' to website using drupal 7

I want to add a link named "Add to favorite" in the footer of my site. I don't find any module which can do it, so please is there any way to do this ?
Big Thanks
I will just explain what Pete already said.
You need to add this javascript code somehow to make your "Add to favorite" button functional:
<script type="text/javascript">
$(function() {
$('#bookmarkme').click(function() {
if (window.sidebar && window.sidebar.addPanel) { // Mozilla Firefox Bookmark
window.sidebar.addPanel(document.title,window.location.href,'');
} else if(window.external && ('AddFavorite' in window.external)) { // IE Favorite
window.external.AddFavorite(location.href,document.title);
} else if(window.opera && window.print) { // Opera Hotlist
this.title=document.title;
return true;
} else { // webkit - safari/chrome
alert('Press ' + (navigator.userAgent.toLowerCase().indexOf('mac') != - 1 ? 'Command/Cmd' : 'CTRL') + ' + D to bookmark this page.');
}
});
});
</script>
You need to create a link in a block or template:
Add to favorite
If you have your own theme, then put the javascript in a separate file and add it in the theme info file:
scripts[] = myFile.js
You can add it via a custom module also with durpal_add_js() function.
The easiest & NOT RECOMMENDED way is to add it in the block body itself, just after adding the link. You need to set formatting as "Full HTML" or "PHP" though for this to work.

Resources