I have a hidden field that stores all of the id's of images that have been uploaded for a specific post.
The hidden field HTML looks something like this:
<input type="hidden" id="post_images" name="post_images" value="1,2,3,4,5" />
When an image is deleted from the post, I need to remove it's image_id from that hidden field. So if I delete image_id 4 from the post, the hidden field needs to update to be value="1,2,3,5"
I'm open to changing the way I store the image_id's for the post to a different format if there is a better way of doing this.
While you could use this dirty regex:
$("#post_images").val(function(i, v) {
return v.replace( new RegExp('(?=(?:^|,))(,?)' + id + '(?=(?:,|$)),?'), '$1' );
});
Here's the fiddle: http://jsfiddle.net/43hhs/
A more sane way would be to use array splicing:
$("#post_images").val(function(i, v) {
var values = v.split(','),
i = $.inArray(id.toString(), values);
if ( i != -1 ) {
values.splice(i, 1);
return values.join(',');
}
else {
return v;
}
});
Here's the fiddle: http://jsfiddle.net/khHPq/
jsFiddle: http://jsfiddle.net/4Mwsu/15/
$(".imageRemove").click( function()
{
$(this).hide();
var values = $("#post_images").val().split(",");
var newValue = "";
for ( var i = 0 ; i < values.length ; i++ )
{
if ( $(this).attr("id") != values[i] )
{
newValue = newValue + values[i] + ",";
}
}
$("#post_images").val( newValue );
});
You might consider using jQuery's data method instead, which lets you store true arrays. If you need data to be passed in the value of the elements, you can convert back and forth at your convenience, such as in an .on('submit', ...) handler.
The following code is a bit cumbersome, but I think it communicates the idea.
$pi = $('#post_images');
$pi.data('values', $pi.val().split(',') );
// now .data('values') is a true JS array
console.log($pi.data('values').indexOf("3")); // 2
$pi.data('values').splice(2,1); // removes the third element
console.log($pi.data('values')); // ["1","2","4","5"]
$pi.val( $pi.data('values').join(',') );
console.log($pi.val()); // "1,2,4,5"
http://jsfiddle.net/mblase75/vx3XL/2/
using that, to me easiest way to go would be to have the value start and end in ',', then you can just do a
$("#post_images").val($("#post_images").val().replace("," + idtoremove + ",", ",")
var theVals = $(':input').val().split(','); //split the values into an array
var myVal = '4'; //this should be the ID of the element you want to remove
if($.inArray(myVal, theVals)){ //is the item in the array
index = theVals.indexOf(myVal); //if it is, then get the index position
theVals.splice(index, 1); //starting at the index of the element in the array, remove 1 element
$(':input').val(theVals); //update the input with the new array of IDs
}
console.log($(':input').val()); //general purpose to visualize this output
a working jsFiddle
Related
I have an array of arrays in JavaScript that I'm storing some values in, and I'm attempting to find a way to clear the value within that array when the user removes the specified control from the page, however I'm not finding a good way to do this and anything I try doesn't seem to be working.
What is the best method for clearing the value in the array? I'd prefer the value to be null so that it's skipped when I iterate over the array later on.
I've tried to do MyArray[id][subid] = '' but that still is technically a value. I've also tried to do MyArray[id][subid].length = 0 but that doesn't seem to do anything either. Trying to grab the index and splice it from the array returns a -1 and therefore doesn't work either.
var MyArray;
window.onload = function(){
MyArray = new Array();
}
function EditValuesAdd(){
var Input = document.getElementById('Values-Input').value;
var ID = document.getElementById('FID').value;
var ValueID = ControlID(); // generate GUID
if (!MyArray[ID]) MyArray[ID] = new Array();
MyArray[ID][ValueID] = Input;
document.getElementById('Values').innerHTML += '<a href="#" id="FV-' + ValueID + '" onclick="EditValuesRemove(this.id)"/><br id="V-' + ValueID + '"/>';
}
function EditValuesRemove(id)
{
var ID = document.getElementById('FID').value;
document.getElementById(id).remove();
document.getElementById(id.replace('FV-', 'V-')).remove();
MyArray[ID][id.replace('FV-', '')] = '';
}
I've also tried to do an index of and then splice it from the underlying array but the index always returns -1.
var Index = MyArray[ID].indexOf(id.replace('FV-', ''));
MyArray[ID].splice(Index, 1);
Setting the length to zero has no effect either.
MyArray[ID][id.replace('FV-', '')].length = 0;
I would expect that one of the methods above would clear out the value and make it null so that it is skipped later on but all of the methods I've found and tried so far leave some non-null value.
What you need is an object (a Map), not an array (a list).
Here's a basic idea of how to do it :
MyArray = {};
....
if (!MyArray[ID]) MyArray[ID] = {}
MyArray[ID][ValueID] = Input;
...
delete MyArray[ID][id.replace('FV-', '')];
Check here for more information : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
In the end I used an array of objects MyArray = [] and then using splice/findindex to remove it from the array:
function RemoveItem(id)
{
var Index = MyArray.findIndex(a => a.ID == id.replace('FV-', ''));
MyArray.splice(Index, 1);
document.getElementById(id).remove();
document.getElementById('FVB-' + id.replace('FV-', '')).remove();
}
It doesn't solve the actual question asked but I don't know if there really is an answer since I was using arrays in the wrong manner. Hopefully this at least points someone else in the right direction when dealing with arrays and objects.
I have a situation, hope experts here will help me to sort it out. I need to get "id" values for first three tags and than on console.log print the values with comma separated.
I have managed to get the values from tag and print it on output. However, I am not able to comma separate them, and the issue is I am getting id of all the number of articles rather than only 3.
This is the jquery code that I come up with
jQuery(document).ready(function($) {
$("article").each(function() {
var info1 = $(this).attr("id");
var info2 = info1.replace( /[^\d]/g, '');
console.log(info2);
});
});
And this is the test
http://jsfiddle.net/0mvjbkhs/1/
Please note that I am not able to do any changes to html, all I can do is to get things done using jquery.
Please help to fix my code, So my output will looks like
[155569, 155570, 155571]
Thank you,
Use the jQuery .map() method which returns an array; if you need a single comma-delimited string, use the JavaScript .join() method. Don't forget :lt(3) which say you want the first three:
var arr1st3 = $('article:lt(3)').map(function() {
return this.id.replace(/[^\d]/g, '');
}).get();
console.log( arr1st3 );//OUTPUT: ["155569", "155570", "155571"]
//If you want [155569, 155570, 155571] as output
//use return +this.id.replace(/[^\d]/g, ''); instead
DEMO
jQuery(document).ready(function($) {
// search by the attribute
var ids = $('article')
// Take only the first three items
.slice(0, 3)
// Loop them to return an array
.each(function() {
// Get just the id and put that in the array
return this.attr('id');
});
// Format your output
console.log('[' + ids.join(', ') + ']');
});
http://jsfiddle.net/0mvjbkhs/4/
jQuery(document).ready(function($) {
var articles = [];
$("article").each(function() {
var info1 = $(this).attr("id").replace( /[^\d]/g, '');
articles.push(info1);
if (articles.length == 3) {
// break;
return false;
}
});
console.log('[' + articles.join(', ') + ']');
});
When clicking a li element, I want to store its text as a localStorage value only once. If it exists in localStorage, a second click must have no effect (just an alert).
To check if the string exists I'm doing an if inside a for loop, but I'm doing something wrong. (fiddle line 26). My question is if there is a way to make this condition work.
I can not use the colors as keys, since my real script uses large strings instead of colors. Adding a class is not the way I want to solve it.
Thanks
http://jsfiddle.net/SXjtd/3/
// Each color must be stored with localStorage once with a click.
// The second click must have no effect, just run an alert.
// LINE 26: the problem is while checking if the value exists
// Colors are used for this example, the real js uses long strings, that's why I can not use the colors as keys.
localStorage.clear();
// define a value that will be used for increment
if (localStorage.getItem('current_id') === null) {
localStorage.setItem('current_id', 0);
}
$(document).on('click', 'li', function() {
var dl = $('dl');
var current_color = $(this).text();
// each click generates a new key
current_key = 'color_id_' + (parseInt(localStorage.getItem('current_id')) + 1);
localStorage.setItem('current_id', (parseInt(localStorage.getItem('current_id')) + 1));
$('<dt>' + current_key + '</dt><dd>' + current_color + '</dd>').appendTo(dl);
// THE PROBLEM IS HERE
// I want to know how to check if a value exists in localStorage
// if this value doesn't exist, it is set in localStorage with a click
for (var i = 0, len = localStorage.length; i < len; i++) {
if (localStorage.getItem('color_id_' + i) == current_color) {
alert('Color exists in localStorage.');
} else {
alert('New Color added to localStorage');
localStorage.setItem(current_id, current_color);
}
}
});
I think this solution can help to you:
$(document).on('click', 'li', function() {
var color = $(this).text();
if(!localStorage.getItem("colors")){
localStorage.setItem("colors", "[]");
}
var list = JSON.parse(localStorage.getItem("colors"));
var exist = false;
for(var i = 0; i < list.length; i++)
if(list[i] == color) {
exist = true;
break;
}
if(!exist) list.push(color);
else{
alert("EXIST");
}
localStorage.setItem("colors", JSON.stringify(list));
});
Working demo.
The idea is storing selected colors in array, then save to localStorage. If user clicks to color we just get data serialize it and then check for existing.
Get data serialize it
Check if color exist
Save if not exist, otherwise show alert
Deserialize data and store
Another way:
$(document).on('click', 'li', function() {
var color = $(this).text();
var nSpace = "colors." + color;
if(localStorage.getItem(nSpace))
alert("EXIST");
else
localStorage.setItem(nSpace, true);
});
Idea is using namespaces.
Why don't you just use the string you're storing as the key of the localStorage entry?
I want to get values of all fields in a variable separated by a comma. For example: 1,2,3
The following code will work fine, but it only adds the comma at end of the last value also. How can I remove that?
fields = $('.wrap').find('.text');
var data = '';
fields.each(function() {
var value = $(this).val();
if ( value != '' ) {
data += ' ' + value + ',';
}
});
alert(data);
JSFiddle:
http://jsfiddle.net/cn5Gt/
I always use arrays for these kind of things:
var fields = $('.wrap').find(".text[value!='']");
var data = [];
fields.each(function() {
data.push($(this).val());
});
alert(data.join(','));
You can push elements on array than just use join() method.
fields = $('.wrap').find('.text');
var data = [];
fields.each(function() {
var value = $(this).val();
if ( value != '' ) {
data.push(value);
}
});
alert(data.join());
Try the code below, using the i which is the loop index and test against the length of the jQuery object.
fields = $('.wrap').find('.text');
var length = fields.length;
var data = '';
fields.each(function(i) {
var value = $(this).val();
if ( value != '' ) {
if(i === length-1) { //The last one
data += ' ' + value;
} else {
data += ' ' + value + ',';
}
}
});
Updated fiddle
You could just remove the final character afterwards?
data = data.substr(0, data.length - 1);
http://jsfiddle.net/cn5Gt/3/
Simplest of all:just replace your last line with the below line
alert(data.slice(0,-1));//where data is string
http://jsfiddle.net/cn5Gt/7/
DOC MDN : slice
How about something like this:
var data = $('.wrap').find('.text')
.map(function(i,el){ return el.value || null; })
.get().join(", ");
Demo: http://jsfiddle.net/cn5Gt/11/
jQuery's .map() method will "Pass each element in the current matched set through a function, producing a new jQuery object containing the return values." You can still include your if ( value != '' ) { test in the callback function because if your function returns null or undefined then .map() will not use that particular value. (I've used || null above as a shortcut to an if/else structure.)
Call .get() (or .toArray()) on the result and you'll have an actual array, which means you can then use the Array .join() method to form a string with the values comma separated.
If you need to do other processing on each item besides just getting the value you could stick with the .each() loop and add the values to an array that you then join after the loop (like some of the other answers), or just use the string .slice() method to remove the trailing comma and space characters.
Try this:
Using the length function to determine the position of the each
var fields = $('.wrap').find('.text');
var len = fields.length;
var data = '';
fields.each(function(index, element) {
var value = $(this).val();
if ( value != '' ) {
data += ' ' + value;
if (index != len - 1) {
data += ',';
}
}
});
alert(data);
this is my first post in stackoverflow.. I am trying to iterate over an object(my implementation is an associative array) which in turn has some properties. Now I wish to construct another array out of it in order to use it as a localsource in jquery autocomplete widget for seach operations. Now the problem is that i am using for in loop to that according to the documenations available... However the output is always one less than the original object. The itearation involving the last element is not performed at all. Below is the sample object that I am using as input.
SubTeachPair = object{"5CS1":{SubAbbrev:"CA-L",SubCode:"5CS1",SubName:"Computer Architecture",TeacherId:"1",TeacherName:"Ayush Pandey",label:"Computer Architecture",value:"5CS1"},"5CS2":{SubAbbrev:"CA-P",SubCode:"5CS2",SubName:"Computer Engg",TeacherId:"10",TeacherName:"MAyush Pandey",label:"Computer Engg",value:"5CS2"}}
It has this kind of elements and is dynamically generated so the property names are variable. The loop construct that I have written is
var SubSource = [];
console.log(SubTeachPair);
var count = 0;
for(sub in SubTeachPair){
console.log(count);
SubSource[count] = {};
SubSource[count]['label']=SubTeachPair[sub]['label'];
SubSource[count]['value']=SubTeachPair[sub]['value'];
count++;
}
However, the result for the given input is only:
object{{ label: "Computer Architecture", value: "5CS1"}}
Am I missing something here?
edit-- The function that produces the input object is as follows(It is triggered onclick by the next button).
$('#' + $(this).attr("id")).autocomplete({
source : 'search',
minLength : 1,
change : function(event, ui) {
if( typeof ui.item != 'undefined') {
SubTeachPair[$(this).attr("id")] = {};
// console.log(ui.item);
SubTeachPair[$(this).attr("id")]['value'] = $(this).attr("id");
SubTeachPair[$(this).attr("id")]['label'] = $('label[for="' + this.id + '"]').html();
SubTeachPair[$(this).attr("id")]['SubCode'] = $(this).attr("id");
SubTeachPair[$(this).attr("id")]['SubName'] =$('label[for="' + this.id + '"]').html();
SubTeachPair[$(this).attr("id")]['SubAbbrev'] =$('label[for="' + this.id + '"]').attr('id');
SubTeachPair[$(this).attr("id")]['TeacherId'] = ui.item.id;
SubTeachPair[$(this).attr("id")]['TeacherName'] = ui.item.value;
// console.log(SubTeachPair);
//window.SubTeachPair = SubTeachPair;
}
}
});
I think I have found the cause of the error -- the object that is the input is actually the out put of another form that uses jquery autocomplete . Now when I enter something in the input and then click on the suggestion, the suggestion is filled in the text input, however if i do not click outside the input text and directly click the button which triggers my script, I get that error. Otherwise its fine. Is there any way to avoid that?
In your code, the array SubSource and count are not defined, You have to declare:
var SubSource = [];
var count = 0`
before for(sub in SubTeachPair) {...}
See http://jsfiddle.net/abu5C/
Try this:
SubSource[count] = {};
for(sub in SubTeachPair) {
console.log(count);
SubSource[count]['label']=SubTeachPair[sub]['label'];
SubSource[count]['value']=SubTeachPair[sub]['value'];
count++;
}