Unsing clipboard, I try to copy a html text, but the copy is correct without the html code.
I have 2 button, one for the plain text, one for the html code (copy image link)
Do you have any idea where is the problem ?
Html code
<div id="Area-output" class="text-bg-light"></div>
<button id="copyResultButton" class="btn btn-primary d-none" data-clipboard-target="#Area-output">
<i class="bi bi-clipboard" title="Copy Result"></i> Copy Result
</button>
<button id="copyHTMLButton" class="btn btn-primary d-none" data-clipboard-target="#Area-output" data-clipboard-action="copy">
<i class="bi bi-code" title="Copy HTML"></i> Copy HTML
</button>
Now the javascript code
$(document).ready(function() {
// Initialize the clipboard for result button
var clipboardResult = new ClipboardJS("#copyResultButton");
// Handler for when the result button is clicked
clipboardResult.on("success", function(e) {
// Show a tooltip indicating that the text was copied
$(e.trigger).tooltip({title: "Copied!", placement: "bottom", trigger: "manual"}).tooltip("show");
setTimeout(function() {
$(e.trigger).tooltip("hide");
}, 1000);
e.clearSelection();
});
// Initialize the clipboard for HTML button
var clipboardHTML = new ClipboardJS("#copyHTMLButton", {
text: function() {
return $("#Area-output").html();
}
});
// Handler for when the HTML button is clicked
clipboardHTML.on("success", function(e) {
// Show a tooltip indicating that the HTML was copied
$(e.trigger).tooltip({title: "Copied HTML!", placement: "bottom", trigger: "manual"}).tooltip("show");
setTimeout(function() {
$(e.trigger).tooltip("hide");
}, 1000);
e.clearSelection();
});
$("#send").click(function() {
let message = $("#message").val();
let engine = $("#engine").val();
let save = $("#save").val();
$.post("' . $url . '", {message: message, engine: engine, save: save}, function(data) {
$("#Area-output").html(data);
// Show the copy buttons after the chat message is generated
$("#copyResultButton, #copyHTMLButton").removeClass("d-none");
});
});
});
Related
What I am trying to do is have a modal form which contains a file input along with various other form fields, then, once the modal form is submitted, the file input, as well as other form elements, are then moved to the main form I want to eventually submit and I then reset the form and replace the original file input with a clone of the original in order to accept further entries.
Everything works perfectly fine except that the html 5 image preview doesn't work on any cloned file inputs, so it only works on the original file input that's present on page load and not any subsequent inputs.
I've tried changing the event handler as well as recalling handleImages once the clone is added to the DOM but neither seemed to make a difference and I can't think of what to try next.
I've made a codpen and the code is also below:
HTML
<div class="container">
<form action="" class="form-inline" id="image-form">
<label class="btn btn-info upload-button">
Tap to Select Images
<input type="file" style="display: none" multiple accept="image/*" capture="camera">
</label>
<button type="button" class="btn btn-primary" id="save-image">Save Images</button>
<div class="preview">
<div class="row">
</div>
</div>
</form>
<div id="saved-images" style="display: none;"></div>
</div>
JS
var imageCount = 0;
var ImageUpload = function() {
var handleImages = function() {
document.querySelector('#image-form input[type="file"]').addEventListener('change', handleFileSelect, false);
// also tried
// $(document).on('change', '#image-form input[type="file"]', handleFileSelect);
}
var handleFileSelect = function(e) {
if ( !e.target.files || !window.FileReader) return;
var $element = $(e.srcElement).closest('form').find('.preview > .row');
$element.empty();
var $srcElement = $(e.srcElement);
var files = e.target.files;
var filesArr = Array.prototype.slice.call(files);
filesArr.forEach(function(f) {
if (!f.type.match("image.*")) {
return;
}
var reader = new FileReader();
reader.onload = function(e) {
var html = `
<div class="col-lg-3 col-md-4 col-xs-6 thumbnail m-t m-b m-r m-l">
<img class="img-responsive" src="${e.target.result}" alt="${f.name}">
<div class="title bg-success">${f.name}</div>
</div>
`;
$element.append(html);
}
reader.readAsDataURL(f);
});
}
var handleSaveImage = function() {
$(document).on('click', '#save-image', function(f) {
// Clone the "real" input element
var $real = $('#image-form input[type="file"]');
var $clone = $real.clone(true);
/* Also tried:
var $clone = $real.clone(false);
handleImages();
and
var $clone = $real.clone(true).val('');
*/
// Put the cloned element directly after the real element
$clone.insertAfter($real);
// change the name and class of the real input
$real.addClass(`image-${imageCount}`);
// Move the real element
$real.appendTo('#saved-images');
imageCount++;
resetImageForm();
});
}
var resetImageForm = function() {
$('#image-form').trigger('reset');
$('#image-form .preview').empty();
}
return {
// main function to initiate the module
init: function() {
handleImages();
handleSaveImage();
}
};
}();
jQuery(document).ready(function() {
ImageUpload.init();
});
If I change the event listener to $(document).on('change', '#image-form input[type="file"]', handleFileSelect); then the preview code is reached every time but there's no preview, here's a forked version to show what I mean enter link description here
I seen your code and here is solution
jsfiddle
use $(e.target) instead of $(e.srcElement)
I'be been using modals as a means to communicate to users in my apps for some time now via several different front end frameworks. The logic is usually the same, defining the modal's html then rendering it via some click event.
As my applications grow, so do the number of modals I use for a user prompt or confirmation - these modals can have anything from text inputs to forms to dropdowns and so on.
My current method is to write out each separate modal in a single html file and simply call them by their IDs but I feel this is inefficient as there is plenty of duplicate boilerplate code, so I'm wondering the best way would be to create modals dynamically while keeping the code as light andclean as possible?
I've been thinking of something like a "modal factory" where you pass the content of the modal along with the height, width, styling, etc. would this be a good approach?
Thanks for any input!
Well what I do for Forms/HTML Content loaded from the server - is create a div with an ID - PartialViewDialog at the end of my page -(I load Partial Views inside a Dialog)
This one is Bootstrap 3.* based - (HTML structure based on Frontend framework
So the HTML is like this:
<body>
<!-- Other page content -->
<div class="modal fade" id="PartialViewDialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" data-modal="title"></h4>
</div>
<div class="modal-body" data-modal="content">
</div>
<div class="modal-footer" data-modal="footer">
</div>
</div>
</div>
</div>
</body>
Then in JS, I create a dialog Manager:
var MyApp = MyApp || {};
MyApp.UIHelper = MyApp.UIHelper || {};
MyApp.UIHelper.DialogManager = (function () {
"use strict";
var self = {};
self.divId = null;
self.dialog = null;
self.dialogBody = null;
self.dialogTitle = null;
self.dialogFooter = null;
self.actionUrl = "";
self.modalObject = null;
self.options = {};
function Initilize(divId, options) {
self.options = $.extend({ buttons: [] }, options);
self.divId = divId;
self.dialog = $(self.divId);
self.dialogBody = self.dialog.find('*[data-modal="content"]');
self.dialogTitle = self.dialog.find('*[data-modal="title"]');
self.dialogFooter = self.dialog.find('*[data-modal="footer"]');
self.BootgridObject = null;
};
function OpenPartialViewDialog(url, title, preprocessingFunction, postProcessingFunction) {
// Create the buttons
var options = self.GetPartialViewButtons(url, preprocessingFunction, postProcessingFunction);
// Initialise the PartialViewDialog with Buttons
Initilize('#PartialViewDialog', options);
// Set the URL for Ajax content load and Form Post
self.actionUrl = url;
// Set Dialog Title
self.dialogTitle.html(title);
// Open the PartialViewDialog
self.OpenModel();
};
// This Method creates the buttons for the Form dialog
// e.g Save, Cancel, Ok buttons
self.GetPartialViewButtons = function (url, preprocessingFunction, postProcessingFunction) {
// I only need Save and Cancel buttons always so I create them here
var buttons = {
buttons: {
// I create a save button which Posts back the Form in the Dialog
Save: {
Text: "Save",
css: "btn btn-success",
click: function () {
// Call a function before sending the Ajax request to submit form
if (preprocessingFunction) { preprocessingFunction(); }
$.ajax({
type: "POST",
url: url,
// This Dialog has a Form - which is Post back to server
data: self.dialogBody.find("form").serialize(),
success: function (response) {
// TODO: Check if response is success -
// Apply your own logic here
if (response.hasOwnProperty("IsSuccess")) {
if (response.IsSuccess) {
self.dialogBody.html("");
self.dialog.modal("hide");
// TODO: Show Success Message
// You can call another function if you want
if (postProcessingFunction) {
postProcessingFunction();
}
} else {
// If failure show Error Message
}
}
},
error: function (response) {
// If failure show Error Message
}
});
}
},
Cancel: {
Text: "Cancel",
css: "btn btn-danger",
click: function () {
self.dialogBody.html("");
self.dialogFooter.html("");
self.dialogTitle.html("");
self.dialog.modal("hide");
}
}
}
};
return buttons;
};
// dynamic creating the button objects
self.CreateButtonsHtml = function () {
var htmlButtons = [];
$.each(self.options.buttons, function (name, props) {
var tempBtn = $("<button/>", {
text: props.Text,
id: "btn_" + props.Text,
"class": props.css + "",
click: props.click
}).attr({ "style": "margin-right: 5px;" });
htmlButtons.push(tempBtn);
});
return htmlButtons;
};
// This method will load the content/form from server and assign the modal body - it will assign the buttons to the Modal Footer and Open the Dialog for user
self.OpenModel = function () {
$.ajax({
url: self.actionUrl,
type: "GET",
success: function (response) {
// Handle response from server -
// I send JSON object if there is Error in loading the content - otherwise the result is HTML
if (response.hasOwnProperty("HasErrors")) {
// Means some error has occured loading the content - you will have to apply your own logic
} else {
//Server return HTML - assign to the modal body HTML
self.dialogBody.html(response);
self.modalObject = self.dialog.modal();
// show modal
self.modalObject.show();
}
}
});
// Create the buttons in the Dialog footer
var buttons = self.CreateButtonsHtml();
self.dialogFooter.html('');
for (var i = 0; i < buttons.length; i++) {
self.dialogFooter.append(buttons[i]);
}
};
return {
OpenPartialViewDialog: OpenPartialViewDialog,
};
})();
Then whenever I need to open a dialog from the server I can call it like this:
MyApp.UIHelper.DialogManager
.OpenPartialViewDialog('/Content/Load', "My Title",
function(){alert('pre-process')},
function(){alert('post-process')}
);
Note: The PreProcess + PostProcess are called when the Save button is clicked
Here is a working/demo example which shows what the above JS does - Hope it helps
In the demo I load Dummy HTML from a div id="dummycontent"
Fiddle: https://jsfiddle.net/1L0eLazf/
Button Fiddle: https://jsfiddle.net/1L0eLazf/1/
I would like to show an error message AFTER a user clicks on a save button. The field that they need to complete is a URL link and it must be a valid url.. I have a working regex in place, I just have no clue how this is supposed to be done as I am very new to angular.
Here is what I have so far:
<div class="form-group">
<button type="button" class="btn btn-primary btn-block btn-lg"
ng-click="save()">
<spring:message code="journalist.social.submit.label"/>
<span class="glyphicon glyphicon-chevron-right"</span>
</button>
<span style="color: #d2232a;padding-left: 0px" class="btn"
ng-show="!canSave()">
<spring:message code="journalist.info.error.fill.all"/>
</span>
And in my scripts (The save button only works if the canSave function is true):
$scope.save = function () {
var res = [];
var files = [];
var ind = 0;
if ($scope.canSave()){ //save button should only work if the URL is valid
$scope.linkList.forEach(function (clip) {
if (!clip.link) {
return;
}
if (!CommonUtils.startsWithHttp(clip.link)) {
clip.link = CommonUtils.EMPTY_LINK + clip.link;
}
if (clip.imgData && clip.imgData.input) {
files.push({id: ind, file: clip.imgData.input, cropData: clip.imgData.cropData})
clip.logos = undefined;
}
ind = ind + 1;
res.push({
id: clip.id,
title: clip.title,
description: clip.description,
name: clip.name,
link: clip.link,
ordering: ind,
logoUrl: clip.logos ? clip.logos[clip.logoInd] : null
})
});
Journalist.updateClips(
files,
res,
$scope,
function (e) {
$scope.warningOnLocationChange = false;
Navigation.open($scope, ["journalist", "profile", "profile"]);
}
);
};
$scope.showUpload = function (clip) {
if(clip.link) {
clip.showUpload = true;
}
};
}}]
);
If you think the condition I have in my script for the save() function is not right then by all means tell me otherwise. How can I show an alert after the button is clicked? The alert shows before a URL is even entered (or as they are typing and will go away once the url is correct.) Thanks!
I included a calendar in my project using fullcalendar.js. My database entries are showing up but they are one month ahead.
If I enter something for 16.octobre.2015, it will be saved in the database as 16.octobre.2015 but will be displayed as 16.novembre.2015. This happens with every single one of my entries.
I searched a lot here on Stack Overflow and found a few similar topics. In one, someone explained that this has something to do with how months are indexed.
PHP counts from 1 to 12.
JavaScript counts from 0 to 11.
I guess that maybe this is my problem?
Can someone tell me what I need to change, so that my entries show correctly? Here is my code:
<!-- inline scripts related to this page -->
<script type="text/javascript">
jQuery(function($) {
/* initialize the external events
-----------------------------------------------------------------*/
$('#external-events div.external-event').each(function() {
// create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
// it doesn't need to have a start or end
var eventObject = {
title: $.trim($(this).text()) // use the element's text as the event title
};
// store the Event Object in the DOM element so we can get to it later
$(this).data('eventObject', eventObject);
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
/* initialize the calendar
-----------------------------------------------------------------*/
<?php
print "var date = new Date();\n";
print "var d = date.getDate();\n";
print "var m = date.getMonth();\n";
print "var y = date.getFullYear();\n";
print "var unixTimestamp = Date.now(); // in milliseconds;"
?>
var calendar = $('#calendar').fullCalendar({
//isRTL: true,
buttonHtml: {
prev: '<i class="ace-icon fa fa-chevron-left"></i>',
next: '<i class="ace-icon fa fa-chevron-right"></i>'
},
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
<?php
$dates=getPcalInfoOfHour($gl_userid,0,0);
print "events: [\n";
for ($x=0;$x<count($dates["id"]);$x++) {
print " {\n";
print " title: '".$dates["title"][$x]."',\n";
print " start: new Date(".date("Y",$dates["start"][$x]).", ".date("n",$dates["start"][$x]).", ".date("j",$dates["start"][$x]).", ".date("G",$dates["start"][$x]).", ".date("i",$dates["start"][$x]).",0,0),\n";
print " end: new Date(".date("Y",$dates["end"][$x]+1).", ".date("n",$dates["end"][$x]+1).", ".date("j",$dates["end"][$x]+1).", ".date("G",$dates["end"][$x]+1).", ".date("i",($dates["end"][$x]+1)).",0,0),\n";
print " allDay: false,\n";
print " className: 'label-info'\n";
if ($x<(count($dates["id"])-1)) {
print " },\n";
} else {
print " }\n";
}
}
print "]\n";
?>
,
editable: true,
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function(date, allDay) { // this function is called when something is dropped
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
var $extraEventClass = $(this).attr('data-class');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
if($extraEventClass) copiedEventObject['className'] = [$extraEventClass];
// render the event on the calendar
// the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
}
,
selectable: true,
selectHelper: true,
select: function(start, end, allDay) {
calendar.fullCalendar('unselect');
}
,
eventClick: function(calEvent, jsEvent, view) {
//display a modal
var modal =
'<div class="modal fade">\
<div class="modal-dialog">\
<div class="modal-content">\
<div class="modal-body">\
<button type="button" class="close" data-dismiss="modal" style="margin-top:-10px;">×</button>\
<form class="no-margin">\
<label>Title </label>\
<label>$dates["title"][0]</label>\
<button type="submit" class="btn btn-sm btn-success"><i class="ace-icon fa fa-check"></i> Save</button>\
</form>\
</div>\
<div class="modal-footer">\
<button type="button" class="btn btn-sm btn-danger" data-action="delete"><i class="ace-icon fa fa-trash-o"></i> Delete Event</button>\
<button type="button" class="btn btn-sm" data-dismiss="modal"><i class="ace-icon fa fa-times"></i> Cancel</button>\
</div>\
</div>\
</div>\
</div>';
var modal = $(modal).appendTo('body');
modal.find('form').on('submit', function(ev){
ev.preventDefault();
calEvent.title = $(this).find("input[type=text]").val();
calendar.fullCalendar('updateEvent', calEvent);
modal.modal("hide");
});
modal.find('button[data-action=delete]').on('click', function() {
calendar.fullCalendar('removeEvents' , function(ev){
return (ev._id == calEvent._id);
})
modal.modal("hide");
});
modal.modal('show').on('hidden', function(){
modal.remove();
});
console.log(calEvent.id);
console.log(jsEvent);
console.log(view);
// change the border color just for fun
//$(this).css('border-color', 'red');
}
});
})
</script>
The answer is literally in the question. I'll just quote you:
I searched a lot here on Stack Overflow and found a few similar topics. In one, someone explained that this has something to do with how months are indexed.
PHP counts from 1 to 12.
JavaScript counts from 0 to 11.
I guess that maybe this is my problem?
Yes. If you need a finger pointed in the right direction, let's take this part of your code:
print " start: new Date(".date("Y",$dates["start"][$x]).", ".date("n",$dates["start"][$x]).", ".date("j",$dates["start"][$x]).", ".date("G",$dates["start"][$x]).", ".date("i",$dates["start"][$x]).",0,0),\n";
print " end: new Date(".date("Y",$dates["end"][$x]+1).", ".date("n",$dates["end"][$x]+1).", ".date("j",$dates["end"][$x]+1).", ".date("G",$dates["end"][$x]+1).", ".date("i",($dates["end"][$x]+1)).",0,0),\n";
More precisely this:
date("n", $dates["start"][$x])
date("n", $dates["end"][$x]+1)
Simply subtract one from the month value:
(date("n", $dates["start"][$x]) - 1)
(date("n", $dates["end"][$x]+1) - 1)
Do this everytime you output a PHP month value in a JavaScript source.
Even better, you could just use the timestamps directly (remember that JavaScript uses milliseconds):
print " start: new Date(".($dates["start"][$x] * 1000)."),\n";
print " end: new Date(".(($dates["end"][$x]+1) * 1000)."),\n";
I try to add the multi uploading options in the wordpress plugins I repeated this code in the plugin(two times) only changing the id name.
<script language="JavaScript">
jQuery(document).ready(function($) {
jQuery('#upload_image_button').click(function() {
formfield = jQuery('#upload_image').attr('name');
tb_show('', 'media-upload.php?type=image&TB_iframe=true');
return false;
});
window.send_to_editor = function(html) {
imgurl = jQuery('img', html).attr('src');
jQuery('#upload_image').val(imgurl);
tb_remove();
};
});
</script>
<input id="upload_image" style=" margin-left:303px;" type="text" size="36" name="upload_image_template" value="<?php echo get_option('upload_image_template'); ?>" />
<input id="upload_image_button" type="button" value="Browse" />
Whenever I try to upload a image that media frame comes and the uploading process are did successfully. But Insert Into Post fetch the correct url but pasted in different input box.
For example:
1) [text box1] [browse Button]
2) [text box2] [browse button]
When I upload image with Text Box One that [insert post] that image path is shown in [text box 2]
I am Not Sure Whether the Problem is mine or that script didn't support multi file upload option.
Here is the example how you can use the wordpress multimedia uploader for more than one field or as many fields. The JS code and html code looks like this
How it works
Add upload_image_button class on each upload button on the basis of this class click function triggers to fetch the wordpress multimedia uploader , see i have used the prev() property to get the previous element to the clicked one formfieldID=jQuery(this).prev().attr("id"); and then i have assigned the image url returned by uploader to formfieldID
<input id="upload_image1" type="text" name="upload_image1" value="<?php echo $upload_image1;?>" />
<input class="upload_image_button" type="button" value="Upload image 1" />
<input id="upload_image2" type="text" name="upload_image2" value="<?php echo $upload_image2;?>" />
<input class="upload_image_button" type="button" value="Upload image 2" />
<script type="text/javascript">
//tb_show('', 'media-upload.php?TB_iframe=true');
var upload_image_button=false;
jQuery(document).ready(function() {
jQuery('.upload_image_button').click(function() {
upload_image_button =true;
formfieldID=jQuery(this).prev().attr("id");
formfield = jQuery("#"+formfieldID).attr('name');
tb_show('', 'media-upload.php?type=image&TB_iframe=true');
if(upload_image_button==true){
var oldFunc = window.send_to_editor;
window.send_to_editor = function(html) {
imgurl = jQuery('img', html).attr('src');
jQuery("#"+formfieldID).val(imgurl);
tb_remove();
window.send_to_editor = oldFunc;
}
}
upload_image_button=false;
});
})
</script>
Also make sure you have included the necessary JS and CSS files of the uploader for this you have to add an action
<?php
function my_admin_uploader_scripts() {
wp_enqueue_script('media-upload');
wp_enqueue_script('thickbox');
wp_register_script('my-upload', WP_PLUGIN_URL.'/my-script.js', array('jquery','media-upload','thickbox'));
wp_enqueue_script('my-upload');
}
function my_admin_uploader_styles() {
wp_enqueue_style('thickbox');
}
add_action('admin_print_scripts', 'my_admin_uploader_scripts');
add_action('admin_print_styles', 'my_admin_uploader_styles');
?>
Note: Also take care of one thing when you assign the uploader to
you input fields the control of uploader now assigns to the fields so
when ever uploader will be called it assigns the image url to your
text field , so this is the problem when you triggers the uploader you
are unable to insert the images in the content area of the post for
this solution you have to store the previous control in some where and
when you are done with uploader then reassign the control of uploader
to the previous function which i have provided in my JS code see below
how it works
var oldFunc = window.send_to_editor;
window.send_to_editor = function(html) {
imgurl = jQuery('img', html).attr('src');
jQuery("#"+formfieldID).val(imgurl);
tb_remove();
window.send_to_editor = oldFunc;
}
I have used this technique many times and it works perfect for me
Hope it makes sense
Here, for the edit image to work, also to show other filter, hope it helps.
pa_uploader = wp.media({
title: 'Choose Images',
multiple: true,
//frame: 'select',
library: {
filterable: 'all',
editable: true,
contentUserSetting: false
},
states: [
new wp.media.controller.Library({
id: 'library',
title: 'Select Images',
priority: 40,
// toolbar: 'gallery',
filterable: 'all',
multiple: 'add',
editable: true,
contentUserSetting: false,
library: wp.media.query( _.defaults({
type: 'image'
}, {} ) )
}),
new wp.media.controller.EditImage({model: {}})
]
});
// pa_uploader.states.add([
// new wp.media.controller.EditImage({model: {}})
// ]);
pa_uploader.on('content:render:edit-image', function() {
var controller = pa_uploader.modal.controller;
image = pa_uploader.state().get('image'),
view = new wp.media.view.EditImage( { model: image, controller: controller } ).render();
pa_uploader.content.set( view );
// after creating the wrapper view, load the actual editor via an ajax call
view.loadEditor();
});
pa_uploader.on('select', function(e){
// This will return the selected image from the Media Uploader, the result is an object
var selected_images = pa_uploader.state().get('selection');
});
});
});
The answer from M Khalid Junaid is great but outdated.
See the codex page about wp.media : https://codex.wordpress.org/Javascript_Reference/wp.media.
Here is my code based on Codex wp.media Example
Javascript
var sfieldGroup= '.field-group'; // top level parent
var wpMediaUploader = {
sBtnAdd : ".upload-custom-wp-media",
sBtnRemove : ".remove-custom-wp-media",
sMediaData: ".media-data",
sInput : ".custom-wp-media"
};
function wpMedia() {
$(wpMediaUploader.sBtnAdd).on("click", function (event) {
event.preventDefault();
var self = $(this);
var fieldGroup = self.parents(sfieldGroup);
// Create a new media frame
var 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
});
frame.on("select", function () {
var attachment = frame.state().get("selection").first().toJSON();
switch(attachment.mime){
case "image/jpeg" :
case "image/png" :
case "image/bmp" :
case "image/gif" :
fieldGroup.find(wpMediaUploader.sMediaData)
.append("<img src=\"" + attachment.url + "\" alt=\"\" />");
break;
}
$("<p/>",{
text: attachment.filename
}).appendTo(fieldGroup.find(wpMediaUploader.sMediaData));
fieldGroup.find(wpMediaUploader.sInput).val(attachment.id);
fieldGroup.find(wpMediaUploader.sBtnAdd).addClass("hidden");
fieldGroup.find(wpMediaUploader.sBtnRemove).removeClass("hidden");
frame.close();
});
frame.open();
});
$(wpMediaUploader.sBtnRemove).on("click", function (event) {
event.preventDefault();
var self = $(this);
var fieldGroup = self.parents(sfieldGroup);
// Clear out the preview image
fieldGroup.find(wpMediaUploader.sMediaData).html("");
// Un-hide the add image link
fieldGroup.find(wpMediaUploader.sBtnAdd).removeClass("hidden");
// Hide the delete image link
fieldGroup.find(wpMediaUploader.sBtnRemove).addClass("hidden");
// Delete the image id from the hidden input
fieldGroup.find(wpMediaUploader.sInput).val("");
});
}
HTML
<div class="field-group">
<div class="media-data"></div>
<p class="hide-if-no-js">
<a class="button upload-custom-wp-media" href="javascript:void(0)">Upload Media</a>
<a class="button remove-custom-wp-media hidden" href="javascript:void(0)">Remove Selected Media</a>
</p>
<input id="test" name="test" class="custom-wp-media" value="" type="hidden">
</div>
Tip
if you console.log frame,you will be exposed to API :)
var 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
});
It wasn't that hard...
See this revision history to see how I did...
Basically what I did was adding this to my plugin:
function wp_gear_manager_admin_scripts() {
wp_enqueue_script('media-upload');
wp_enqueue_script('thickbox');
wp_enqueue_script('jquery');
}
function wp_gear_manager_admin_styles() {
wp_enqueue_style('thickbox');
}
add_action('admin_print_scripts', 'wp_gear_manager_admin_scripts');
add_action('admin_print_styles', 'wp_gear_manager_admin_styles');
And later this part in my JavaScript file:
<script language="JavaScript">
jQuery(document).ready(function() {
jQuery('#upload_image_button').click(function() {
formfield = jQuery('#upload_image').attr('name');
tb_show('', 'media-upload.php?type=image&TB_iframe=true');
return false;
});
window.send_to_editor = function(html) {
imgurl = jQuery('img',html).attr('src');
jQuery('#upload_image').val(imgurl);
tb_remove();
}
});
</script>
And this in my html:
<tr valign="top">
<td>Upload Image</td>
<td><label for="upload_image">
<input id="upload_image" type="text" size="36" name="upload_image" value="<?php echo $gearimage; ?>" />
<input id="upload_image_button" type="button" value="Upload Image" />
<br />Enter an URL or upload an image for the banner.
</label>
</td>
</tr>
You can just copy and paste this code to your plugin and see the magic.