plus minus button with specific parent input doesn't work - javascript

as you can see here jsfiddle.net/TTU4Z/1/
The jquery code in question is below and if i run it without all my code (like in jsfiddle) it run perfectly. but with all my code doesn't run.
$(document).ready(function() {
// This button will increment the value
$('.plus').click(function(e){
// Stop acting like a button
e.preventDefault();
// Get the field name
fieldName = $(this).attr('field');
// Get its current value
var currentVal = parseInt($('input[id='+fieldName+']').val());
// If is not undefined
if (!isNaN(currentVal)) {
// Increment
$('input[id='+fieldName+']').val(currentVal + 1);
} else {
// Otherwise put a 0 there
$('input[id='+fieldName+']').val(0);
}
});
// This button will decrement the value till 1
$(".minus").click(function(e) {
// Stop acting like a button
e.preventDefault();
// Get the field name
fieldName = $(this).attr('field');
// Get its current value
var currentVal = parseInt($('input[id='+fieldName+']').val());
// If it isn't undefined or its greater than 0
if (!isNaN(currentVal) && currentVal > 0) {
// Decrement one
$('input[id='+fieldName+']').val(currentVal - 1);
} else {
// Otherwise put a 0 there
$('input[id='+fieldName+']').val(0);
}
});
});
Clicking on "add" button all is good, but when you click in one of minus or plus button it delete all.
It should increase or decrease the val of the relative input as you can see, but nothing change if i try to edit everything in those functions.
What to do?

Since you are appending elements dynamically you have to use event delegation in this situation. Actually the registered events are not invoking in your context, that's why the buttons are exhibiting their original behavior.
Try,
$(document).on('click','.plus',function(e){
and
$(document).on('click','.minus',function(e){
Additionally, the selector that you are framing dynamically contains some meta-characters, just pass that as a string or you have to escape it, in order to make your code work properly.
DEMO
New Demo after fixing your concatenation issues. And in that demo, i just removed the attribute selectors like [id='blah'] and replaced that with $('#blah').
DEMO - I

See updated fiddle http://jsfiddle.net/LfNmh/
You had your x variable inside the code string where it should have been in the code. line 15 ..
var numPortata = '<td><button class="minus" field="portata'+x+'">-</button><input id="portata'+x+'" type="number" name="numPortata[]" value="1" size="10" min="1" max="10" step="1" required><button class="plus" field="portata'+x+'">+</button></td>';
I also changed the code so that the events are attached at the document level as Rajaprabhu said.

Related

Dynamically Added button, jquery not working

I've been going through my dynamically added code and changing everything that was using .click() to use .on("click") and its been working great but now I've run into something that I am not sure how to convert to dynamically added compatible.
Here is the code: This is a function in javascript that is called when a button named "Add" or "Remove" is clicked (these buttons are also dynamically added after another button is clicked)
function row_add_remove(sname, snum, count, type) {
if (type == "add") {
var selectbox = '<select id="qty_'+snum+'_'+count+'" name="qty_'+snum+'_'+count+'">';
for (i=1;i<16;i++){selectbox += '<option value='+i+'>'+i+'</option>';}
selectbox += '</select>';
if (count > 1) {
$("#tr_"+sname+"_"+(count-1)).after('<tr id="tr_'+sname+'_'+count+'"><td>'+selectbox+' X <input type=text id="item_'+sname+'_'+count+'" name="item_'+snum+'_'+count+'" size="70" placeholder="Item '+count+'" /></td></tr>');
$("#toprow"+snum+"_count").html("("+count+")");
}
}
if (type == "remove") {
if (count == 1) {
$("#"+sname).hide();
$("#toprow"+snum+"_count").html("");
$("#td_"+sname+"_"+count).remove();
$("#ph_order_div").show();
count--;
}
if (count > 1) {
$("#tr_"+sname+"_"+count).remove();
count--;
$("#toprow"+snum+"_count").html("("+count+")");
}
if (count < 0) {count = 0;}
}
}
The problem (I think, maybe its more than this) is the .after() doesn't fire. Now i'm not sure if the problem lies with that or with the whole code but when I click the Add button its not adding another TR after the one that is shown by default.
This code works great when NOT dynamically added so can anyone help me with what I need to change to get the above function to work when the buttons that call it and the TR's that it tries to modify are dynamically added?
Here is the code that is fired when the buttons are clicked:
whatmeatfield = $("#meat_field_count").html();
$(document).on("click", "#add_btn_1", function() {
if (whatmeatfield <= 0) {whatmeatfield = 1;}
whatmeatfield++;
row_add_remove("meatseafood",1,whatmeatfield,"add");
});
$(document).on("click", "#remove_btn_1", function() {
row_add_remove("meatseafood",1,whatmeatfield,"remove");
whatmeatfield--;
if (whatmeatfield <=0) {whatmeatfield = 1;}
});
in your .after(), there is typo mistake in <input type=text there should be quote like <input type="text"
You have not define whatmeatfield variable. it should be
var whatmeatfield
Also you are directly passing html of some element id, you need to parse it to integer. like
var whatmeatfield = parseInt($("#meat_field_count").html()) ;
This may help you to solve your issues
The problem may occur becouse of two things.
You're using id selector and you're porobably adding another button with the same id and as far as html spec says id should be unique.
What can you do?
Change ID to CLASS.
The problem occurs becouse you're changing the id to schema like #remove_btn_1, #remove_btn_2, #remove_btn_3 and therefore you do not have any handler for this buttons.
What can you do?
Change selector from "#remove_btn_1" to "[id*=remove_btn_]"
Of course same with #add_btn_
Post me back if it was helpful.

Block btn until at least 1 checkbox of an offset is selected

A little frustrated here, somehow I can't make this work no matter what I try. I have a small form with 2 offsets, each containing a few checkboxes as the following:
<input type="checkbox" id="test1" /><label for="test1">
I need to make sure the user selects at least one of them in each offset in order to be able to click this button, otherwise it should be unclickable :)
<div class="offset6">
<a class="btn btn-warning" href="#openModal">CONTINUAR<span class="btn_caret"></a>
</span></button>
</div>
This should work for you:
//listen for changes to any checkbox so we can re-evaluate the button state
$("input[type='checkbox']").change(function(){
validateInput();
});
//checks to see if the button should be enabled or not
function validateInput(){
//get the count of checked items in each of the offsets
var offset3Count = $(".offset3").find("input[type='checkbox']:checked").length;
var offset8Count = $(".offset8").find("input[type='checkbox']:checked").length;
//set the disabled state of the button based on the offset counts
$(".btn").prop("disabled", offset3Count == 0 || offset8Count == 0);
}
//call the function on page load to ensure the button is initially disabled
validateInput();
Here is a working example (I had to change your HTML a bit as it was invalid)
If you need a specific .btn, as in the one in offset6, then use this line instead:
$(".offset6 .btn").prop("disabled", offset3Count == 0 || offset8Count == 0);
Here is the example
A quick recommendation: If you have unique elements then consider using an id attribute for them. For example:
<button id="btn6" ...>
With the following JQuery selector:
$("#btn6")...
Try
var chk = $(".offset3,.offset8").find('input[type="checkbox"]'); //cache your selector
chk.change(function () {
$('div.offset6 a.btn.btn-warning[href="#openModal"]').prop('disabled', chk.filter(':checked').length);
});
chk.filter(':checked').length get length of checked checboxes
$('.btn').prop('disabled', $('input[type="checkbox"]:checked').length);
Updated After OP's Comment
$('div.offset6 a.btn.btn-warning[href="#openModal"]').prop('disabled', $('input[type="checkbox"]:checked').length);
or add and id to than use # id-selector

jQuery: focusout triggering before onclick for Ajax suggestion

I have a webpage I'm building where I need to be able to select 1-9 members via a dropdown, which then provides that many input fields to enter their name. Each name field has a "suggestion" div below it where an ajax-fed member list is populated. Each item in that list has an "onclick='setMember(a, b, c)'" field associated with it. Once the input field loses focus we then validate (using ajax) that the input username returns exactly 1 database entry and set the field to that entry's text and an associated hidden memberId field to that one entry's id.
The problem is: when I click on the member name in the suggestion box the lose focus triggers and it attempts to validate a name which has multiple matches, thereby clearing it out. I do want it to clear on invalid, but I don't want it to clear before the onclick of the suggestion box name.
Example:
In the example above Paul Smith would populate fine if there was only one name in the suggestion list when it lost focus, but if I tried clicking on Raphael's name in the suggestion area (that is: clicking the grey div) it would wipe out the input field first.
Here is the javascript, trimmed for brevity:
function memberList() {
var count = document.getElementById('numMembers').value;
var current = document.getElementById('listMembers').childNodes.length;
if(count >= current) {
for(var i=current; i<=count; i++) {
var memberForm = document.createElement('div');
memberForm.setAttribute('id', 'member'+i);
var memberInput = document.createElement('input');
memberInput.setAttribute('name', 'memberName'+i);
memberInput.setAttribute('id', 'memberName'+i);
memberInput.setAttribute('type', 'text');
memberInput.setAttribute('class', 'ajax-member-load');
memberInput.setAttribute('value', '');
memberForm.appendChild(memberInput);
// two other fields (the ones next to the member name) removed for brevity
document.getElementById('listMembers').appendChild(memberForm);
}
}
else if(count < current) {
for(var i=(current-1); i>count; i--) {
document.getElementById('listMembers').removeChild(document.getElementById('listMembers').lastChild);
}
}
jQuery('.ajax-member-load').each(function() {
var num = this.id.replace( /^\D+/g, '');
// Update suggestion list on key release
jQuery(this).keyup(function(event) {
update(num);
});
// Check for only one suggestion and either populate it or clear it
jQuery(this).focusout(function(event) {
var number = this.id.replace( /^\D+/g, '');
memberCheck(number);
jQuery('#member'+number+'suggestions').html("");
});
});
}
// Looks up suggestions according to the partially input member name
function update(memberNumber) {
// AJAX code here, removed for brevity
self.xmlHttpReq.onreadystatechange = function() {
if (self.xmlHttpReq.readyState == 4) {
document.getElementById('member'+memberNumber+'suggestions').innerHTML = self.xmlHttpReq.responseText;
}
}
}
// Looks up the member by name, via ajax
// if exactly 1 match, it fills in the name and id
// otherwise the name comes back blank and the id is 0
function memberCheck(number) {
// AJAX code here, removed for brevity
if (self.xmlHttpReq.readyState == 4) {
var jsonResponse = JSON.parse(self.xmlHttpReq.responseText);
jQuery("#member"+number+"id").val(jsonResponse.id);
jQuery('#memberName'+number).val(jsonResponse.name);
}
}
}
function setMember(memberId, name, listNumber) {
jQuery("#memberName"+listNumber).val(name);
jQuery("#member"+listNumber+"id").val(memberId);
jQuery("#member"+listNumber+"suggestions").html("");
}
// Generate members form
memberList();
The suggestion divs (which are now being deleted before their onclicks and trigger) simply look like this:
<div onclick='setMember(123, "Raphael Jordan", 2)'>Raphael Jordan</div>
<div onclick='setMember(450, "Chris Raptson", 2)'>Chris Raptson</div>
Does anyone have any clue how I can solve this priority problem? I'm sure I can't be the first one with this issue, but I can't figure out what to search for to find similar questions.
Thank you!
If you use mousedown instead of click on the suggestions binding, it will occur before the blur of the input. JSFiddle.
<input type="text" />
Click
$('input').on('blur', function(e) {
console.log(e);
});
$('a').on('mousedown', function(e) {
console.log(e);
});
Or more specifically to your case:
<div onmousedown='setMember(123, "Raphael Jordan", 2)'>Raphael Jordan</div>
using onmousedown instead of onclick will call focusout event but in onmousedown event handler you can use event.preventDefault() to avoid loosing focus. This will be useful for password fields where you dont want to loose focus on input field on click of Eye icon to show/hide password

Can't get sessionStorage to work correctly

I have multiple buttons that when they are clicked an image is loaded and the image is supposed to stay there based even when the page refreshes. When I use this the button with the highest setItem value always shows even if I click on other button. How do I fix this?
here is one of the scripts:
<script type="text/javascript">
var isImage1 = sessionStorage.getItem('2');
function showImage1() {
sessionStorage.setItem('isImage1', '2');
$("#loadingImage1").show();
$("#loadingImage").hide();
$("#loadingImage2").hide();
$("#loadingImage3").hide();
$("#loadingImage4").hide();
$("#loadingImage5").hide();
$("#loadingImage6").hide();
}
if(isImage1 == 2) showImage1();
</script>
and here is one of my buttons:
<input name="EPL/MECH DESIGN - TECHS" style="white-space:normal"
onclick="moveText(this.name);showImage1();form1.submit()"
style="width: 275px" type="button" value="7SBD EPL/Mech. Design Techs" />
Update: I have updated this line
var isImage1 = sessionStorage.getItem('2');
to
var isImage1 = sessionStorage.getItem('isIamge1');
but my issue still exists, that the isImage with the largest value stays even when i click the other buttons, so help is still needed.
In your session storage, you are setting the value of the 'isImage1' Item to '2'
sessionStorage.setItem('isImage1', '2');
But in your code to retrieve the value you are actually retrieving the item '2'
var isImage1 = sessionStorage.getItem('2');
You need to change your sessionStorage.getItem to reference 'isImage1'
var isImage1 = sessionStorage.getItem('isImage1');
Then you should get the value you are expecting.
There are loads of good jsfiddles on session storage. you may get some ideas from this one:
http://jsfiddle.net/gabrieleromanato/XLRAH/
Incidently; this is a very small value you are storing, why not store it in a cookie instead?
EDIT:
based on the fact that you have multiple functions exactly like this one, you are better off following Ken's solution, the only thing I would add is a wildcard to turn off the other images:
function showImage(imgNum) {
sessionStorage.setItem('Image',imgNum);
$("[id^=loadingImage]").hide();
$("#loadingImage" + imgNum).show();
}
showImage(sessionStorage.getItem('Image'));
The code in the buttons would then be showImage(1) instead of showImage1();
_Pez
By re-factoring the code a little you can do something like this:
/// setup some vars including max number of images
var maxImages = 6, i = 1, v;
/// now loop through and get the items for each image
for(; i =< maxImages; i++) {
v = sessionStorage.getItem('isImage' + i);
/// if in storage, call show image with the number to show
if (v !== null) showImage(i);
}
/// show image based on number
function showImage(num) {
sessionStorage.setItem('isImage' + num, '1');
$("#loadingImage" + num).show();
}
Also note that sessionStorage only deals with strings. So in order to check a specific number you need to convert it to one first parseInt(value, 10);.
But in this case the 1 that we set can be anything - it's just to store some value so sessionStorage doesn't return null.
In the button code you can change it to do this:
<input name="EPL/MECH DESIGN - TECHS" style="white-space:normal"
onclick="moveText(this.name);showImage(1);form1.submit()"
style="width: 275px" type="button" value="7SBD EPL/Mech. Design Techs" />

jquery return value of input to var

I'm trying to make a variable equal the value of the text box. I have the text box value being set to a variable and returned as an alert (for now) but I can't figure out how to call that variable from other functions.
$('#max_char').keyup(function () {
var max_char = $(this).val();
alert(max_char + ' Handler for .keyup() called.');
});
var count_options = {
'maxCharacterSize': max_char,
'originalStyle': 'originalDisplayInfo',
'warningStyle': 'warningDisplayInfo',
'warningNumber': 40,
'displayFormat': '#input Characters | #left Characters Left | #words Words'
};
$('#textinput').textareaCount(count_options);
});
HTML
<textarea cols="68" rows="21" name="textinput" id="textinput"></textarea><br/>
<input type="textbox" id="max_char" name="max_char" value="-1" /> Max Characters <br/>
Any help would be great. Trying to add the var max_char to the maxCharacterSize of count_options
All you need to do is declare max_char in a higher scope, i.e. outside of the keyup function:
var max_char;
$('#max_char').keyup(function () {
max_char = +$(this).val();
alert(max_char + ' Handler for .keyup() called.');
});
Also note that I put a + in front of $(this).val() to convert it from a string into a number, since "1" + 1 == "11".
Update:
The reason the textareaCount plugin isn't working is because it is initialised once, on document ready. At this time, max_char is nothing because the user hasn't typed anything yet.
You'd have to either reconfigure or re-initialise the plugin on every keyup to get the effect you're after. Unfortunately the plugin doesn't document an easy way to do this. After digging through the plugin's source code, I think there are only 3 events it binds that you need to revert, before you can simply re-initialize it again. Try this out:
var count_options = {
'maxCharacterSize': 100, // Just some default value
'originalStyle': 'originalDisplayInfo',
'warningStyle': 'warningDisplayInfo',
'warningNumber': 40,
'displayFormat': '#input Characters | #left Characters Left | #words Words'
};
// Initialise the plugin on document ready
$('#textinput').textareaCount(count_options);
$('#max_char').keyup(function () {
var max_char = +$(this).val();
count_options.maxCharacterSize = max_char;
// Unbind the 3 events the plugin uses before initialising it
$('#textinput')
.next('.charleft').remove().end()
.unbind('keyup').unbind('mouseover').unbind('paste')
.textareaCount(count_options);
});
If I understand you correctly, if you declare the var within the global scope of javascript
Or if you directly access the input with
$("#max_char").val()
parseInt($('#max_char').val())

Categories

Resources