How can I use Multi Media Uploader in the WordPress Plugins? - javascript

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.

Related

Ajax search doesn't work the second time (ASP.NET MVC)

I have a problem changing items after searching.
I looked at similar threads but found no solution there :(
It looks like the first time the page loads well - the first time the entire Index.cshtml page is loaded which contains a collection of books in the selected category.
There is a search engine on the page - after searching for "manual" - ajax correctly replaces elements with those containing "manual" in the name.
Then when I enter something into the search engine a second time (for example "exercises") - the content of the page does not change any more.
I tried to debug and I see that new items are correctly downloaded from the database - the condition "if (Request.IsAjaxRequest ())" is true and the items are passed to partial view - there the "foreach" loop goes through them. Unfortunately, after _Partial, nothing happens.
I can't find a mistake - the strangest thing is that the first ajax call works fine - only the second (and subsequent) bad.
CatalogController.cs
public ActionResult Index(string categoryName = null, string searchQuery = null)
{
if (categoryName == null)
categoryName = (db.Categories.Find(1)).Name;
var category = db.Categories.Include("Books").Where(x => x.Name.ToLower() == categoryName).Single();
var books = category.Books.Where(x => (searchQuery == null || x.Title.ToLower().Contains(searchQuery.ToLower()) || x.SubTitle.ToLower().Contains(searchQuery.ToLower()) || x.Level.ToLower().Contains(searchQuery.ToLower())) && !x.Inaccessible);
if (Request.IsAjaxRequest())
return PartialView("_PartialBooksList", books);
else
return View(books);
}
Index.cshtml
<form class="o-search-form" id="search-form" method="get" data-ajax="true" data-ajax-target="#booksList">
<input class="o-search-input" id="search-filter" type="search" name="searchQuery" data-autocomplete-source="#Url.Action("SearchTips")" placeholder="Search" />
<input class="o-search-submit" type="submit" value="" />
</form>
<div class="row" id="booksList">
#Html.Partial("_PartialBooksList")
</div>
#section Scripts
{
<script src="~/Scripts/jquery-3.5.0.js"></script>
<script src="~/Scripts/jquery-ui-1.12.1.js"></script>
<script>
$(function () {
var setupAutoComplete = function () {
var $input = $(this);
var options =
{
source: $input.attr("data-autocomplete-source"),
select: function (event, ui) {
$input = $(this);
$input.val(ui.item.label);
var $form = $input.parents("form:first");
$form.submit();
}
};
$input.autocomplete(options);
};
var ajaxSubmit = function () {
var $form = $(this);
var settings = {
data: $(this).serialize(),
url: $(this).attr("action"),
type: $(this).attr("method")
};
$.ajax(settings).done(function (result) {
var $targetElement = $($form.data("ajax-target"));
var $newContent = $(result);
$($targetElement).replaceWith($newContent);
$newContent.effect("slide");
});
return false;
};
$("#search-filter").each(setupAutoComplete);
$("#search-form").submit(ajaxSubmit);
});
</script>
}
_PartialBooksList
#model IEnumerable<ImpressDev.Models.Book>
#using ImpressDev.Infrastructure
<div class="row">
#foreach (var book in Model)
{
<div class="col-12 col-xl-4">
<a class="o-shop-link" href="#Url.Action("Details", "Catalog", new { bookId = book.BookId })">
<div class="o-shop-item">
<img class="o-shop-img" src="#Url.BookPhotoSourcePath(book.PhotoSource)" />
<div class="o-shop-text">
<h2>#book.Title</h2>
<h6>#book.SubTitle - #book.Level - <b>#book.Price zł.</b></h6>
+ Add to cart
</div>
</div>
</a>
</div>
}
</div>
Please help
I am not sure if this is the case, but try to change this code:
$($targetElement).replaceWith($newContent);
To this:
$($targetElement).html($newContent);
I think the problem is the div element with id="booksList" is replaced after first search. So you don't have this element in the second search.
I looked through the code step by step and found a solution to my problem.
In the first search, replace id="booksList"
<div class="row" id="booksList">
#Html.Partial("_PartialBooksList")
</div>
partial view in which there was only without id = booksLists.
In the next search there was no ID in this place and there was nothing to replace.

use dropzone.options without form

I want to use dropzone on with id. But my Dropzone.options.myid={}
is not working. How to validate file type, size in
var myDropzone = new Dropzone("div#myid", { url: "/file/post"});
I cant use tag
console.log file is not working why?
My source:
<div id="myid" style="width: 500px; height: 300px; border: 1px solid black">click here</div>
javascript
var myDropzone = new Dropzone("div#myid", { url: "dropzoneupload"});
Dropzone.options.myid = {
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 2, // MB
accept: function(file, done) {
console.log(file);
if (file.name == "justinbieber.jpg") {
done("Naha, you don't.");
}
else { done(); }
}
};
I don't see where are you using dropzone class to define your dropzone area, does it generate you the default dropzone?
<div id="myDropZone" class="fallback dropzone" enctype="multipart/form-data">
<input type="file" id="files" class="display" multiple />
</div>
First you need to detach the default dropzone, add this out of you document ready load.
Dropzone.autoDiscover = false;
Then you jquery or js
var $myDropZone;
$myDropZone= new Dropzone('div#myDropZone', {*all your settings*
addRemoveLinks: true, //to remove
dictRemoveFile: '<i class="fa fa-times-circle" style="font-weight: 900;
cursor:pointer;"></i>' //I used an icon and styled as button so to give a user
experience to remove it});
Hope it helps, regards.

HTML5 Image Preview Not Working On Cloned File Input (Does on Original)

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)

Google recaptcha callback not working with multiple reCAPTCHA

I have multiple google captchas on page. Code:
<script>
var qqqq =function(captcha_response){
console.log('?')
}
var CaptchaCallback = function(){
$('.g-recaptcha').each(function(index, el) {
grecaptcha.render(el, {'sitekey' : '{{ recaptcha_key}}', 'callback': 'qqqq', 'theme': 'dark'});
});
};
</script>
<script src='https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit' async defer></script>
On the page there are several blocks for reCAPTCHA:
<div class="g-recaptcha"></div>
All reCAPTCHA's render well, all with dark theme, all do verifying work, but the callback function does not get called.
When I tried single reCAPTCHA with data-callback attribute, it worked well.
I was facing the same issue. After checking the documentation again I found my problem. Try to remove the single quotation marks around your function name.
Like this:
<script>
var qqqq =function(captcha_response){
console.log('?')
}
var CaptchaCallback = function(){
$('.g-recaptcha').each(function(index, el) {
grecaptcha.render(el, {'sitekey' : '{{ recaptcha_key}}', 'callback': qqqq });
});
};
</script>
Maybe this helps someone else as well :)
Steps to implement multimple recaptcha with a callback method for disable the submit button
1) Add the reference
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
2) Add the Code that will render the captcha widget
<script>
var CaptchaCallback = function () {
grecaptcha.render('RecaptchaField1', { 'sitekey': 'xxx', callback: 'recaptchaCallback1'});
grecaptcha.render('RecaptchaField2', { 'sitekey': 'xxx', callback: 'recaptchaCallback2' });
grecaptcha.render('RecaptchaField3', { 'sitekey': 'xxx', callback: 'recaptchaCallback3' });
};
</script>
3) Add the method to remove the disable property on the submit button
$('#GetHelpButton').prop('disabled', true);
function recaptchaCallback1()
{
$('#GetHelpButton').prop('disabled', false);
}
4) Add the widget inside a form
<form id="formContact" method="post" class="login-form margin-clear" action="Landing/SendContactForm">
<div class="form-group has-feedback">
<label class="control-label">Correo electronico</label>
<input name="EmailContact" value="" id="EmailContact" type="text" class="form-control" placeholder="">
<i class="fa fa-envelope form-control-feedback"></i>
</div>
<div id="RecaptchaField1"></div>
<button id="GetHelpButton" type="submit" data-sitekey="xxxx" class="btn btn-info col-md-12 g-recaptcha">Send</button>
Try setting a unique ID for each div and then use a for loop to iterate through them. Something like this:
window.onloadCallback = function() {
var captcha = ['recaptcha1' ,'recaptcha2', 'recaptcha3']; //put your IDs here
for(var x = 0; x < captcha.length; x++){
if($('#'+captcha[x]).length){
grecaptcha.render(captcha[x], {
'sitekey' : '{{ recaptcha_key}}',
'theme' : 'dark',
'callback': function() {
console.log("Woof");
}
});
}
}
};

display loading image with jquery/ajax

I am trying to display a spinning image while ajax call is being completed. I am using the following jsp and jquery code yet it is not working.
Any help will be appreciated
jsp:
<div class="tab-content" id="rdfTabs">
<div id="data">
<p>Please enter dataset URL or absolute file location (e.g: c:\data\dbpedia.rdf)</p>
<table width="100%">
<tr>
<td colspan="2"><input name="txtDataSource" id="txtDataSource" type="text" class="textbox"/>
<input type="button" value="Analyse File"
name="btnAnalyseFile" id="btnAnalyseFile" class="btn-blue" /></td>
</tr>
</table>
**<div id="loadingImage" style="display:none">
<img src="http://preloaders.net/preloaders/287/Filling%20broken%20ring.gif">
</div>**
<p id="presult">
</div>
and here is the jquery code
$(document).ready(function()
{
$("#presult").hide();
$("#btnAnalyseFile").click(
function(e)
{
**$("#loadingImage").show();**
$.ajax({
url : 'CreatePatternServlet',
type : 'POST',
dataType : 'json',
data : $("#formCreatePattern").serialize(),
success : function(data)
{
if(data.analyseResult==true){
var predicates = {};
var objectList = {};
var ddlSubject = $('#ddlSubject');
var ddlPredicate = $('#ddlPredicate');
var ddlObject = $('#ddlObject');
var ddlClass = $('#ddlClass');
$.each(data.Subjects, function(key, value)
{
ddlSubject.append($('<option></option>')
.val(value).html(key));
});
$.each(data.Classes, function(key, value)
{
ddlClass.append($('<option></option>')
.val(value).html(key));
});
$.each(data.Predicates, function(key, value)
{
ddlPredicate.append($('<option></option>')
.val(value).html(key));
});
$.each(data.Objects, function(key, value)
{
ddlObject.append($('<option></option>')
.val(value).html(key));
});
$('#ddlSubject').filterByText(
$('#txtSearchSubject'));
$('#ddlPredicate').filterByText(
$('#txtSearchPredicate'));
$('#ddlObject').filterByText(
$('#txtSearchObject'));
$('#ddlClass').filterByText(
$('#txtSearchClass'));
$("#presult").html("Data uploaded successfully");
$("#presult").css("color","green");
$("#presult").fadeIn(500);
}
else{
$("#presult").html("Upload failed, please check file path or URL. Server returned error: "+data.result);
$("#presult").css("color","red");
$("#presult").fadeIn(500);
}
}
});
**$('#loadingImage').hide();**
return false;
});
});
Problem is that your ajax function is asynchronous, so you are showing the loader, firing the ajax and inmediately hiding the loader, without waiting for the request to end.
Easy fix is putting the $('#loadingImage').hide(); inside the success function, but would be better to add a done function in case it fails
$("#btnAnalyseFile").click(function() etc...
shoudn't be
$("#btnAnalyseFile").on("click", function() { etc...
?

Categories