How to process FormData in javascript? - javascript

I have global $.ajaxPrefilter function that filter values for XSS like this:
if (typeof filterXSS == 'function') {
$.ajaxPrefilter(function(options, origOptions, jqXHR) {
if (typeof options.data == 'string') {
var object = {};
options.data.split('&').forEach(function(pair) {
pair = pair.split('=');
object[pair[0]] = decodeURIComponent(pair[1].replace(/\+/g, ' '));
});
var newData = {};
options.data = Object.keys(object).map(function(key) {
var value = filterXSS(object[key]);
return key + '=' + encodeURI(value.replace(/ /g, '+'));
}).join('&');
} else {
console.log(typeof options.data);
console.log(options.data);
}
});
}
it work fine except when I call ajax request with FormData like this:
var file = files.shift();
if (file) {
var formData = new FormData();
formData.append(file);
formData.append('value', '<script>alert("x");</script>');
$.ajax({
method: 'POST',
url: $form.attr('action'),
data: formData,
cache: false,
contentType: false,
processData: false
});
}
how can I process FormData inside $.ajaxPrefilter, I've try to iterate over options.data but only get append:
for (var i in options.data) {
console.log(i);
}

Related

How to get selected row values from a table

I am converting a HTML table to an array and passing it in to a controller for inserting multiple rows. I am able to create the array, but the problem is it's creating a complete table array but I want to get the selected row td values only.
//function to convert HTML table to array//
var HTMLtbl = {
getData: function (table) {
var data = [];
table.find('tr').not(':first').each(function(rowIndex, r) {
var cols = [];
// I believe the main problem is here:
$(this).find('td').each(function(colIndex, c) {
cols.push($(this).text().trim());
});
data.push(cols);
});
return data;
}
}
$(document).on('click', '#btnsave', function() {
var data = HTMLtbl.getData($('#tblresult'));
var parameters = {};
parameters.array = data;
var request = $.ajax({
async: true,
cache: false,
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
url: "../Home/Save_SearchCarsDocs",
data: JSON.stringify(parameters)
});
request.done(function(msg) {
alert("Row saved " + msg.d);
});
You can try following...
//function to convert HTML table to array//
var excludedTD_Index = [0,5,7]; // define what you want to exclude by index
var HTMLtbl = {
getData: function (table) {
var data = [];
table.find('tr').not(':first').each(function(rowIndex, r) {
var cols = [];
// I believe the main problem is here:
$(this).find('td').each(function(colIndex, c) {
if(excludedTD_Index.indexOf(colIndex) >=0) // exclude TD
continue;
cols.push($(this).text().trim());
});
data.push(cols);
});
return data;
}
}
$(document).on('click', '#btnsave', function() {
var data = HTMLtbl.getData($('#tblresult'));
var parameters = {};
parameters.array = data;
var request = $.ajax({
async: true,
cache: false,
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
url: "../Home/Save_SearchCarsDocs",
data: JSON.stringify(parameters)
});
request.done(function(msg) {
alert("Row saved " + msg.d);
});
OR you can make it more managable if you can add following data to your TD tag
<td data-exclude="1">
...
after adding above data you can exclude those columns as following
var HTMLtbl = {
getData: function (table) {
var data = [];
table.find('tr').not(':first').each(function(rowIndex, r) {
var cols = [];
// I believe the main problem is here:
$(this).find('td').each(function(colIndex, c) {
if($(this).data("exclude") == 1) // exclude TD
continue;
cols.push($(this).text().trim());
});
data.push(cols);
});
return data;
}
}
thanks Rory McCrossan finally get my answer i am adding my solution below
var CB=1;
var HTMLtbl =
{
getData: function (table) {
var data = [];
table.find('tr').not(':first').each(function (rowIndex, r) {
if ($("#chk_" + CB).is(':checked'))
{
var cols = [];
$(this).find('td').each(function (colIndex, c) {
cols.push($(this).text().trim());
});
data.push(cols);
}
CB++;
});
CB = 1;
return data;
}
}

why my file upload not copied on directory? (javascript, php)

please help
This my constructor in class
$this->covername = $image['cover']['name'];
$this->coverdir = $image['cover']['tmp_name'];
$this->covertype = pathinfo($this->covername, PATHINFO_EXTENSION);
This json script
prosesSave = function(saveas) {
document.getElementById("saveas").value = saveas;
var message = $('#message');
var fields = $("#form1,#form2,#form3");
var formdata = new FormData(fields[0]);
$.ajax({
type: "POST",
url: "project/proses-new-page.php",
data: formdata,
cache: false,
contentType : false,
processData : false,
dataType: 'json',
success: function(response) {
$(message).empty();
if(response.saveas){
if (saveas == 'Draft') {
var idmsg = $("<div></div>", {
"class":"callout callout-info"}).appendTo(message);
}else{
var idmsg = $("<div></div>", {
"class":"callout callout-success"}).appendTo(message);
}
}else{
var idmsg = $("<div></div>", {
"class":"callout callout-danger"}).appendTo(message);
}
$(idmsg).empty().html(response.html);
document.getElementById("status").value = "EditPage";
document.getElementById("idpage").value = response.idpage;
}
});
return false;}
This my process copy
if ($this->covername) {
$this->filename = $id."_".$this->date.".".$this->covertype;
$this->move = $this->dirupload."cover/".$this->filename;
if(!move_uploaded_file($this->coverdir, $this->move)){
$this->response_html = '<p>Faild</p>'.$this->covername."<br>".$this->coverdir."<br>".$this->move;
}else{
$this->response_html = '<p>Succes</p>'.$this->covername;
}
chmod($this->move, 0777);
mysqli_query($this->conn, "UPDATE tb_pages SET COVER_PAGE = '".$this->filename."' WHERE ID_PAGE = '".$id."'");
}
i have problem with my code. in this code name of image, type and so on can insert into database. but on the image can't copied in directory($this->coverdir).
sory for my bad english.

Iterate over array items and check property value

function GetViewModelData() {
var RDcViewModel = [];
var recordId = $.trim($("#recordId").val());
for (i = 1; i <= rowCount; i++) {
var item1 = $.trim($("#item1" + i).val()) == '' ? 0 : parseInt($("#item1" + i).val());
var item2 = $.trim($("#item2" + i).val()) == '' ? 0 : parseInt($("#item2" + i).val());
var GrandTotal = (item1 + item2);
var rdtCViewModel = new ItemDetailsViewModel(0, item1, item2, GrandTotal);
RDcViewModel.push(rdtCViewModel);
}
var obj = new ReportViewModel(recordId, RDcViewModel);
var viewmodel = JSON.stringify(obj);
return viewmodel;
}
I have the above sample function that i'm using to iterate over html table rows and storing the row values in an array.
Once i have my array populated, i'm using below code snippet to post the data to my controller.
var PostData = function () {
$(".btnSubmit").click(function () {
var viewmodel = GetViewModelData();
//i want to check from here if viewmodel has any item(row) where GrandTotal is 0 (zero)
$.ajax({
async: true,
cache: false,
contentType: 'application/json; charset=utf-8',
data: viewmodel,
headers: GetRequestVerificationToken(),
type: 'POST',
url: '/' + virtualDirectory + '/Item/DataSave',
success: function (data) {
if (data == true) {
window.location.href = '/' + virtualDirectory + '/Destination/Index';
}
},
error: function (e) {
return false;
}
});
});
}
What i now want to do in my PostData function is to check if my "viewmodel" object contains any item(row) where "GrandTotal" is 0.
using JSON.parse(viewmodel), prepare object of type ReportViewModel with RDcViewModel JS array of type ItemDetailsViewModel and iterate over it to find if any grandtotal == 0 for ItemDetailsViewModel instances
var viewmodel = GetViewModelData(),
var obj = JSON.parse(viewmodel);
var bFoundZero=false;
$.each(obj.RDcViewModelArray, function(idx, elem){
if( elem.GrandTotal === 0 ) bFoundZero=true;
})
if( bFoundZero ) return 0;
As you have stringified it, now you have to parse it back if you want to access its keys and values:
var PostData = function() {
$(".btnSubmit").click(function() {
var viewmodel = GetViewModelData(),
viewObj = JSON.parse(viewmodel),
flag = false; // <-----parse it back here
viewObj.forEach(function(i, el){
flag = el.GrandTotal === 0;
return flag;
});
if(flag){ return false; } // <------ and stop it here.
$.ajax({
async: true,
cache: false,
contentType: 'application/json; charset=utf-8',
data: viewmodel,
headers: GetRequestVerificationToken(),
type: 'POST',
url: '/' + virtualDirectory + '/Item/DataSave',
success: function(data) {
if (data == true) {
window.location.href = '/' + virtualDirectory + '/Destination/Index';
}
},
error: function(e) {
return false;
}
});
});
}
There is no point iterating array again. Break the loop in GetViewModelData() and return false from that function. Then test it in PostData
Inside existing for loop:
var GrandTotal = (item1 + item2);
if(!GrandTotal){
return false;
}
Then in PostData()
var PostData = function () {
$(".btnSubmit").click(function () {
var viewmodel = GetViewModelData();
if(viewmodel === false){
alert('Missing total');
return; //don't proceed
}
/* your ajax */

Assign jquery plugin to dropdown not working

I am creating an audio player that have 4 dropdown lists each depends on each other to get the right mp3 file, the jquery code works fine until i assign a plugin to the dropdown called (fancyspinbox) to look better.
The problem is the dropdown dont update its value though its triggered successfully.
Kindly find my code below
<script>
$(document).ready(function () {
$('#ddbibletype').fancyspinbox();
$('#ddtestament').fancyspinbox();
$("#booksdd").fancyspinbox();
$("#chapterdd").fancyspinbox();
});
$("#ddtestament").change(function () {
var options = {};
options.url = '#Url.Action("GetBooks", "Home")';
options.type = "POST";
if ($("#ddtestament option:selected").index() == 0)
options.data = JSON.stringify({ testament: 'OT' });
else
options.data = JSON.stringify({ testament: 'NT' });
options.dataType = "json";
options.contentType = "application/json; charset=utf-8";
options.success = function (jsonResult) {
$("#booksdd").empty();
$("#chapterdd").empty();
var jb = $(jsonResult.jbooks);
var jc = $(jsonResult.jchapters);
for (var i = 0; i < jb.length; i++) {
$("#booksdd").append("<option>" + jb[i] + "</option>");
}
for (var i = 0; i < jc.length; i++) {
$("#chapterdd").append("<option>" + jc[i] + "</option>");
}
$("#booksdd").change();
};
options.error = function () { alert("Error retrieving Books!"); };
$.ajax(options);
});
$("#booksdd").change(function () {
var options = {};
options.url = '#Url.Action("GetChapters", "Home")';
options.type = "POST";
if ($("#ddtestament option:selected").index() == 0)
options.data = JSON.stringify({ bookID: $("#booksdd option:selected").index() });
else
options.data = JSON.stringify({ bookID: ($("#booksdd option:selected").index() + 39) });
options.dataType = "json";
options.contentType = "application/json; charset=utf-8";
options.success = function (chapters) {
$("#chapterdd").empty();
for (var i = 0; i < chapters.length ; i++) {
$("#chapterdd").append("<option>" + chapters[i] + "</option>");
}
$("#chapterdd").prop("disabled", false);
$("#chapterdd").change();
};
options.error = function () { alert("Error retrieving chapters!"); };
$.ajax(options);
});
$("#chapterdd").change(function () {
var options = {};
options.url = '#Url.Action("GetTrackPath", "Home")';
options.type = "POST";
if ($("#ddtestament option:selected").index() == 0)
options.data = JSON.stringify({ bibleType: $("#ddbibletype option:selected").index(), bookID: $("#booksdd option:selected").index() + 1, chapterNum: $("#chapterdd option:selected").index() + 1 });
else
options.data = JSON.stringify({ bibleType: $("#ddbibletype option:selected").index(), bookID: ($("#booksdd option:selected").index() + 40), chapterNum: $("#chapterdd option:selected").index() + 1 });
options.dataType = "json";
options.contentType = "application/json; charset=utf-8";
options.success = function (trackpath) {
var audio = $('#bibleplayer');
$('#mpsource').attr('src', trackpath);
audio[0].pause();
audio[0].load();//suspends and restores all audio element
audio[0].oncanplaythrough = audio[0].play();
};
options.error = function () {
alert("Error retrieving Books!");
};
$.ajax(options);
});
I'm assuming you are using this fancyspingbox? https://github.com/mayakokits/jquery.fancyspinbox
There is no mention there of needing to add different event listeners, but they do mention "If you need to access the spinbox element, use the element object.". Possibly that is the solution
ie this line
$("#ddtestament").change(function () {
becomes
$("#ddtestament").element.change(function () {
or
$($("#ddtestament").element).change(function () {
as do the other similar lines.

403 (FORBIDDEN)

I'm trying to send $ajax, and I have got it, but I have to send file with my form, in the same or not, doesn't matter. csrf token has not been found and I'm getting error.
My javascript
$(document).ready(function() {
var csrf_token = $('input[name="_token"]').val();
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
}
});
// $("body").bind("ajaxSend", function(elm, xhr, s) {
// if (s.type == "POST") {
// xhr.setRequestHeader('X-CSRF-Token', csrf_token);
// }
// });
window.getCookie = function(cname) { //window for testing in console
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
}
return "";
};
function sendPost() {
var data = $('form').serialize();
var file = $(document.getElementById('files').files[0]);
$.ajax({
type: 'POST',
url: '/delling_data_objects/document/',
//data: $('form').serialize(), it's working
data: file, // its don't
enctype: 'multipart/form-data',
headers: window.getCookie('csrftoken')
});
};
$('#submit').on('click', function() {
sendPost();
});
});
my view.py
def load_files(request):
form = ApartForm(request.POST)
import pdb
pdb.set_trace()
if form.is_valid():
form.save()
file_form = request.POST['file']
for f in file_form:
with open(f) as dest:
for chunk in f.chunks():
dest.write(chunk)
else:
return HttpResponse('form is not valid')
return HttpResponse('ok')
You are not doing it correctly. It feels like you are sending the requestHeader twice.(edit: nevermind didn't see a part of the code was commented)
Based on your code, try something like this :
function sendPost() {
var data = $('form').serialize();
var file = $(document.getElementById('files').files[0]);
var csrftoken = getCookie("csrftoken");
$.ajax({
method: "POST",
url: '/delling_data_objects/document/',
data: data,
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
success: function(data) {
// whatever you want to do
}
});
}
$('#submit').on('click', function() {
sendPost();
});
var getCookie = function(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== "") {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + "=")) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
};
var csrfSafeMethod = function (method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
};

Categories

Resources