I'm doing a PrestaShop module. This module will be anchored to the hook called "hookDisplayAdminProductsExtra".
I need to use the TEXTAREA field tinymce using the library, you can do so by creating the textarea directly from Smarty and not as a controller? Maybe using jQuery function or adding a class to the field?
My code in tpl file is:
{foreach $row_list as $row}
<textarea id="description_1" name="description_1" class="autoload_rte" aria-hidden="true">
{$row['desc']}
</textarea>
{/foreach}
My module function is:
$this->context->smarty->assign(
array(
'row_list' => $this->getField($id)
)
);
return $this->display(__FILE__, 'admin-view.tpl');
The autoload_rte is "used" when tab Informations is loaded by Prestashop using:
$(document).ready(function(){
// Execute when tab Informations has finished loading
tabs_manager.onLoad('Informations', function(){
tinySetup({
editor_selector :"autoload_rte",
setup : function(ed) {
ed.on('init', function(ed)
{
if (typeof ProductMultishop.load_tinymce[ed.target.id] != 'undefined')
{
if (typeof ProductMultishop.load_tinymce[ed.target.id])
tinyMCE.get(ed.target.id).hide();
else
tinyMCE.get(ed.target.id).show();
}
});
ed.on('keydown', function(ed, e) {
tinyMCE.triggerSave();
textarea = $('#'+tinymce.activeEditor.id);
var max = textarea.parent('div').find('span.counter').data('max');
if (max != 'none')
{
count = tinyMCE.activeEditor.getBody().textContent.length;
rest = max - count;
if (rest < 0)
textarea.parent('div').find('span.counter').html('<span style="color:red;">Maximum '+ max +' characters : '+rest+'</span>');
else
textarea.parent('div').find('span.counter').html(' ');
}
});
}
});
});
});
In addition to this, the other tabs are also loaded later than the Informations tab. To solve this, you need to initialized the tinymce for the field you want. Choose another selector (not sure it's needed but at least there is 100% no chance to mess with the current ones), for example the class mytextarea, then use:
<script>$(document).ready(function(){tinymce.init({mode : "textareas", editor_selector : "mytextarea", plugins: "textcolor paste code"});})</script>
This can be in your tpl.
In my tests, if there is no plugins setup there would be an error in console log. But you can adjust the tinymce settings as you wish.
Ok here is my code - stock standard and works if I simply select an existing image
jQuery(function($){
var file_frame;
$('#upload-button').on( 'click', function( e ){
e.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create a new media frame
file_frame = wp.media({
title: 'Select or Upload Media Of Your Chosen Persuasion',
button: {
text: 'Use this media'
},
multiple: false // Set to true to allow multiple files to be selected
});
file_frame.on('open', function(){
console.log("inside open");
});
file_frame.on('update', function(){
console.log("inside update");
});
file_frame.on('select', function(){
// This will return the selected image from the Media Uploader, the result is an object
var uploaded_image = file_frame.state().get('selection').first();
// We convert uploaded_image to a JSON object to make accessing it easier
// Output to the console uploaded_image
console.log(uploaded_image);
var image_url = uploaded_image.toJSON().url;
// Let's assign the url value to the input field
$('#image-url').val(image_url);
});
file_frame.open();
});
});
But if I goto drag and drop an image in there the image is uploaded but an error is returned
"An error occurred in the upload. Please try again later."
What have I missed, I'm assuming its some kind of refresh for the existing media selection window and my googling has not turned up anything.
Cheers
EDIT
I have tried several things to get the uploaded image to be shown in the media frame once uploaded. Not having much success.
As I said it appears the image is uploaded and added to the media library but I am missing a refresh or reload of the frame to show the image.
Any one have experience with or know another place to go look?
Maybe this call when everything is 'done':
if(wp.media.frame.library) wp.media.frame.library.props.set({ignore: (+ new Date())});
Or if you need to separate the library Grid modal from media upload (edit post) modal:
if(wp.media.frame.library){
wp.media.frame.library.props.set({ignore: (+ new Date())});
} else if(wp.media.frame.content.get().collection){
wp.media.frame.content.get().collection.props.set({ignore: (+ new Date())});
wp.media.frame.content.get().options.selection.reset();
}
PHP FILE:
<?php
#Communication with the API
require_once 'api.php';
$cloudkey = new CloudKey($user_id, $api_key);
if(isset($_FILES["FileInput"]) && $_FILES["FileInput"]["error"]== UPLOAD_ERR_OK)
{
//Deleted Code: putting the uploaded files in my server.
if(move_uploaded_file($_FILES['FileInput']['tmp_name'], $UploadDirectory.$NewFileName ))
{
$video_file = "/home/george/public_html/q/";
$video_file = $video_file . $NewFileName;
#Sending the video from my server to the cloud server
$res = $cloudkey->file->upload_file($video_file);
#The cloud server will create a link
$source_url = $res->url;
#The cloud server will convert the video very fastly
while(1) {
#Deleted Code: Conversion
if ($asset->status == 'ready') {
# A lot of code. It will convert the videos here and if it succeeds it will stop.
break;
# If the conversion fails, display error
} else if ($asset->status == 'error') {
echo "Error while transcoding the media\n";
}
sleep(1);
}
# Getting the URL of a thumbnail
echo $thumb = $cloudkey->media->get_stream_url(array('id' => $media_id, 'asset_name' => 'jpeg_thumbnail_source'));
}else{
die('error uploading File!');
}
}
else
{
die('Something went wrong!');
}
?>
HTML FILE:
{literal}
<script type="text/javascript">
$(document).ready(function() {
var options = {
target: '#output', // target element(s) to be updated with server response
beforeSubmit: beforeSubmit, // pre-submit callback
success: afterSuccess, // post-submit callback
uploadProgress: OnProgress, //upload progress callback
resetForm: true // reset the form after successful submit
};
//function after succesful file upload (when server response)
function afterSuccess()
{
$('#loading-img').hide(); //hide submit button
$('#progressbox').fadeOut(); //hide progress bar
//I WANT TO INSERT SOMETHING HERE.
}
//progress bar function
function OnProgress(event, position, total, percentComplete)
{
//DOES NOT INTEREST YOU
});
</script>
{/literal}
<div id="output"></div>
I am using smarty template engine. I have an html upload form that will communicate with a php file progressupload.php where the php file will convert the video (using API services) and brings back a response when it finishes.
When the user uploads the video file, ajax will take over show the percentage (in html), and it will send the file to progressupload.php and when the progressupload.php finishes the conversion it will output everything echoed in the php by simply putting this in the html file (I don't know why): <div id="output"></div>.
WHAT I WANT:
When progressupload.php finishes the conversion, it will generate a thumbnail (screenshot) and store its link in $thumb. I want to retrieve $thumb and show it to the user using jquery.
Now if you look at the HTML Code, afterSuccess() is the function where I want to show the thumbnail to the user:
function afterSuccess()
{
$('#loading-img').hide(); //hide submit button
$('#progressbox').fadeOut(); //hide progress bar
//I WANT TO SHOW THE THUMBNAIL HERE.
}
I deleted a lot of unnecessary code that could've distracted you. Remember that I am using smarty template engine, my html file does not end with .php, I cannot echo the variable directly. How can I retrieve the php variable and put it in a jquery method after the variable is created.
I have a suspicion that if you retrieve the variable directly on page load, it will not succeed in getting $thumb since the link needs time to be created (uploading, conversion). How can I retrieve that $thumb?
Assuming that you are using jQuery.ajax();
First parameter in the $.ajax 'success' callback is what returned from the server side.
function afterSuccess( response /** this is what returned from your server **/ )
{
$('#loading-img').hide(); //hide submit button
$('#progressbox').fadeOut(); //hide progress bar
//I WANT TO INSERT SOMETHING HERE.
console.log(response); // here you can access your $thumbnail
// below code is untested but it should work
// $("#output").html("<img src='"+response+"' class='thumbnail' />");
}
When I click the Add Media button on a Post/Page, I have the option to Add Media. After selecting media, I click Insert Into Post, and the images are inserted. However, there is another option, which is on the left sidebar. I can click Create Gallery. The image selecting process is the same, but when I click Create New Gallery, it goes to a new frame which allows me to edit the order of the images.
This second window is what I am after. I am calling the frame from a metabox, and I have gotten it successfully to allow me to grab single or multiple images and save the ID's as a string, as well as insert thumbnails live into a preview box. I cannot find anything about calling the Gallery frame.
My current code is as follows:
jQuery('#fg_select').on('click', function(event){
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frame = wp.media({
title: "Select Images For Gallery",
button: {text: "Select",},
library : { type : 'image'},
multiple: true // Set to true to allow multiple files to be selected
});
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
ids = jQuery('#fg_metadata').val().split(',');
ids.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
});
file_frame.on('ready', function() {
// Here we can add a custom class to our media modal.
// .media-modal doesn't exists before the frame is
// completly initialised.
$( '.media-modal' ).addClass( 'no-sidebar' );
});
// When an image is selected, run a callback.
file_frame.on('select', function() {
var imageIDArray = [];
var imageHTML = '';
var metadataString = '';
images = file_frame.state().get('selection');
images.each(function(image) {
imageIDArray.push(image.attributes.id);
imageHTML += '<li><button></button><img id="'+image.attributes.id+'" src="'+image.attributes.url+'"></li>';
});
metadataString = imageIDArray.join(",");
if(metadataString){
jQuery("#fg_metadata").val(metadataString);
jQuery("#featuredgallerydiv ul").html(imageHTML);
jQuery('#fg_select').text('Edit Selection');
jQuery('#fg_removeall').addClass('visible');
}
});
// Finally, open the modal
file_frame.open();
});
Any ideas?
EDIT:
I've gotten it to the point where it calls the gallery directly, without any sidebars, etc. However, it now ignores the on('select') call. I guess galleries send a different call when selecting the image?
jQuery(document).ready(function($){
// Uploading files
var file_frame;
jQuery('#fg_select').on('click', function(event){
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frame = wp.media({
frame: "post",
state: "featured-gallery",
library : { type : 'image'},
button: {text: "Edit Image Order"},
multiple: true
});
file_frame.states.add([
new wp.media.controller.Library({
id: 'featured-gallery',
title: 'Select Images for Gallery',
priority: 20,
toolbar: 'main-gallery',
filterable: 'uploaded',
library: wp.media.query( file_frame.options.library ),
multiple: file_frame.options.multiple ? 'reset' : false,
editable: true,
allowLocalEdits: true,
displaySettings: true,
displayUserSettings: true
}),
]);
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
ids = jQuery('#fg_metadata').val().split(',');
if (!empty(ids)) {
ids.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
}
});
file_frame.on('ready', function() {
// Here we can add a custom class to our media modal.
// .media-modal doesn't exists before the frame is
// completly initialised.
$( '.media-modal' ).addClass( 'no-sidebar' );
});
file_frame.on('change', function() {
// Here we can add a custom class to our media modal.
// .media-modal doesn't exists before the frame is
// completly initialised.
setTimeout(function(){
$('.media-menu a:first-child').text('← Edit Selection').addClass('button').addClass('button-large').addClass('button-primary');
},0);
});
// When an image is selected, run a callback.
file_frame.on('set', function() {
alert('test');
});
// Finally, open the modal
file_frame.open();
});
EDIT 2:
Okay, so I've gotten everything to fire correctly. But I can't decipher the outputted gallery code.
// When an image is selected, run a callback.
file_frame.on('update', function() {
var imageIDArray = [];
var imageHTML = '';
var metadataString = '';
images = file_frame.state().get('selection');
images.each(function(image) {
imageIDArray.push(image.attributes.id);
imageHTML += '<li><button></button><img id="'+image.attributes.id+'" src="'+image.attributes.url+'"></li>';
});
metadataString = imageIDArray.join(",");
if (metadataString) {
jQuery("#fg_metadata").val(metadataString);
jQuery("#featuredgallerydiv ul").html(imageHTML);
jQuery('#fg_select').text('Edit Selection');
jQuery('#fg_removeall').addClass('visible');
}
});
Nothing is coming out for $imageArray, or $imageHTML. $image is something, it's an [object object].
EDIT 3: As mentioned below in comment, the main problem with the code from Edit 2 is that when using Gallery, you have to call 'library' instead of 'selection'.
// Uploading files
var file_frame;
jQuery('#fg_select').on('click', function(event){
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frame = wp.media({
frame: "post",
state: "gallery",
library : { type : 'image'},
button: {text: "Edit Image Order"},
multiple: true
});
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
var ids = jQuery('#fg_metadata').val();
if (ids) {
idsArray = ids.split(',');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
}
});
// When an image is selected, run a callback.
file_frame.on('update', function() {
var imageIDArray = [];
var imageHTML = '';
var metadataString = '';
images = file_frame.state().get('library');
images.each(function(attachment) {
imageIDArray.push(attachment.attributes.id);
imageHTML += '<li><button></button><img id="'+attachment.attributes.id+'" src="'+attachment.attributes.url+'"></li>';
});
metadataString = imageIDArray.join(",");
if (metadataString) {
jQuery("#fg_metadata").val(metadataString);
jQuery("#featuredgallerydiv ul").html(imageHTML);
jQuery('#fg_select').text('Edit Selection');
jQuery('#fg_removeall').addClass('visible');
}
});
// Finally, open the modal
file_frame.open();
});
The main thing here I'm having difficulty with now is that I can't get it to open to gallery-edit with a selection. I can get it to open there, but there are no images selected. I'm looking into that. I'm also looking into re-opening instead of creating a new view and sending a pre-selection. If I go to the selection window, then the order window, but click the X to close, I can re-open to the order window. So there should be a way.
EDIT 4
As per code from answer below, I've changed the pre-selection code to:
file_frame.on('open', function() {
var library = file_frame.state().get('library');
var ids = jQuery('#fg_perm_metadata').val();
if (ids) {
idsArray = ids.split(',');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
library.add( attachment ? [ attachment ] : [] );
});
}
});
This allows me to re-open directly to the gallery-edit state and have images pre-selected. However, when I open directly to this state, I cannot click Cancel Gallery (return to image selection state). Clicking that button/link just closes the frame. I tried pre-filling both the library and the selection, but that doesn't work either. The following is from media-views.js, and seems to be what controls that button. Instead of changing the state to a specific state, it changes it to the previous state. Since we are opening directly to gallery-edit, there is no past state. I'm wondering if it's possible to open to gallery, and then on open, change to gallery-edit. Do it instantly so that the user doesn't see, but so that it gets the past state into the system.
galleryMenu: function( view ) {
var lastState = this.lastState(),
previous = lastState && lastState.id,
frame = this;
EDIT 5:
Finally figured it all out. I couldn't get the above to work at all, I'm not sure why. So, there may be a better way to do this, involving that code. If so, I'd love to know.
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
var library = file_frame.state('gallery-edit').get('library');
var ids = jQuery('#fg_perm_metadata').val();
if (ids) {
idsArray = ids.split(',');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
file_frame.setState('gallery-edit');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
library.add( attachment ? [ attachment ] : [] );
});
}
});
FINAL EDIT
My code is now working entirely, and I appreciate the help! If you'd like to see it in action, check out http://wordpress.org/plugins/featured-galleries/
I'm relatively new to WP. In fact, I'm building my first WP theme and I'm stuck on the same question as you. Thank to your code, I can get to the Gallery page. And luckily, I've got the images saved. Here's my code:
// when click Insert Gallery, run callback
wp_media_frame.on('update', function(){
var library = wp_media_frame.state().get('library');
var images = [];
var image_ids = [];
thumb_wraper.html('');
library.map( function( image ) {
image = image.toJSON();
images.push(image.url);
image_ids.push(image.id);
thumb_wraper.append('<img src="' + image.url + '" alt="" />');
});
});
What I have found is you should get 'library' instead of get 'selection'.
Edit:
I've figured out how to go back to gallery-edit. Here is my full code:
$( '#btn_upload' ).on( 'click', function( event ) {
event.preventDefault();
var images = $( '#image_ids' ).val();
var gallery_state = images ? 'gallery-edit' : 'gallery-library';
// create new media frame
// You have to create new frame every time to control the Library state as well as selected images
var wp_media_frame = wp.media.frames.wp_media_frame = wp.media( {
title: 'My Gallery', // it has no effect but I really want to change the title
frame: "post",
toolbar: 'main-gallery',
state: gallery_state,
library: {
type: 'image'
},
multiple: true
} );
// when open media frame, add the selected image to Gallery
wp_media_frame.on( 'open', function() {
var images = $( '#image_ids' ).val();
if ( !images )
return;
var image_ids = images.split( ',' );
var library = wp_media_frame.state().get( 'library' );
image_ids.forEach( function( id ) {
attachment = wp.media.attachment( id );
attachment.fetch();
library.add( attachment ? [ attachment ] : [] );
} );
} );
// when click Insert Gallery, run callback
wp_media_frame.on( 'update', function() {
var thumb_wrapper = $( '#thumb-wrapper' );
thumb_wraper.html( '' );
var image_urls = [];
var image_ids = [];
var library = wp_media_frame.state().get( 'library' );
library.map( function( image ) {
image = image.toJSON();
image_urls.push( image.url );
image_ids.push( image.id );
thumb_wrapper.append( '<img src="' + image.url + '" alt="" />' );
} );
} );
} );
I figured that if you re-open the existed frame, it'll always keep the initial state, in your case it's 'gallery'. You'll have to create new frame every time and check if there's images to open 'gallery-edit'
Also, I prefer 'gallery-library' than 'gallery' because I want user to focus on my gallery.
I'm stuck on making CKEditor inline editing work on jQuery UI, especially on Tabs. Does anyone know how to make it work? Are there any plugins that will make CKEditor work on jQuery UI?
I had a similar issue and it turned out to be due to how the browsers were handling the "hidden" or "disabled" components which had yet to be rendered.
http://ckeditor.com/ticket/9814 gave a example of adding a listener to change the readOnly status when the instance becomes ready.
var ck = CKEDITOR.inline(element);
ck.on( 'instanceReady', function( ev ) {
var editor = ev.editor;
editor.setReadOnly( false );
});
I've been struggling with the same problem since this morning, but I found a fix.
var objCKeditor = new Object({
config: base_url + "library/applications/ckeditor/config.simple.js"
});
var objTab = new Object({
active: false
});
CKEDITOR.disableAutoInline = true;
// Activate your editors when the tabs themselves are activated.
$( ".navigation-tabs" ).on( "tabsactivate", function( event, ui ) {
// Find which tab has been chosen by the user.
objTab.chosen = $(this).tabs('option', 'active');
// Only initialize the editors once...
if ( (objTab.chosen == 3) && (objTab.active == false) ) {
// Loop through the editors.
$( 'div.link-bookmark-comment').each( function() {
// Find the ID for the editor.
objCKeditor.editor = $(this).attr('id');
// ... which is facilitated by this boolean.
objTab.active = true;
CKEDITOR.inline( objCKeditor.editor, { customConfig: objCKeditor.config } );
});
}
} );
So, it would appear that CKEditor does not like to be placed within tabs, or any object which is initially hidden.