Open/Access WP Media library from tinymce plugin popup window - wordpress

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

Related

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

Creating a button in EXTJs

I have a login screen which has an ExtJs form panel with two button Login and Reset.
Now, I'm trying to add another button below the lofin panel for a new user sign up.
But the button goes out to the bottom of the screen and a scroll bar appears making the page look ugly!
I have these in my login.jsp file:
<link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all-access.css">
<script type="text/javascript" src="extjs/ext-all.js"></script>
<script type="text/javascript" src="js/app.js"></script>
And this is my app.js file:
Ext.onReady(function(){
Ext.QuickTips.init();
var login = new Ext.FormPanel({
labelWidth:100,
frame:true,
title:'Member Login',
defaultType:'textfield',
monitorValid:true,
// Specific attributes for the text fields for username / password.
// The "name" attribute defines the name of variables sent to the server.
items:[{
fieldLabel:'Username',
name:'loginUsername',
allowBlank:false
},{
fieldLabel:'Password',
name:'loginPassword',
inputType:'password',
allowBlank:false
}],
buttons: [{
text: 'New User Register',
scale: 'medium',
handler: function()
{
login.getForm().doAction('standardsubmit',{
target : '_self',
method : 'POST',
standardSubmit:true,
formBind: false,
url: 'registration.jsp'
})
}
},{
text: 'Login',
scale: 'medium',
handler: function()
{
login.getForm().doAction('standardsubmit',{
target : '_self',
method : 'POST',
standardSubmit:true,
formBind: true,
url: 'index.jsp'
})
}
},{
text: 'Reset',
scale: 'medium',
handler: function(){
login.getForm().reset();
}
}]
});
// This just creates a window to wrap the login form.
// The login object is passed to the items collection.
var win = new Ext.Window({
layout:'fit',
width:325,
height:175,
closable: false,
resizable: false,
plain: true,
border: false,
items: [login]
});
win.show();
});
I tried adding a new button using the Ext.Createat the end of the above one but it wouldn't work.
I tried having the code in a separate js file and adding the script tag with src to the button file along with the panel file in a separate script tag and even that failed.
Can anybody help me out to create a separate button and my desired position?
Any kind of help is appreciated. Thanks.
I've looked everywhere and I've tried everything I could, but I'm not able to come up with the answer.
NOTE: The code makes the question seem very long and big, but my main query and issue is at the top and bottom of the question.
Im assuming you dont want to add the new button INSIDE the login panel because otherwise you could just add another button to your buttons list anyway. To add a button under your login panel and YET inside the window, do the following steps;
Put your form panel as an item inside a container
Add your button as a second item in the container after your form pannel
Add the container to your window as you did the panel to the window
Voilah! You could also try giving your window and 'id' such as 'id=loginWindow' and then calling the code
Ext.getCmp('loginWindow').add(
{
xtype:button,
text:'Yay!'
}
);
If you need more code specific help, feel free to message me. I know your feel bro <3

Attaching media to post type without editor support

I'm trying to add attachments to a custom post type that hasn't editor support (only excerpt).
I've managed to show the Media Manager dialog box, but I can only see the "Insert into post" button (that does nothing anyway) and when uploading images, they don't get attached to the post.
To implement what I did so far, I've added a very simple meta box to the post type:
function add_gallery_post_media_meta_box()
{
add_meta_box(
'gallery_post_media',
'Gallery Media',
'gallery_post_media',
'gallery',
'side',
'high'
);
} // add_file_meta_box
add_action('add_meta_boxes', 'add_gallery_post_media_meta_box');
function gallery_post_media()
{
echo '' . __('Add media') .'';
} // end post_media
function register_admin_scripts() {
wp_enqueue_media();
wp_register_script( 'gallery_post_media_admin_script', get_template_directory_uri() . '/library/cpt/gallery.js' );
wp_enqueue_script( 'gallery_post_media_admin_script' );
} // end register_scripts
add_action( 'admin_enqueue_scripts', 'register_admin_scripts' );
And the script:
jQuery(document).ready(function ($) {
$('#gallery-add-media').click(function (e) {
var send_attachment_bkp = wp.media.editor.send.attachment;
var button = $(this);
var id = button.attr('id').replace('_button', '');
wp.media.editor.send.attachment = function (props, attachment) {
$("#" + id).val(attachment.url);
wp.media.editor.send.attachment = send_attachment_bkp;
}
wp.media.editor.open(button);
event.preventDefault();
return false;
});
});
If I would able to find some documentation about wp.media.editor.send.attachment, I'd probably manage to get what I want, but I can't find anything useful.
The only solutions I've found all relies on custom fields, instead I want to simply attach these images to the post, without inserting them in the post content, as I would do with normal posts.
As a side question: is it possible to tell the Media Manager to only accept images?
This is the JavaScript I use for media fields. Once you hit insert you can do whatever you want with the data from the image's selected
jQuery(document).ready(function() {
//uploading files variable
var custom_file_frame;
jQuery(document).on('click', '.meida-manager', function(event) {
event.preventDefault();
$this = jQuery(this);
//If the frame already exists, reopen it
if (typeof(custom_file_frame)!=="undefined") {
custom_file_frame.close();
}
//Create WP media frame.
custom_file_frame = wp.media.frames.customHeader = wp.media({
//Title of media manager frame
title: "Sample title of WP Media Uploader Frame",
library: {
type: 'image'
},
button: {
//Button text
text: "insert text"
},
//Do not allow multiple files, if you want multiple, set true
multiple: false
});
//callback for selected image
custom_file_frame.on('select', function() {
var attachment = custom_file_frame.state().get('selection').first().toJSON();
//do something with attachment variable, for example attachment.filename
//Object:
//attachment.alt - image alt
//attachment.author - author id
//attachment.caption
//attachment.dateFormatted - date of image uploaded
//attachment.description
//attachment.editLink - edit link of media
//attachment.filename
//attachment.height
//attachment.icon - don't know WTF?))
//attachment.id - id of attachment
//attachment.link - public link of attachment, for example ""http://site.com/?attachment_id=115""
//attachment.menuOrder
//attachment.mime - mime type, for example image/jpeg"
//attachment.name - name of attachment file, for example "my-image"
//attachment.status - usual is "inherit"
//attachment.subtype - "jpeg" if is "jpg"
//attachment.title
//attachment.type - "image"
//attachment.uploadedTo
//attachment.url - http url of image, for example "http://site.com/wp-content/uploads/2012/12/my-image.jpg"
//attachment.width
$this.val(attachment.url);
$this.siblings('img').attr('src',attachment.url);
});
//Open modal
custom_file_frame.open();
});
});

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

WordPress Custom Insert Into Post Button

For images uploaded using WordPress' media uploader, there is an "Insert Into Post" button that sends a shortcode to the editor for that image.
I have a text input that, when focused, I'd like the media uploader to appear so that the user can select an image and send the file URL to the text input.
The main issue I'm having is creating the additional "Insert Into Post" button that sends the file URL to the appropriate text field.
Which hook do I use for that and how can I get the file URL data returned to the input field?
Your guidance is appreciated!
What you've described is the older Wordpress way of doing it... If you want to use the new uploader in Wordpress 3.5+, you can create a wp.media object to upload it, similar to the code in wp-admin/js/custom-background.js:
// Create the media frame.
frame = wp.media.frames.customBackground = wp.media({
// Set the title of the modal.
title: $el.data('choose'),
// Tell the modal to show only images.
library: {
type: 'image'
},
// Customize the submit button.
button: {
// Set the text of the button.
text: $el.data('update'),
// Tell the button not to close the modal, since we're
// going to refresh the page when the image is selected.
close: false
}
});
// When an image is selected, run a callback.
frame.on( 'select', function() {
// Grab the selected attachment.
var attachment = frame.state().get('selection').first();
// Run an AJAX request to set the background image.
$.post( ajaxurl, {
action: 'set-background-image',
attachment_id: attachment.id,
size: 'full'
}).done( function() {
// When the request completes, reload the window.
window.location.reload();
});
});
// Finally, open the modal.
frame.open();
the frame.on('select' function(){ code is run when a file is chosen.
A litter further searching and I was able to find some good sources explaining how to do this. I went for a JavaScript, PHP mix:
JavaScript
$j('input').live('focusin',function(){
var target = '#'+$j(this).attr('id');
tb_show('','media-upload.php?post_id=[post_id]&tab=gallery&context=choose&TB_iframe=1');
window.send_to_editor = function(html) {
fileurl = $j(html).attr('href');
$j(target).val(fileurl);
tb_remove();
};
});
source: http://jaspreetchahal.org/wordpress-using-media-uploader-in-your-plugin/
PHP
/* Customize button */
function media_uploader_btn($form_fields, $post) {
$send = "<input type='submit' class='button' name='send[$post->ID]' value='" . esc_attr__( 'Choose This File' ) . "' />";
$form_fields['buttons'] = array('tr' => "\t\t<tr class='submit'><td></td><td class='savesend'>$send</td></tr>\n");
$form_fields['context'] = array( 'input' => 'hidden', 'value' => 'choose' );
return $form_fields;
}
/* Check for button context */
function check_upload_image_context($context){
if(isset($_REQUEST['context']) && $_REQUEST['context'] == $context){
return true;
} elseif(isset($_POST['attachments']) && is_array($_POST['attachments'])){
/* check for context in attachment objects */
$image_data = current($_POST['attachments']);
if (isset($image_data['context']) && $image_data['context'] == $context ){
return true;
}
}
return false;
}
if(check_upload_image_context('choose')){
add_filter('attachment_fields_to_edit', 'media_uploader_btn', 20, 2);
}
source: http://shibashake.com/wordpress-theme/how-to-hook-into-the-media-upload-popup-interface

Resources