Changing Array causing glitches with splice - javascript

I have a form event which takes entered values and constructs an array out of them using the following:
keywordArray = []
var getVal = $('#search').val();
if(getVal.length > 1){
keywordArray.push(getVal);
$('.test').on('click', function(){
removeTag(this, getVal);
});
$('#search').val("");
}
My remove function then looks as follows:
function removeTag(el, getVal){
var index = keywordArray.indexOf(getVal);
keywordArray.splice(index, 1);
}
There is no problem when removing a value for the first time as the index is in sync, but once a value is removed the index changes and it seems that JS isn't staying in sync with the updated index, so when I remove another value it glitches with a -1 on splice and will remove all values.

I see two problems: Your removeTag function and the way it is called.
First of all, removeTag() does not need the element, so remove the el parameter if it is really not needed. Second, it should do nothing when the given string does not occur in the array:
function removeTag(val){
var index = keywordArray.indexOf(val);
if (index >= 0) keywordArray.splice(index, 1);
}
The second problem might be related to this part of your code:
$('.test').on('click', function(){
removeTag(this, getVal);
});
I suspect that you don't want to register a click handler for all '.test' elements because you refer to this in the next line but this is not used in the removeTag function (see above). In case there are several '.test' elements, you should make sure that removeTag() is only called with the value that corresponds to the clicked '.test' element. Currently you call removeTag() several times for each click -- once for each '.test' element.

The main problem is pointed out by #vijayP in the comments. Here is a first possible solution.
When adding a tag, use the data attribute to associate the tag with the remove button (el):
function addTag(el, value) {
$(el).data('value', value).on('click', removeTag);
}
I assume you have a separate remove button for each tag. Then, the click handler function can look like this (with the check for a correct index):
function removeTag(){
var index = keywordArray.indexOf($(this).data('value'));
if (index > -1) keywordArray.splice(index, 1);
}

Related

Clearing empty element from array

Hello i am not sure why those empty elements still there even i clear (or clear function does not work guess). Might you guys have a look on this. I am getting this array after add another value into same array.I am asking whats is happening behind not just solving code thank you
this is function when ever i click button it adds 4 into DVALUE array.
if("q"+idcount+"d" == this.id){
DVALUE[dcount++] = 4;
// alert("D ARRAY"+DVALUE.toString());
}
And this is when ever i click revert button it will remove last added number
if ("d" === qwer) {
// alert(""+DVALUE.toString());
DVALUE.pop();
cleararrayD(); // also calling this function to remove empty elements when ever this if occurs
}
And this is cleararrayD Function
function cleararrayD() {
lens = DVALUE.length, i;
for (i = 0; i < lens; i++) DVALUE[i] && DVALUE.push(DVALUE[i]); // copy non-empty values to the end of the array
DVALUE.splice(0, lens);
}
I am asking whats is happening behind not just solving code
The .length of DVALUE array does not change at cleararrayD() function call as an element is .push()ed to DVALUE array for each index of DVALUE before .splice() is called with original array .length at second parameter, removing the preceding elements to the elements .push()ed to the array.
Okey i got answer for my question. As you can see it clears array but i put element at wrong indexes. Everytime i click button Dcount++ adding indexes so i just doing this Dcount-- in my removing functions
DVALUE[dcount++] = 4;

Every time user clicks on the button I need the next value from the array in Javascript

I'm currently trying to loop an array in a function. This function supposed to be used for a button, which gives every time a different value from the array when its pressed.
var list=['DEFAULT','ADVANCED','DEVELOPMENT'];
Every time user clicks on the button i need the next value from the array. (when its "DEVELOPMENT", next should be "DEFAULT"). Is it possible to do it without using a global variable ?
If you fine with changing array chiliNUT's answer would work (shift/push to implement circular buffer).
Alternatively you can keep current selection and loop that with %. To avoid global variables wrap counter in a function to capture value.
Sample (assuming usage of JQuery, you can find equivalent addEventListener code yourself):
$(function()
{
// outside of click handler to be able to preserve values between clicks
var current = 0;
$("button.next").click(function()
{
alert(list[current]);
current = (current + 1) % list.length;
});
}
<button class="next">Next</button>
something like this. shift pulls off the first element. push sends it to the back.
var list=['DEFAULT','ADVANCED','DEVELOPMENT'];
function nextWord() {
var word=list.shift();
list.push(word);
console.log(word);
return word;
}
nextWord();//DEFAULT
nextWord();//ADVANCED
nextWord();//DEVELOPMENT
nextWord();//DEFAULT
nextWord();//ADVANCED
nextWord();//DEVELOPMENT
//...
<button onclick=nextWord()>Next Word</button>

Trigger event not working or suspected passing on index

.full-arrow is an arrow that selects the next page. .full-navigation is a navigation bar, quite simply boxes in a line that change colour when you select them. The rest of the function isn't on here but you get the general idea.
When I create a trigger event to the function below the first one, it goes through okay but I'm unsure whether it's not picking up the index() or whether it's just not working at all. Weirdly, it works the first time but I think that's because the same_page variable is declared as 0 in the beginning.
The reason I'm also doubting whether it's the index() not being passed on is because the alert("foo"); isn't coming up.
$(".full-arrow").click(function() {
$(".full-navigation li:eq(" + same_page+1 + ")").trigger("click");
});
$(".full-navigation li").click(function(event) {
//alert("foo");
//alert(same_page);
same_page = $(this).index();
if(same_page == $(this).index()) { return false; }
});
Where are you getting the same_page variable from? Try using parseInt( same_page, 10 )--I have a hunch it's actually a string.

Trying to get some jQuery functions to run in order. Is callback the issue?

I'm trying to do some things in order, and I'm having some trouble.
When the button with the id #sub_button is clicked,
Make sure each element with class ".verify" has it's own object value (see code)...
... if not, blur that element (will run some other code and create an object for it).
AFTER the above IF check is COMPLETE (now all elements should have an object), THEN run function "isitgood". (The "isitgood" function is running before all elements get their object values, which is done on blur)
$("#sub_button").click(function() {
$(".verify").each(function(){
objtitle = $(this).attr('id');
if (!myObj[objtitle]) {
$("#"+objtitle).blur(); // Define anything undefined
}
}); // end each
isitgood();
}); // end click function
function isitgood(){
if (myObj.login_id == "ok" && myObj.email == "ok") {
// submit the form
} else {
// shows error
}
}
Also, once I get this executing in the right order, it would be nice to do some sort of .each loop to check if all the object values == "ok" instead of specifying all of them in the function. All of the names of the objects (ie. login_id, email) are the ID attr of any element with class name .verify.
Well, you could do a quick index check in the click callback:
var sub_buttons = $("#sub_button");
sub_buttons.click(function() {
$(".verify").each(function(index){
objtitle = $(this).attr('id');
if (!myObj[objtitle]) {
$("#"+objtitle).blur(); // Define anything undefined
}
if (index == sub_buttons.length - 1)
isitgood();
}
}); // end each
}); // end click function
This will check if you're on the last element in the jQuery object, and if so, will run the isitgood() function. This way, you make sure that you're finished with the $.each method before executing isitgood()
Javascript is asynchronous. Your isitgood() will always fire while .each is still doing it's thing.
That said from your code it's not clear what you're trying to accomplish. The way you're using .each seems to indicate that you have multiple of the same ID attributes on your tags. That won't work, IDs have to be unique. Also you seem to be mixing jQuery and regular Javascript. Use one or the other. Actually just use jQuery, you'll save yourself time and effort!
If you do have unique ids then you shouldn't need the .each at all. Just check the appropriate ids with your if statement.
Please provide more of your code and i can update this with a better answer. For instance what does your myObj look like? How do elements of it get the value of ok? It doesn't seem to get set within your call to .each().

how the code is executed?

setInterval((function() {
var index = -1;
return function() {
var all = $('#latest a');
if (index >= 0) {
all.eq(index).hide();
}
index++;
if (index == all.length) {
index = 0;
}
all.eq(index).show();
};
})(), 1000);
how the code is executed? when index = -1; it not fits the first if condition, then the code goes to execute index++; now the index=0, then which step the code will be executed? if (index >= 0) or if (index == all.length) why?
i can't follow the first parameter of the setInterval well. could you explain it with more datails. thank you,
SetInterval call the function in the first parameter every second.
I will split you code into a semantically equivalent one to be more clear
timedFn = (function() {
var index = -1;
return function() {
var all = $('#latest a');
if (index >= 0) {
all.eq(index).hide();
}
index++;
if (index == all.length) {
index = 0;
}
all.eq(index).show();
};
})();
setInterval(timedFn, 1000);
timeFn is a closure and then the index variable value is retained between the different calls.
At the first call, index is -1, and then the execution skip the first if and the control go to the index++ instruction (likely the '#latest a` link are all hidden at the first run so you don't have to hide anything)
Now, a digression before we can continue:
You should know that eq method is applied to a collection
of elements and retrieve the zero based nth element of the collection it is applied to.
If you have a collection of three elements you can address them by eq(0)..eq(2) and
this is why you step into this >strange if. it is a guard that means if you pass over
the last element of my collection >the restart from the first one.
The updated index now contains 0 and, if the collection is empty you will have a bug as the index remains unchanged (index=0 but index is already zero) and the show will attempt to display a non existent element.
By the last instruction the first link is displayed and the execution stops.
After a second the function is called a second time but this time the index star at 0, not -1 and then the execution is repeated:
hide the first element
add 1 to index
if there is just an anchor in your set then reset the index to zero
show the second elements
the function ends
After another seconds the function is called again but you should already know how it works.
You can google on closures to have an indeep view of their inner working or just refer, as a starting point, to How do JavaScript closures work? on Stackoverflow itself.
The first parameter to setInterval, which when simplified looks like this:
(function() {
var index = -1;
return function() {
// some code that can access index
};
})()
defines an anonymous function expression that is immediatedly executed (note that at the end of the function definition it has () causing the execution). When this outer function is executed it returns the inner anonymous function, where due to the magic of closures the inner (nested) function has access to the index variable defined in the outer function.
setInterval expects a function expresssion/reference as its first parameter, which means it is happy if the above structure is passed in as the first parameter since the above returns a function.
The point of all that is essentially to keep the functionality self-contained, rather than declaring a "plain" function that uses a global variable called "index".
As for what the code within the function actually does, well, it will be executed every 1000ms. If index >= 0, which it will be every time except the first time, then all.eq(index).hide(); will be executed - I assume this hides the element that matches the current index. index is then incremented, with the second if setting it back to 0 if it reaches the maximum number of elements in all, essentially ensuring that the code will keep cycling through the elements. Finally the element at the (newly incremented) index is shown.
Presumably all of these elements are hidden to begin with such that the overall effect is to show and then hide one element at a time, changing once per second.
If index=0, then the all.eq(index).hide() will be executed. The second if could also be executed, but only if all.length = 0.

Categories

Resources