Explain what is wrong here. First, the run function and its ajax request must be executed. But for some reason the function is executed, and the ajax request is not. It runs right at the very end of the script - after all the functions ... Why is this happening and how to fix it?..
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="id_product_create_form" method="post" enctype="multipart/form-data"></form>
<div class="media_preview_wrap">
<div class="addPhoto">
<div class="addPhotoHeader">
<button type="button" class="button product_images_button">Add</button>
<button id="id_submit" type="button">Submit</button>
</div>
</div>
</div>
<input type="file" name="image" style="display: none" required="" class="product_images" id="">
<script>
var files = [];
$('.product_images_button').click(function() {
$('.product_images').click();
});
$('.product_images').change(function() {
handleFiles(this);
});
$('.media_preview_wrap').on('click', '.thumb', function() {
removeFile($(this).data('id'));
});
$('#id_submit').click(function() {
event.preventDefault();
var $form = $('form'),
formdata = new FormData($form[0]),
$button = $('#id_submit');
formdata.append('content', CKEDITOR.instances.id_content.getData());
function run() {
var product_id = null;
$.ajax($form.attr('action'),{
type: 'POST',
data: formdata,
processData: false,
contentType: false,
success: function(data) {
product_id = data.product_id;
}, error: function(error) {
console.log(error)
}
});
return product_id}
product_id = run();
files.forEach(function(file, index) {
var data = new FormData();
data.append('name', file.name);
data.append('gallery_image', file.file);
uploadFile(event.target.action, data)
.done(function(response) {
removeFile(file.id);
})
.fail(function(error) {
console.log(error);
});
});
});
function handleFiles(input) {
var URL = window.URL || window.webkitURL;
var uniqueId = (new Date()).getTime()
for (var i = 0; i < input.files.length; i++) {
var file = input.files[i];
if (file && file.type.startsWith('image/')) {
uniqueId++;
files.push({
id: uniqueId,
file: file,
name: file.name // задел для возможности переименования файла.
});
var img = $('<img src="'+ URL.createObjectURL(file) +'" class="thumb" data-id="'+ uniqueId +'">');
$('.media_preview_wrap').append(img);
img.on('load', function() {
URL.revokeObjectURL(this.src);
});
}
}
$(input).val('');
}
function removeFile(id) {
files = files.filter(function(file) {
return id !== file.id;
})
$('img[data-id="'+ id +'"]').remove();
}
function uploadFile(url, data) {
return $.ajax({
headers: {'X-CSRFToken': '{{ csrf_token }}' },
type: 'POST',
url: url,
data: data,
processData: false,
contentType: false,
cache: false
});
}
</script>
<style>
.thumb {
width: 150px;
height: auto;
opacity: 0.9;
cursor: pointer;
}
.thumb:hover {
opacity: 1;
}
.product_images {
display: none;
}
</style>
The initial problem is likely due to some browsers having a global event object while others don't.
You are likely getting an error that event is undefined and that would prevent the remaining code to run
Use the argument of the event handler function which always passes in an event object:
$('#id_submit').click(function(event) {
// ^^^
event.preventDefault();
Once that issue is solved... you need to realize that $.ajax is asynchronous and you can't use the new value of product_id until first request completes in the success callback
See How do I return the response from an asynchronous call?
Related
I'm writing a web application where I need to initialize multiple dropzones basing on server content, I currently have a code similar to this:
<script src="/js/dropzone.min.js"></script>
<script>
Dropzone.autoDiscover = false;
window.dropzones = {};
function checkDropzones(container) {
var possibleDropzones = container.querySelectorAll('.needs-to-be-dropzoned');
possibleDropzones.forEach(function (zone) {
if (zone.id.length === 0) {
zone.id = 'dropzone_filled_' + (new Date()).getTime();
window.dropzones[zone.id] = new Dropzone(
'#' + zone.id,
{
paramName: 'image',
addRemoveLinks: true,
}
);
}
})
}
function renderServerContent() {
window.customSections.forEach(function (custom_section) {
var container = document.getElementById(custom_section);
$.ajax({
method: 'GET',
url: '/customRenderUrl?section=' + custom_section,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
success: function (response) {
container.innerHTML = container.innerHTML + response.component;
if (response.component_type === 'image_uploader') {
checkDropzones(container);
}
// ... other marginal stuff ...
},
dataType: 'json'
})
})
}
// ... other scripts ...
window.customSections = [/* server stuff */];
renderServerContent();
</script>
Basically, I have some stuff to dynamically render from the server, so I send a request asking for component rendered data and when I get the answer-back, I check if the inserted content contains an element with .needs-to-be-dropzoned, if so, I assign it a time-based ID (component rendering has a delay between each component so the IDs are unique) and instance the dropzone. This works well with just one dropzone, but when multiple are on the same page it won't generate errors but will work for just the last element on the page.
The server content is something like this:
<form
class="col-12 container-fluid pb-2 dropzone needs-to-be-dropzoned"
method="POST"
action="/imageUploadUrl"
>
<input type="hidden" name="_token" value="..." >
<div class="dz-default dz-message">
Upload files
</div>
<div class="fallback">
<input name=image" type="file" />
</div>
</form>
If I launch a console.dir(window.dropzones) I get 2 objects:
Object { dropzone_filled_1624370363574: {…}, dropzone_filled_1624370363803: {…} }
dropzone_filled_1624370363574: Object { element: form#dropzone_filled_1624370363574.col-12.container-fluid.pb-2.dropzone.needs-to-be-dropzoned.dz-clickable, version: "5.9.2", clickableElements: (1) […], … }
dropzone_filled_1624370363803: Object { element: form#dropzone_filled_1624370363803.col-12.container-fluid.pb-2.dropzone.needs-to-be-dropzoned.dz-clickable, version: "5.9.2", clickableElements: (1) […], … }
What am I doing wrong or missing?
I did various attempts to fix this, and finally, I fixed it by wrapping all server calls into promises, waited for all promises to solve and only after that, I checked for dropzones. The code is approximately this:
<script src="/js/dropzone.min.js"></script>
<script>
Dropzone.autoDiscover = false;
window.dropzones = {};
window.containersToCheck = [];
function checkDropzones(container) {
var possibleDropzones = container.querySelectorAll('.needs-to-be-dropzoned');
possibleDropzones.forEach(function (zone) {
if (zone.id.length === 0) {
zone.id = 'dropzone_filled_' + (new Date()).getTime();
window.dropzones[zone.id] = new Dropzone(
'#' + zone.id,
{
paramName: 'image',
addRemoveLinks: true,
}
);
}
})
}
function renderServerContent() {
return new Promise(function(resolve, reject) {
window.customSections.forEach(function (custom_section) {
var container = document.getElementById(custom_section);
$.ajax({
method: 'GET',
url: '/customRenderUrl?section=' + custom_section,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
success: function (response) {
container.innerHTML = container.innerHTML + response.component;
if (response.component_type === 'image_uploader') {
window.containersToCheck.push(container);
}
resolve();
// ... other marginal stuff ...
},
dataType: 'json'
})
})
});
}
// ... other scripts ...
window.customSections = [/* server stuff */];
var promises = [];
promises.push(renderServerContent());
// other renderings
Promise.all(promises).then(function (results) {
window.containersToCheck.forEach(function(container) {
checkDropzones(container);
});
})
</script>
This way, all Dropzones work.
The function named post1() is being called in the html form tag. This code is throwing an error which is "Uncaught ReferenceError: post1 is not defined". How to call the function inside the HTML code?
Tia.
<script>
function post1()
{
var comment = document.getElementById("comment").value;
var name = document.getElementById("username").value;
if(comment && name)
{
$.ajax
({
type: 'POST',
url: "post_cmnt.php",
data:
{
user_comm:comment,
user_name:name
},
success: function (response)
{
document.getElementById("all_comments").innerHTML=response+document.getElementById("all_comments").innerHTML;
document.getElementById("comment").value="";
document.getElementById("username").value="";
}
});
}
return false;
}
</script>
<form method='POST' action="#" onsubmit="return post1();">
Try adding this document.addEventListener("DOMContentLoaded", function() {}) this would initialize your javascript code on load.
<script type="application/javascript">
document.addEventListener("DOMContentLoaded", function() {
function post1() {
var comment = document.getElementById("comment").value;
var name = document.getElementById("username").value;
if (comment && name) {
$.ajax
({
type: 'POST',
url: "post_cmnt.php",
data:
{
user_comm: comment,
user_name: name
},
success: function (response) {
document.getElementById("all_comments").innerHTML = response + document.getElementById("all_comments").innerHTML;
document.getElementById("comment").value = "";
document.getElementById("username").value = "";
}
});
}
return false;
}
});
</script>
The code below is working fine to upload files to SPO through RestAPI. No feedback is received on file upload progress. An alert is thrown once the upload is complete.
I would like to have a progress bar to display the upload percentage and reload this upload page while clicking OK to the successful alert message.
Kindly assist.
<script src="https://code.jquery.com/jquery-1.12.4.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script type="text/javascript">
$(document).ready(function () {
init();
});
function init(){
$("#btnUploadFiles").click(function(){
var files=$("#inputTypeFiles")[0].files;
uploadFiles(files[0]); // uploading singe file
});
}
function uploadFiles (uploadFileObj) {
var fileName = uploadFileObj.name;
var webUrl = _spPageContextInfo.webAbsoluteUrl;
var documentLibrary="TEST";
var folderName = "";
var targetUrl = _spPageContextInfo.webServerRelativeUrl + "/" + documentLibrary + "/" + folderName;
var url = webUrl + "/_api/Web/GetFolderByServerRelativeUrl(#target)/Files/add(overwrite=true, url='" + fileName + "')?$expand=ListItemAllFields&#target='" + targetUrl + "'";
uploadFileToFolder(uploadFileObj, url, function (data) {
var file = data.d;
var updateObject = {
__metadata: {
type: file.ListItemAllFields.__metadata.type
},
departname: $("#departname").val(), //meta data column1
Filename: $("#filename").val(), //meta data column2
ACFTREG: $("#ACFTREG").val(), //meta data column3
Date: $("#datepicker").val() //meta data column4
};
url = webUrl + "/_api/Web/lists/getbytitle('"+documentLibrary+"')/items(" + file.ListItemAllFields.Id + ")";
updateFileMetadata(url, updateObject, file, function (data) {
alert("File uploaded & metadata updation done successfully");
}, function (data) {
alert("File upload done but metadata updating FAILED");
});
}, function (data) {
alert("File uploading and metadata updating FAILED");
});
}
function getFileBuffer(uploadFile) {
var deferred = jQuery.Deferred();
var reader = new FileReader();
reader.onloadend = function (e) {
deferred.resolve(e.target.result);
}
reader.onerror = function (e) {
deferred.reject(e.target.error);
}
reader.readAsArrayBuffer(uploadFile);
return deferred.promise();
}
function uploadFileToFolder(fileObj, url, success, failure) {
var apiUrl = url;
var getFile = getFileBuffer(fileObj);
getFile.done(function (arrayBuffer) {
$.ajax({
url: apiUrl,
type: "POST",
data: arrayBuffer,
processData: false,
async: false,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
},
success: function (data) {
success(data);
},
error: function (data) {
failure(data);
}
});
});
}
function updateFileMetadata(apiUrl, updateObject, file, success, failure) {
$.ajax({
url: apiUrl,
type: "POST",
async: false,
data: JSON.stringify(updateObject),
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"Content-Type": "application/json;odata=verbose",
"X-Http-Method": "MERGE",
"IF-MATCH": file.ListItemAllFields.__metadata.etag,
},
success: function (data) {
success(data);
},
error: function (data) {
failure(data);
}
});
}
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', getItems);
function getItems() {
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('L%20-%20MDB%20-%20ACFTREG')/items?$Select=Title&$top=2000",
type: "GET",
headers: {
"accept": "application / json;odata = verbose",
},
success: function(data) {
var results = data.d.results;
var options = "";
for(var i = 0; i < results.length; i++){
options = options + "<option value='" + results[i].Title + "'>" + results[i].Title + "</option>";
}
$("#ACFTREG").append(options);
},
error: function(error) {
alert(JSON.stringify(error));
}
});
}
$( function() {$( "#datepicker" ).datepicker(
{
changeMonth: true,
changeYear: true
}
);} );
</script>
Select File:<input type="File" id="inputTypeFiles" /><br />
Departname: <input id="departname" type="textbox"/><br />
Date: <input type="text" id="datepicker" autocomplete="off" name="hidden"><br />
Filename: <input id="filename" type="textbox"/><br />
ACFTREG: <select id="ACFTREG" class="select">
<option selected="selected">Select</option><br />
<input type="button" id="btnUploadFiles" value="Upload"/><br />
Inside the $.ajax({}) function, you can add the xhr setting inside the ajax.
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
var percentComplete = (evt.loaded / evt.total) * 100;
// Place upload progress bar visibility code here
}
}, false);
return xhr;
},
type: 'POST',
//add the rest of ajax settings
check this link for ajax documentation
jQuery/ajax
check this link for example on upload progress
jQuery-upload-progress/example
I found lots os posts with the solution to my problem, but no one works to me...
I tried like:
<div class="ibox-content">
<div id="carregando" class="text-center" style="display:none">
<img src="~/Imagens/logo.png" />
</div>
<div id="container" style="height: 460px; margin: 0 auto"></div>
</div>
My JS is called on a button clink who calls a funcion like bellow:
$("#atualiza").click(function () {
$(document).ajaxStart(function () {
$("#carregando").show();
});
$.ajax({
url: '/Portaria/AtendOperador',
dataType: "json",
type: "GET",
data: { 'data1': data1, 'data2': data2, 'evento': evento, 'cuc': cuc, 'conta': conta },
async: false,
cache: false,
delay: 15,
success: function (data) {
var Categories = new Array();
var Series = new Array();
for (var i in data) {
Categories.push(data[i].Operador);
Series.push(data[i].Fechados);
}
var CategArray = JSON.parse(JSON.stringify(Categories));
atendOperador(CategArray, Series);
$(document).ajaxStop(function () {
$("#carregando").hide();
});
},
error: function (xhr) {
alert('error');
$(document).ajaxStop(function () {
$("#carregando").hide();
});
}
});
});
function atendOperador(CategArray, Series) {
var chart2 = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar'
}
});
}
Even I put the code:
$( document ).ajaxStart(function() {
$( "#carregando" ).show();
});
The image appear only after ajax finishing. Using the two blocks, show and Hide, the image not appear, so, i tried to remove the hide block and i could see that the problem is: Show and Hide happens together when ajax is loaded like:
I cliked on button and noting happened like: http://prntscr.com/ars97n
And after few seconds, Ajax load data and show icon and data together: http://prntscr.com/ars9xq
Try $("#carregando").hide(); instead of $(document).ajaxStop(function ()$("#carregando").hide();});
edit: ajaxStart and ajaxEnd are event handlers. I think they should be registered outside of the click function. Something like this:
$(document).ready(function(){
$(document).ajaxStart(function () {
$("#carregando").show();
});
$(document).ajaxStop(function () {
$("#carregando").hide();
});
$("#atualiza").click(function () {
/* all your code here except for the ajaxStart/ajaxStop portion */
});
});
As Karl stated, the best way to do it is without using ajaxStart/ajaxStop event handlers, or even better, without using jQuery at all.
document.querySelector('.get-data').addEventListener('click', function() {
document.querySelector('.display-data').textContent = null;
document.querySelector('.loading').style.display = 'block';
var request = new XMLHttpRequest();
request.open('GET', 'http://jsonplaceholder.typicode.com/photos', true);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
// Success!
var data = JSON.parse(this.response);
document.querySelector('.loading').style.display = 'none';
document.querySelector('.display-data').textContent = JSON.stringify(data[0]);
} else {
// We reached our target server, but it returned an error
document.querySelector('.loading').style.display = 'none';
}
};
request.onerror = function() {
// There was a connection error of some sort
document.querySelector('.loading').style.display = 'none';
};
request.send();
});
<button class="get-data">Get Data</button>
<div class="loading" style="display: none">
<img src="https://upload.wikimedia.org/wikipedia/commons/2/28/InternetSlowdown_Day.gif" width="50px">
</div>
<div class="display-data"></div>
Finally! I found the problem here! All ways I tried before works now, with this modification I did.
Just:
$("#carregando").show();
Or:
$(document).ajaxStart(function () {
$("#carregando").show();
});
$(document).ajaxStop(function () {
$("#carregando").hide();
});
Or:
beforeSend: function() {
$("#carregando").show();
},
complete: function() {
$("#carregando").hide();
},
All my problem were here: http://prntscr.com/asbxbk!!!
So, I commented that async and works!!!
$("#atualiza").click(function () {
$(document).ajaxStart(function () {
$("#carregando").show();
});
$(document).ajaxStop(function () {
$("#carregando").hide();
});
$.ajax({
url: '/Portaria/AtendOperador',
dataType: "json",
type: "GET",
data: { 'data1': data1, 'data2': data2, 'evento': evento, 'cuc': cuc, 'conta': conta },
//async: false, COMMENTED!!!
success: function (data) {
var Categories = new Array();
var Series = new Array();
for (var i in data) {
Categories.push(data[i].Operador);
Series.push(data[i].Fechados);
}
var CategArray = JSON.parse(JSON.stringify(Categories));
atendOperador(CategArray, Series);
},
error: function (xhr) {
alert('error');
}
});
});
Karl's answer is correct if you want to show the same git for all ajax request on the page
But if you want to do it for this particular AJAX the follow this
$("#atualiza").click(function () {
$.ajax({
beforeSend: function() { $("#carregando").show(); }, //It will show the gif just before sending the request
url: '/Portaria/AtendOperador',
dataType: "json",
type: "GET",
data: { 'data1': data1, 'data2': data2, 'evento': evento, 'cuc': cuc, 'conta': conta },
async: false,
cache: false,
delay: 15,
success: function (data) {
var Categories = new Array();
var Series = new Array();
for (var i in data) {
Categories.push(data[i].Operador);
Series.push(data[i].Fechados);
}
var CategArray = JSON.parse(JSON.stringify(Categories));
atendOperador(CategArray, Series);
$("#carregando").hide(); //this will hide the gif in case of AJAX success
},
error: function (xhr) {
alert('error');
$("#carregando").hide(); //this will hide the gif in case of AJAX failure
}
});
});
Hope this will help you
i'd like to know how can i use $_POST and $_FILES using ajax, i'm trying to upload an image and insert a value on my database with post.
i've tried but it doesn't work.
index.html
<div class="form-group">
<label> img </label>
<input type="file" name="img" id="img" />
<input type='hidden' id='value' value='<?=$_GET["p"]?>' />
</div>
ajax.js
$(document).ready(function() {
$('#upload').click(function() {
var value = $('#value').val();
var img = $('#img').val();
var string= 'value=' + value + '&img=' + img;
$.ajax({
type: "POST",
url: "ajax.php",
data: string,
dataType: "json",
success: function(data) {
var success = data['success'];
if (success == true) {
console.log('success');
} else {
console.log('error');
}
}
});
return false;
});
});
ajax.php
<?php
if(isset($_POST["value"]) && isset($_FILES["img"])) {
echo json_encode(array("success" => true));
} else {
echo json_encode(array("success" => false));
}
?>
The best approach is convert image to base64 first. This conversion is done in the change listener.
var files = [];
$("input[type=file]").change(function(event) {
$.each(event.target.files, function(index, file) {
var reader = new FileReader();
reader.onload = function(event) {
object = {};
object.filename = file.name;
object.data = event.target.result;
files.push(object);
};
reader.readAsDataURL(file);
});
});
$("form").submit(function(form) {
$.each(files, function(index, file) {
$.ajax({url: "/ajax-upload",
type: 'POST',
data: {filename: file.filename, data: file.data},
success: function(data, status, xhr) {}
});
});
files = [];
form.preventDefault();
});