Global counter variable - javascript

im have a code that add and remove dynamically form controls. The add and delete methods works fine. But i like if exist only one control, not remove it.
I defined the next var, outside $(document).ready scope:
var Alumnos = {};
And initialize inside of $(document).ready:
// Valor inicial de casilleros renderizados.
Alumnos.count = 3;
The method that remove controls is:
// Elimina un bloque
$(document).on('click','.closable',function(){
if(Alumnos.count > 1){
var idRow = $(this).attr('data-toggle');
var victim = $(idRow + " .row-fluid:last-child");
victim.remove();
var childs = $(idRow).children();
if(childs.length === 0)
{
$(idRow).remove();
$(this).remove();
Alumnos.count -= 1;
}
}
console.log(Alumnos.count);
return false;
});
The Alumnos.count value persist after delete. Any ideas ?
UPDATE 1
When the user click on "Add more", the code, create a form row with 3 controls, from a prototype.
Because, i cant use children count.
I need the user dont remove all controls.

I think you should have:
if(Alumnos.count >= 1){ //Probably if there is only 1, it's erasable. You had >
And move the decrement outside, like this:
var childs = $(idRow).children();
if(childs.length === 0)
{
$(idRow).remove();
$(this).remove();
}
Alumnos.count -= 1; //This was moved
Hope this helps. Cheers

Thanks for all your replies !! I found the way to control the elements remove with the childs count. May be isnt the best code, but works.
$(document).on('click','.closable',function(){
// Get the id of the row.
var dataToggle = $(this).attr('data-toggle');
// Get the row
var row = $(dataToggle);
// if isnt first row (#id0), ok, remove all if you want.
// if is first row (#id0) and have more than one child, happy remove ^^
if((dataToggle === "#id0" && row.children().length > 1) || dataToggle !== "#id0"){
// remove code...
}
return false;
});

Related

My jquery function is pushing elements to all my arrays

On my website, users can click on some text to open up a Modal. This Modal allows users to choose a bunch of toppings to add to their Pizza.
Through Javascript, I add each selected topping to an array and change the text display to match their selected toppings. This more or less works, but the problem is for some reason, whenever they add a topping, it is added to ALL arrays, not just the item it's selected for. Can someone help me find why this is happening?
// Open Toppings Modal
$(document).ready(function() {
var count = -1
var tplist = []
$(".order").each(function(){
count += 1
tplist.push([])
var listeners = 0
setModal(count, tplist, listeners)
});
function setModal(count, tplist, listeners) {
$("#openModal" + count).click(function(){
console.log("clicked")
$("#toppingModal" + count).modal()
if (listeners == 0) {
listeners += 1
$("input[type='checkbox']").change(function() {
// TODO: Fix Bug
// Adding to all javascript lists
if (this.checked) {
tplist[count].push($(this).val());
console.log(tplist)
}
else {
ele = $(this).val();
pos = $.inArray(ele, tplist[count])
if ( ~pos ) tplist[count].splice(pos, 1);
}
// Change text to list
if (tplist[count].length > 0) {
$("#openModal" + count).text(tplist[count])
}
else {
$("#openModal" + count).text("Select Toppings")
}
})
}
});
};
});
I am suspecting your $("input[type='checkbox']").change(function() {} is called for every model. Try setting count number somewhere when you click select topping and compare inside $("input[type='checkbox']").change(function() {} to prevent adding of toppings in all arrays

Undo ( ctrl + z ) functionality to bring back hidden divs

fiddle http://jsfiddle.net/Q8F5u/3/
I have multiple divs, each having a delete button on its top to delete that particular div(actually i have to hide not delete). After the divs have been deleted I want to retrieve them back by pressing CTRL + Z.
I have had some success in bringing them back. The Logic i have used is that i am pushing the deleted divs id's to a stack and whenever i am pressing ctrl + z, I am popping the last hidden div ID from the stack and using this id to bring back the hidden div.
Here the javascript:
var deletedBlocks = [];
$('.delete').on('click',function(){
var deletedid = $(this).closest('div[id^=block]').attr('id');
deletedBlocks.push(deletedid);
$(this).closest('div[id^=block]').fadeOut(500);
});
$('body').on('keydown',function(e){
//check for ctrl + z key
if( e.ctrlKey && e.which == 90){
if(deletedBlocks.length > 0){
var lastdeleted = deletedBlocks.pop();
$('.container').children('#'+ lastdeleted).fadeIn(1000);
}
else{
alert('NO further Shift to be retrieved');
}
}
});
The problem i am having is that in my real application there's no such unique id's for these divs. instead they all have same classes. How can i implement the same functionality without the div's having unique id's.
If you are just hiding the divs you can actually push the div itself to the stack instead of an ID.
$('.delete').on('click',function(){
var deleted = $(this).closest('div[id^=block]');
deletedBlocks.push(deleted);
deleted.fadeOut(500);
});
$('body').on('keydown',function(e){
//check for ctrl + z key
if( e.ctrlKey && e.which == 90){
if(deletedBlocks.length > 0){
var lastdeleted = deletedBlocks.pop();
lastdeleted.fadeIn(1000);
}else{
alert('NO further Shift to be retrieved');
}
}
});
Note, I just refactored your code. Didn't test it. But you get the idea and it should work.
You might use jQuery's .eq() and .index() methods.
In your line:
var deletedid = $(this).closest('div[id^=block]').attr('id');
You might retrieve the index of the deleted element:
var deletedIndex = $(this).closest('div[id^=block]').index();
Store this index in your array and use .eq() later to undelete the correct element:
$('.container').closest('div[id^=block]').eq(lastdeleted).fadeIn(1000);

AngularJS <select> with ng-model and ng-options gets broken on element delete

I have a selector in v1.3.0-beta.3:
<select
ng-model='selectedPassport'
ng-change="selectPassport(selectedPassport)"
ng-options="passport.number for passport in passports"
required>
</select>
I have a button with ng-click to delete element from passports array:
// delete button handler
$scope.deletePassport = function () {
var delIdx = $scope.passports.indexOf($scope.selectedPassport);
var idx = delIdx;
if (idx > 0) {
idx--;
}
$scope.passports.splice(delIdx,1);
$scope.selectedPassport = $scope.passports[idx];
};
// if I don't do that, I wouldn't be able to use $selectedPassport in my code
$scope.selectPassport = function (pass) {
$scope.selectedPassport = pass;
}
I want to make previous passport to be selected after deleting current passport. But instead of that I get empty passport selected. In DOM model it corresponds to option with value="?", though ng-model points to valid elemnt in ng-options. How can I overcome this?
The problem is that $scope.selectedPassport is going to be an object, and in this case indexOx in this expression
var delIdx = $scope.passports.indexOf($scope.selectedPassport);
will fail to find a corresponding array index. I think you can fix it this way:
$scope.deletePassport = function() {
var delIdx = -1;
for (var i = 0; i < $scope.passports.length; i++) {
if ($scope.passports[i].number === $scope.selectedPassport.number) {
delIdx = i;
break;
}
}
if (delIdx > -1) {
$scope.passports.splice(delIdx, 1);
$scope.selectedPassport = $scope.passports[delIdx];
}
};
Proof of concept: http://plnkr.co/edit/E1BAwS6JHGzQs4gMct7R?p=preview
I made your example into a Plunker example and it seems to be working. You must have forgotten something or messed up your Delete button?
http://plnkr.co/edit/Rs173vmhu1bBubvRS18j
The problem was caused by ng-if= attribute that presented in this element. I didn't put ng-if into source example, because I thought that it is not related to the issue. Each time deletePassport() was invoked, ng-if condition was recalculated automatically by angular and select element was recreated and thus lost selection. Solved by replacing ng-if with ng-show.

Jquery Next and Prev Button Loop function

I have this simple next and previous function that i wrote but i am having one simple issue. On the last slider on click next, it shows a blank slider then on click next it starts all over as it is supposed to. What am i missing? Below is the jquery code;
$('div.contsliders').each(function(e) {
if (e != 0)
$(this).hide();
});
$('span.next').click(function(){
if ($('div.contsliders:visible').next().length != 0)
$('div.contsliders:visible').next().fadeIn(1000).prev().hide();
else {
$('div.contsliders:visible').hide();
$('div.contsliders:first').fadeIn(1000);
}
return false;
});
$('span.prev').click(function(){
if ($('div.contsliders:visible').prev().length != 0)
$('div.contsliders:visible').prev().fadeIn(1000).next().hide();
else {
$('div.contsliders:visible').hide();
$('div.contsliders:last').fadeIn(1000);
}
return false;
});
HERE IS THE JSFIDDLE LINK
I will really appreciate it mates, thanks.
That is because when it checks for the following condition for the div which you think it is the last using $('div.contsliders:visible').next().length gives .contsnextprev (hence length will still be 1 instead of 0 as assumed) so it shows that one instead of moving to the beginning, which happens when you click on it again. It is because .contsnextprev is the div next to the last slide #five.
if ($('div.contsliders:visible').next().length != 0)
$('div.contsliders:visible').next().fadeIn(1000).prev().hide();
You can change it to:
var $nxt = $('div.contsliders:visible').next('.contsliders');
if ($nxt.length != 0)
$nxt.fadeIn(1000).prev().hide();
Demo
Infact you can simplify this to just one handler as well:
$('div.contsliders:gt(0)').hide(); //Hide all but the first one
var $allSlides = $('div.contsliders'),
traverseDefault = "first", //set the defaults
actionDefault ="next";
$('span.next, span.prev').click(function(){
var traverse = traverseDefault,
action = actionDefault;
if($(this).is('.prev')){ //if action is prev
traverse = "last"; //set traverse to last in case nothing is available
action = "prev"; //set action to prev
}
var $curr = $allSlides.filter(':visible'), //get the visible slide
$nxtTarget = $curr[action](".contsliders"); //get the next target based on the action.
$curr.stop(true, true).fadeIn(1000).hide(); //hide current one
if (!$nxtTarget.length){ //if no next
$nxtTarget = $allSlides[traverse](); //based on traverse pick the next one
}
$nxtTarget.stop(true, true).fadeIn(1000); //show the target
});
Demo

Javascript next button array

I am unrehearsed in javascript and was hoping for some help with a next button that links to an id based on the array. Here is the array
var baseline_next=new Array();
baseline_next[0]="#one";
baseline_next[1]="#two";
baseline_next[2]="#three";
baseline_next[3]="#four";
baseline_next[4]="#five";
baseline_next[5]="#six";
baseline_next[6]="#six2";
baseline_next[7]="#seven";
baseline_next[8]="#eight";
baseline_next[9]="#nine";
baseline_next[10]="#ten";
baseline_next[11]="#eleven";
baseline_next[13]="#thirteen";
baseline_next[14]="#fourteen";
baseline_next[15]="#fifteen";
baseline_next[16]="#sixteen";
baseline_next[17]="#seventeen";
baseline_next[18]="#eighteen";
baseline_next[19]="#nineteen";
baseline_next[20]="#twenty";
baseline_next[21]="#twentyone";
baseline_next[22]="#twentytwo";
baseline_next[22]="#twentythree";
Basically what I need is, when the next button is clicked first ("0" ~ #one) I need the next buttons id to become two, and when clicked again it needs to become #three. I have no idea how to link an array to a button. The reason I need this to happen is because I am using ajax to .load div contents, so the next button doesn't actually submit, it just becomes a new next button. I dont know if it matters, but here is a part of what the button would cause to happen on click.
$('#one').click(function(){
$("#area").hide("slide", { direction: "left" }, 500);
$("#area").load("test_it.jsp #area");
$("#area").show("slide", { direction: "right" }, 500);
$("#two").show();
});
$('#two').click(function(){
if((document.form1.baseline_01[0].checked || document.form1.baseline_01[1].checked| document.form1.baseline_01[2].checked)
&& (document.form1.baseline_02[0].checked || document.form1.baseline_02[1].checked)
&& (document.form1.baseline_03_native.checked || document.form1.baseline_03_asian.checked|| document.form1.baseline_03_black.checked|| document.form1.baseline_03_pacific.checked|| document.form1.baseline_03_white.checked|| document.form1.baseline_03_other.checked)){
if(document.form1.baseline_03_other.checked && document.form1.baseline_03_other_text.value==""){
alert("Please fill in what other race you concider yourself to be.");
return false;
}else{
$("#area").hide("slide", { direction: "left" }, 500);
$("#area").load("test_it.jsp #area2");
$("#area").show("slide", { direction: "right" }, 500);
$("#three").show();
return true;
}
}else{
alert("Please select an answer for each question.");
return false;
}
});
I must apologize in advanced if my question is hard to follow, I just started coding this year.
I think that you should consider reworking your code a bit to not have this list of IDs and use a single class on all of the elements. It would help to see how your HTML is set up to get the next element based on class as well.
Since you already have this array of doom, though, I guess we'll have to use it. Ideally, you have the same class on each element. Let's say, .number.
$(".number").on('click', function () {
var nextID = baseline_next.indexOf(this.id) + 1;
});
If you can't use .number, then you can do the same thing except with a list of every ID that needs to be bound .. ouch. In the above function, nextID should be the index of the ID that comes after the clicked element.
By the way, IDs can be numbers, and you could even use data-id that contains the number. That would be easier too.
OK I really need to ask why are you doing this, are you sure that creating more than 20 ID's called like that is the better way to do want you want?
Anyways, first of all, you can create the array in a shorthand way:
var baseline_next= ["#one", "#two", "#four", "#five", "#six", "#six2" ..., "#twentythree";
(btw "#six2"? really?)
then do something like this:
var counter = 0; // start for the first one
$("#button").on('click', function () {
var id = counter++;
baseline[id]; // and I don't know what you want to do with this, but here it is!
});
Ancient question. (7 years wowzers). Here is some logic that I used for determining the next item in an array using indexOf. This will also start from the beginning once you reach the end of your array.
let options = [true,false,null];
let current = options.indexOf(this.get('order'));
let next = (current+1 > options.length-1 ? 0 : current+1);
this.set('order', options[next]);
It can be simplified as follows:
let baseline_next = ["#one", "#two", "#three"];
Don't use a var as it behaves unpredictably.
Add a variable count to change the index of the array.
let count = 0;
let baseline_next = ["#one", "#two", "#three"];
$(baseline_next[count]).click(function() {
count++;
});
Or
let count = 0;
let baseline_next = ["#one", "#two", "#three"];
$("#one").click(function() {
$(baseline_next[count]).click();
count++;
});

Categories