how to splice selected element from FileList - javascript

selected files preview with fileReader in javascript
if i remove from previewed image. it must delete from selected files!
$scope.getFile = function () {
$scope.progress = 0;
$scope.variant.images = [];
var files = $scope.file;
for ( var i = 0; i < files.length; i++) {
var file = files[i];
fileReader.readAsDataUrl(file, $scope).then(function(result) {
$scope.variant.images.push({path: result})
});
}
};
i try like this but it does not works
angular.forEach($scope.file, function (value, key) {
if(key === id){
delete value;
}
})

You cannot splice a FileList. It is readonly! It only has the length and item but no array logic like splice', 'split., etc. So you will have to make a copy from it in an array:
// **A**
$scope.fileArray = [];
angular.forEach($scope.file, function(file) {
$scope.fileArray.push(file)
});
And then you can splice from this array with something like:
$scope.deleteImage = function(index) {
$scope.fileArray.splice(index, 1);
})
As you mention 'preview' I guess you are displaying a thumbnail of the selected images. You will have to change any display logic also to use the fileArray instead of the current file. So it automatically updates when the user removes one element.
<div ng-repeat="image in fileArray"... >
So best to set up an angular watch to recalculate $scope.fileArray as given above. However I'm afraid you cannot do a $watch on a file list. Not certain, but I recently found out that Angular does NOT support ng-model on a <input type="file". I found a solution for this in this article.
So if a simple $scope.$watch('file', function.. doesn't work, you'd best import use the fileModel directive in that into your system and enhance the file-input in your view with it:
<input type="file" name="files" file-model="filesArray" multiple accept="image"/>
You should then be able to watch that filesArray you assign to it:
$scope.$watch('fileArray', function() {
// Code from **A**
....
});

You can use native JS Array#forEach function as it gives you access the index of the object in the array.
I used id assuming you are actually passing an id in to the function to identify the object that needs to be deleted from the array. Looking at your code above, name seems more ideal, if that's unique property in the object of course
$scope.file.forEach(function(file, index){
if (file.id === id){ // Where id is your identifier, could be file.name === name.
this.splice(index, 1);
}
});

Related

Dropzone js: Add previewElements index number as id

Is there a way to use the index number of preview element within the template code so I can add sequential id's(id="item-[1,2,3]") to each time the template is been used? Similar to the use of placeholders such data-dz-thumbnail, data-dz-name, data-dz-size, etc. or a way to acheive that dynamicly as elements(files) are been added?
Thanks
I did something similar to what you are asking but I used the UUID value that is assigned to each file object by Dropzone rather than a sequential number. This accomplishes the goal of ensuring each entry has a unique identifier while tying it back to the file object and not being dependent on the order of the files array.
myDropzone = new Dropzone('form#myuploadform')
myDropzone.on(
'addedFile',
function (file) {
// get unique UUID value assigned when `file` was created
let uuid = file.upload.uuid
// add the UUID value as an attribute to the HTML preview element
file.previewElement.setAttribute('data-uuid', uuid)
/* additional uses of the UUID not part of the original question */
// append the UUID value to the `for` attribute of an LABEL elements
let labels = file.previewElement.querySelectorAll('label')
for (let label of labels) {
let value = label.getAttribute('for')
label.setAttribute('for', value + '-' + uuid)
}
// append the UUID value to the `id` attribute of any form elements
let inputs = file.previewElement.querySelectorAll('input, select, textarea')
for (let input of inputs) {
let value = input.getAttribute('id')
input.setAttribute('id', value + '-' + uuid)
}
}
)
This also means you can write a function to get the file object based on the UUID.
myDropzone = new Dropzone('form#myuploadform')
function get_file(uuid) {
for (let file of myDropzone.files) {
if (file.upload.uuid == uuid) return file;
}
return undefined
}

Get array from jquery autocomplete

I am using JQuery to autocomplete names from a remote database... this all works fine.
However, I want to also get ALL the information associated with that name from the autocomplete and save it to a php array...
Can anyone help?
This is my code for the autocomplete
<script type="text/javascript">
$(function() {
$("#findname").autocomplete({
source: "templates/search2.php?field=sire",
minLength: 5
});
});
</script>
And here is how I call it...
<input type="text" name="name" id = "findname" size="45"><br>
So, when I find the name I am looking for, which works fine, how can I return ALL the data for that named record and store to an array, to then call a modal with the data ?
Thanks
if i understand your question, you want to get the data of a worker to show in a modal, well, first you need to get all the data you want in a single call, not just the names, but also the mail, age or other atributes, then you save it in an object .
For example:
After you called the information, you should get something like this :
var workersData=[{name:"a1",mail:"m1",age:20},
{name:"a2",mail:"m2",age:20},
{name:"a3",mail:"m3",age:20},
{name:"a4",mail:"m4",age:20}];
Then you create a method to get all the names and put this array in the autocomplete input:
function listStringsFromArray(list, atribute) {
var arrayString = [];
if (list) {
for (var index = 0; index < list.length; index++) {
arrayString.push(list[index][atribute]);
}
}
return arrayString;
}
$("#findname").autocomplete({
source: listStringsFromArray(workersData,"name"),
minLength: 5
});
Finally add a method for the input, so anytime it changes, to search for the rest of the data in the workers array and put the information where you want:
$("#findname").keypress(function(e){
fillDataModalWorker(); });
function fillDataModalWorker(){
var workerName=$("#findname").val();
var mail,age;
for (var index = 0; index < workersData.length; index++) {
if(workersData[index]["name"]==workerName){
mail=workersData[index]["mail"];
age=workersData[index]["age"];
$("#inputMailModal").val(mail);
$("#inputAgeModal").val(age);
break;
}else{
$("#inputMailModal").val("Worker´s information not found");
$("#inputMailModal").val("Worker´s information not found");
}
}
}
Hope it hepls.

Add to array only once - leaving unique items

I program a function that give me all values of some input checkboxes and include them into an array.
Function:
$('#area_tbl .checkbox').each(function(){
/*for(var i = 0; i < test.length; i++){
if(test[i].PLZ === $(this).find('.area-checkbox').val()){
alert('Gleich');
}else{
alert('nicht gleich');
}
}*/
test.push({PLZ:$(this).find('.area-checkbox').val()});
});
My array looks like this:
[Object { PLZ="42799"}]
That's fine!
Now I include automatically more checkboxes with more values. After that my function is refreshing and I include the 'new' values.
Now my problem is that my array looks like this:
[Object { PLZ="42799"}, Object { PLZ="42799"}, Object { PLZ="51399"}]
You can see PLZ='42799' is twice.
I want to find the duplicate values and delete them from my array. I try it with the if clause in my function. But nothing works for me.
Assuming that value of each checkbox is unique, you need to reset the test value before running this each iterator
test = [];
$('#area_tbl .checkbox').each(function(){
test.push({PLZ:$(this).find('.area-checkbox').val()});
});
You could use a memory
// The memory will be a simple list with the already added elements. Firstly empty
memory = []
// we loop over ther checboxes
$('#area_tbl .checkbox').each(function(){
// we store the value
var v = $(this).find('.area-checkbox').val();
// If memory doesn't content the value... (its position is -1)
if(memory.indexOf(v) == -1){
// we store the object and we update the memory
test.push({PLZ:v});
memory.push(v);
}
});
You could use a temporary object and look up with accessing the property:
var object= {};
$('#area_tbl .checkbox').each(function() {
var v = $(this).find('.area-checkbox').val();
if (!object[v]) {
test.push({PLZ: v});
object[v] = true;
}
});

Page with multiple dropdown filters

I have a page which uses dropdowns to filter a listing. I have over 10 filters now and each of the change function, I am calling an AJAX request and passing corresponding variables to the PHP function. Like this :
$("#categories").change(function() {
uri = "myurl" ;
var status=$("#statusfilter").val();
var category=$("#categories").val();
var network=$("#networksfilter").val();
var prod_type = $("#prodtypefilter").val();
loadData(uri,category,status,network,prod_type);
});
and in loadData() I have the following code :
function loadData(uri,category,status,network,prod_type){
url + = category+"/"+status+"/"+network+"/"+prod_type;
$('#userdata').load(url);
}
Here I have given only 4 filters only, but it is actually 10 and may increase.Anyway this is working fine. But the problem is that as I increase the filters, I need to write this same for every dropdown change function. Is there any better approach to optimze the code and so I don't need to load a bunch of JS ?
Rename your filter elements' IDs to start with same word, for example "filter_". Then get all of them at once:
$('select[id^="filter_"]').change(function() {
var uri = "myurl";
var filters = new Array();
$('select[id^="filter_"]').map(function () {
filters[$(this).name()] = $(this).val(); // not tested, just an idea
});
loadData(uri,filters);
});
.map() iterates over its elements, invoking a function on each of them and recording the selected option value in the array.
You can use .each() if it's more intuitive from .map() for you:
$.each('select[id^="filter_"]', function() {
filters[$(this).name()] = $(this).val(); // not tested, just an idea
});
Note: It's a good idea to use associative array as #Tony noticed below to be sure which filter is for which database table attribute in your server side script.
You will need to write some code in any cases, but you can reduce it, for example like this:
$("#categories").change(function() {
uri = "myurl";
var filters = {
status: $("#statusfilter").val(),
category: $("#categories").val(),
network: $("#networksfilter").val(),
prod_type: $("#prodtypefilter").val()
}; // order is important
loadData(filters );
});
loadData(filters) {
var url = '';
for (var filterName in filters)
url += '/' + (filters[filterName] || 'any'); // here some def value needed
url = url.substring(1); // cut first slash
$('#userdata').load(url);
}
EDIT
Or even like this:
loadData(filters) {
var url = Object.keys(filters).map(function(el) {
return filters[el] || 'any';
}).join('/');
$('#userdata').load(url);
}

putting source of all images into an array

What is the cleanest way to put the source attribute string of all images within a div into an array?
I was hoping this would work -
var imageSourceArray = $("#leDiv img").attr('src');
alert(imageSourceArray[3]); //not alerting the source, boo hoo.
Do I need to loop through $("#leDiv img") and add each src string to an array individually? Or is there a more elegant way to do this?
You can use jQuery's map function which is described as:
Pass each element in the current matched set through a function, producing a new jQuery object containing the return values.
For your example:
var mySources = $('#leDiv img').map(function() {
return $(this).attr('src');
}).get();
Edit: Far more elegant solution, there's obviously still some looping involved internally:
var img_sources = $('#leDiv img').map(function(){ return $(this).attr('src') });
You will in fact need to loop over the collection and add sources individually.
var img_sources = [];
$('#leDiv img').each(function(i,e){
img_sources.push($(e).attr('src'))
})
Some background: jQuery.fn.attr() maps to jQuery.access() internally, the key part of which looks like this:
function( elems, key, value, exec, fn, pass ) {
var length = elems.length;
// setter functions omitted here …
// Getting an attribute
return length ? fn( elems[0], key ) : undefined;
}
Note the elems[0] part – only the first item in the collection is fed to the subsequent callback function (jQuery.attr() in fact) responsible for extracting the information.
var imageSourceArray = [];
$('#leDiv img').each(function(){
var src = $(this).attr("src");
imageSourceArray.push(src);
});
alert(imageSourceArray[3]);
you already have the src in a collection when you fetch the the images. It may be more efficient to not store the src attributes in another array:
$('#leDiv img').each(function(i,e){
var dosomethingwith = $(e).attr('src');
})
or you could do:
var ImageCol = $('#leDiv img');
alert(ImageCol[3].attr('src'));

Categories