JavaScript function not getting called? - javascript

So I have a button that calls
<a class="btn btn-primary" id="btnAdd" href="#" onclick="ChangesJs.AddPlayList()"> <i class="fa fa-fw fa-plus fa-lg"></i>Add </a>
and the JS function creates additional form on its own.
function AddPlayList() {
var form = "<div class='form-group col-sm-3 clscommercial_" + addPlayList + "' style='display:none;' ><label>Break No.</label> <span class='red_color'>*</span><input class='form-control' id='txtBreakno_" + x + "' maxlength='2' onblur='ChangesJS.IsNumeric(this)' onchange='CommonJs.HideErrorMessage(this)' placeholder='Break No.' type='text'></div>";
This is the definition of IsNumeric function
function IsNumeric(selectinput) {
var _value = selectinput.value;
var ID = selectinput.id;
if (_value !== "" && !$.isNumeric(_value)) {
$("#div_" + ID).show();
$("#span_" + ID).html("Please Enter numeric value !");
selectinput.value = "";
selectinput.focus();
}
}
When I get of out focus in the text field no validation is shown.

The elements created in the dom after initial load need to have an event listener added.
function AddPlayList() {
var form = "<div class='form-group col-sm-3 clscommercial_" + addPlayList + "' style='display:none;' ><label>Break No.</label> <span class='red_color'>* </span><input class='form-control' id='txtBreakno_" + x + "' maxlength='2' onblur='ChangesJS.IsNumeric(this)' placeholder='Break No.' type='text'></div>";
// append it to the DOM....
var element = document.getElementsByClassName("clscommercial_" + addPlayList);
element.addEventListener('change', function() {
CommonJs.HideErrorMessage(this);
}, false);
}
Also, don't forget to remove the listener if you remove the element it you may end up having it fire multiple times.
The jQuery way handles this well if your using it.
$('body').on('change', '.clscommercial', function() {
// This will fire even on elements added programmatically as long
// as your top selector is (body) was created on page load.
CommonJs.HideErrorMessage($(this)[0]);
)};

Related

closure loop in ajax callback

i have a data which were parsed from json, i display the data in a box like facebook's friends suggestion box. i want when the user click on any of the suggested users the request to be added to DB via ajax and its corresponding button disappears,everything is working just fine except the last thing(button disappears) instead the very first button in the list gets disappear, while im searching for a solution to my problem i came across something called closure but i reaaly couldn't know how to implement it in my code, another problem appeared when i tried to declare the listener anonymous function inside the loop was the data get inserted in the DB multiple times
(because its inside a loop), i know it might seems duplicated question but i just need someone pointing me the right place to declare my inner function,
my code looks like this
$(document).ready(function() {
var suggest = new XMLHttpRequest();
suggest.onreadystatechange = function() {
if (suggest.readyState === 4 && suggest.status === 200) {
var susers = JSON.parse(suggest.responseText);
for (var i = 0; i < susers.length; i += 1) {
var sphoto = '<div class="col-md-4 text-left "> <div id="fimage">';
sphoto += '<img width="50" height="50" src="user/';
sphoto += susers[i].activation + '/' + susers[i].pic + '"> </div> </div>';
var sname = '<div id="fname">' + susers[i].name + '</div>';
// here is the form im targetting to pull informtion from
var hidden = '<form id="fform"><input id="fnameh" name="name" type="hidden" value="' + susers[i].name + '" >';
hidden += '<input name="id" type="hidden" value="' + susers[i].id + '" >';
var fbutton = '<button id="addfriend"class="btn btn-info btn-xs pull-right text-center" type="submit" >Follow <span class=" glyphicon glyphicon-plus" aria-hidden="true"></span> </button></form';
var display = document.getElementById('fsuggest');
display.innerHTML += '<div class="scroller"><div id="fspace" > <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' + sphoto + sname + hidden + fbutton +'</div></div>'
$('#addfriend').live('click', function(arg) {
return function() {
arg.preventDefault();
var data = $('#fform').serialize();
$.ajax({
data: data,
type: "post",
url: "addnew.php",
success: function(data) {
//make the text area empty
$('#addfriend').css("display", "none");
console.log(data);
}
}); // end of $.ajax
}(i); // end of inner function
}); // end of click listner
} //end of for loop
}
};
suggest.open('GET', 'box.php');
suggest.send();
}); // end of JQUERY ready
I am not sure why exactly you need closure here. The problem seems to be with the multiple form & button with same id.
All these buttons have same id so the forms. So
$('#addfriend').live('click', function(arg) {..}) has no reference to the particular button
Hope this change will help
Con-cat the value of iwith the id of the form & add an attribute data-id=i the button.
Beside instead of id add class addfriend to the button. So when this button will be clicked take the data-id value. Use this value to get the relevant form with id , & serialize that
var hidden = '<form id="fform_' + i + '"><input id="fnameh" name="name" type="hidden" value="' + susers[i].name + '" >';
hidden += '<input name="id" type="hidden" value="' + susers[i].id + '" >';
var fbutton = '<button data-id="' + i + '" id=""class=" addfriend btn btn-info btn-xs pull-right text-center" type="submit" >Follow <span class=" glyphicon glyphicon-plus" aria-hidden="true"></span> </button>';
Make below change to the click function.
Also reason of adding the event handler inside loop is not clear.
$('.addfriend').live('click', function(arg) {
arg.preventDefault();
var getDataId = $(this).attr('data-id') // get the data-id
var data = $('#fform_'+getDataId).serialize(); // get relevant form
$.ajax({
// rest of code
}); // end of $.ajax
})
Try to use jquery version above 1.9 to use the on method for event delegation
I made a few changes to your code.
With the new javascript, I believe most browsers support string interpolation natively (without any extra plugins or pre-compiling with babel for example) so you can just interpolate your variables within backticks ``.
Also, you seemed to be creating a form with the id of #fform and a button with the id of #addfriend for each iteration. The problem is that calling $('#fform') or $('#addfriend') will return an array with as many elements as you have users.
So I added an extra data-suser-id attribute with unique id's on those. I am not sure the code will work because I can't actually try it and changed quite a few things but let me know if you are getting closer to your solution.
$(document).ready(function() {
var suggest = new XMLHttpRequest();
suggest.onreadystatechange = function() {
if (suggest.readyState === 4 && suggest.status === 200) {
var susers = JSON.parse(suggest.responseText);
var limit = susers.length;
for (var i = 0; i < limit; i += 1) {
var sphoto = `<div class="col-md-4 text-left ">
<div id="fimage">
<img width="50" height="50" src="user/${susers[i].activation}/${susers[i].pic}">
</div>
</div>`
var sname = `<div id="fname">${susers[i].name}</div>`
// here is the form im targetting to pull informtion from
var hidden = `<form id="fform" data-suser-id='${susers[i].id}'>
<input id="fnameh" name="name" type="hidden" value="${susers[i].name}" >
<input name="id" type="hidden" value="${susers[i].id}">`
var mutalusers = `</form><div id="mutal" class="text-left">
<h6>
<div id="fmutal">
<?php echo $c = mutal(${susers[i].id}, $me, $db) ?>
</div>
</h6>
</div>`
var fbutton = `<button id="addfriend" class="btn btn-info btn-xs pull-right text-center" type="submit" data-suser-id='${susers[i].id}'>Follow <span class=" glyphicon glyphicon-plus" aria-hidden="true"></span> </button>`;
var display = document.getElementById('fsuggest');
display.innerHTML += `<div class="scroller">
<div id="fspace">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
${sphoto}
${sname}
${hidden}
${fbutton}
${mutalusers}
</div>
</div>`
// #live method is deprecated : http://api.jquery.com/live/
var addfriend_button = $(`#addfriend[data-suser-id=${susers[i].id}]`)
addfriend_button.on('click', function(arg) {
// return function(){
arg.preventDefault();
// the selector `#fform` doesn't seem to be unique to the current user's form data, so I added an data-attribute to make sure we are getting the correct form data
var data = $(`#fform[data-suser-id=${susers[i].id}]`).serialize();
$.ajax({
data: data,
type: "post",
url: "addnew.php",
success: function(data) {
//make the text area empty for the current user's `#addfriend` button
addfriend_button.html('done');
console.log(data);
}
}); // end of $.ajax
// }(i); // end of inner function : not sure why this inner function is necessary
}); // end of click listner
} //end of for loop
console.log(susers);
}
};
var suugestFile = 'box.php';
suggest.open('GET', suugestFile);
suggest.send();
}); // end of JQUERY ready

Button Group Click Handler - How to get text content of clicked button?

I am trying to set up two button groups. A click on any button in the second group should add a new button to the first group. The new button shall get the same label as the clicked button.
var name = this.textContent works if the click handler is attached to a single button. How do you get the text content of the clicked button when the click handler is instead attached to a group of buttons?
HTML:
<body>
<div id="group1">
<button> nameA </button>
<button> nameB </button>
</div>
<hr>
<div id="group2">
<button> nameC </button>
<button> nameD </button>
</div>
</body>
Javascript:
$('#group2').on('click', function(event) {
var name = this.textContent // wrong!
var r = $('<input type="button" value="' + name + '">');
$("div#group1").append(r);
});
JSFiddle Demo
Use event delegation:
$('#group2').on('click', 'button', function(event) {
var name = this.textContent
var r = $('<input type="button" value="' + name + '">');
$("div#group1").append(r);
});
Second parameter in 'on' method can be selector string to filter the descendants of the selected elements that trigger the event.
Check this https://jsfiddle.net/q6b6g3xm/
In your case, this should be enought:
$('#group2 button').click(function(event) {
var name = this.textContent
var r = $('<input type="button" value="' + name + '">');
$("div#group1").append(r);
});
Prefer the RobHil solution if you other buttons will be created in #group2 after the execution of the jQuery code.
Else, I see two other possibilities:
$('#group2 button').each(function () {
var $button = $(this).click(function(event) {
var r = $('<input type="button" value="' + $button.text() + '">');
$("div#group1").append(r);
});
});
or:
$('#group2').click(function(event) {
var $button = $(event.target);
var r = $('<input type="button" value="' + $button.text() + '">');
$("div#group1").append(r);
});
But keep in mind the target depend on where you click if you have nested blocks in the clicked zone: https://api.jquery.com/event.target/
Here is my own approach to the problem. I modified HTML code a little by adding individual id to the buttons.
HTML:
<div id="group1" >
<button id="btn-A">nameA</button>
<button id="btn-B">nameB</button>
<button id="btn-C">nameC</button>
</div>
<hr />
<div id="group2">
<button id="btn-D">nameD</button>
<button id="btn-E">nameE</button>
<button id="btn-F">nameF</button>
</div>
JavaScript:
// click on the button
$(document).on('click','button', function(){
//store the value of the id and
// split it # '-' into array ['btn','A']
$id = $(this).attr('id').split('-');
// store the value at index 1 into $id
$id = $id[1];
//get the Id of the current div group
$divId = $(this).closest('div').attr('id');
//check which div group is current and
//Assign the reversed value as appropriate
if($divId === "group1"){
$addId = "#group2";
}else {
$addId = "#group1";
}
//Remove the button from the group
$(this).remove();
//Add the button to the second div group
$($addId).append('<button id="btn-'+$id+'">'+$(this).text()+'</button>');
});

applying text input value to other empty text fields - jQuery

This question is in the continuation of another question I have asked earlier URL
I am generating rows dynamically and and all the fields are being populated using JS thus the input ID's for all text boxes are different. Now if a user enter some number on "Apply to all" input field and click the button the same number should be set to all the rows which are added in the betslip.
HTML structure where I am adding rows dynamically
<div id="bets">
<div id="idNo1" class="bet gray2" name="singleBet">
<div class="left">
<p class="title">
<p class="supermid">
<input id="input_1" type="text">
</div>
</div>
<div id="idNo2" class="bet gray2" name="singleBet">
<div class="left">
<p class="title">
<p class="supermid">
<input id="input_2" type="text">
</div>
</div>
<div id="idNo3" class="bet gray2" name="singleBet">
<div class="left">
<p class="title">
<p class="supermid">
<input id="input_3" type="text">
</div>
</div>
</div>
JS for adding element in the individual bets
BetSlip.prototype.createSingleBetDiv = function(Bet) {
var id = Bet.betType + '_' + Bet.productId + '_' + Bet.mpid,
divId = id + '_div';
// If such bet already exists
if (typeof document.betSlip.singleDivs[divId] == "undefined") {
var div = element.create('div'),
a = element.create('a'),
leftDiv = element.create('div'),
closeDiv = element.create('div'),
singleBetNumber = ++document.getElementsByName('singleBet').length;
element.setId(div, divId);
element.setName(div, 'singleBet');
element.setClassName(div, 'bet gray2');
element.setClassName(a, 'right orange');
element.setClassName(leftDiv, 'left');
element.setClassName(closeDiv, 'icon_shut_bet');
// Info abt the bet
$(leftDiv).append('<p class="title"><b><span class="bet_no">' + singleBetNumber + '</span>. ' + Bet['horseName'] + '</b></p>');
var raceInfo = "";
$("#raceInfo").contents().filter(function () {
if (this.nodeType === 3) raceInfo = $(this).text() + ', ' + Bet['betTypeName'] + ' (' + Bet['value'].toFixed(2) + ')';
});
$(leftDiv).append('<p class="title">' + raceInfo + '</p>');
// Closing btn
(function(id) {
a.onclick=function() {document.betSlip.removeSingleBet(divId);};
})(id);
$(a).append(closeDiv);
// Creating input field
$(leftDiv).append('<p class="supermid"><input id="' + id + '_input\" type="text"></p>');
// Creating WIN / PLACE checkbox selection
$(leftDiv).append('<p><input id="' + id + '_checkbox\" type="checkbox"><b>' + winPlace + '</b></p>');
// Append left part
$(div).append(leftDiv);
// Append right part
$(div).append(a);
// Appending div with data
$.data(div, 'Bet', Bet);
// Add div to the bet slip map
document.betSlip.singleDivs[divId] = div;
return div;
}
else {
$("#betSlipError").show();
$("#betSlipError").html(sameBet);
return null;
}
}
HTML for applyTOall button
<a onclick="document.betSlip.applyToAll(event)" class="button apply orange">APPLY TO ALL <input type="text"> </a>
JS for applyToall function
BetSlip.prototype.applyToAll = function(e) {
e.preventDefault();
document.betSlip.applyToAllBetInput($(this).find("input").val());
}
BetSlip.prototype.applyToAllBetInput = function(value) {
$("#bets div[name=singleBet] .supermid input:text").val(value);
}
Try doing this way:
$('yourbutton').on('click', function(){
var applyVal = $('applyvalinput').val();
$('#bets').find('[id^="input"][type="text"]').val(applyVal);
});//^------finds the inputs in this specific div.
Click your button and cache the value of your apply to all input val and check for the inputs which has the ids started [id^="input"] by the term input and it applies the value to each text input.

Same function for different sections - relative referencing in jquery

By using relative references I am able to remove items which have been added to the list within a specfic part of the form. For example, by adding a requirement it can be deleted just from the requirement.
My issue is two fold:
Adding an item to references adds it to all three categories
When I try to add values to the other sections (qualifications) it says my input was blank.
http://jsfiddle.net/spadez/9sX6X/60/
var container = $('.copies'),
value_src = $('#current'),
maxFields = 10,
currentFields = 1;
$('.form').on('click', '.add', function () {
value_src.focus();
if ($.trim(value_src.val()) != '') {
if (currentFields < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
value_src.focus();
$(this).parents('.line').remove();
currentFields--;
});
Is it possible to modify this code without repeating it for each section, by using relatively references such as "parent" for example. I want to use this same script for all three sections but have it so each list is independant.
I'm new to javascript so I was wondering if this is possible because I only managed to get it working on the delete.
You have to use this to get the current element. In your case this refers to the button which was clicked.
The next step is to get the input box which belongs to the button. E.g. $(this).prev(); like in this example:
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
http://jsfiddle.net/9sX6X/62/
The same is also true for your appending part. Your are appending your html to all three elements which match $('.copies'). Instead you have to try to get there from this.
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var copies = $(this).parent().prev();
http://jsfiddle.net/9sX6X/63/
I would suggest adding a wrapping div to each section.
<div class="section">
<h4>Requirements</h4>
<div class="copies"></div>
<div class="line">
<input id="current" type="text" name="content" placeholder="Requirement" />
<input type="button" value="Add" class="add" />
</div>
</div>
Then you can do this:
var $section = $(this).closest(".section");
$(html).appendTo($section.find(".copies"));
This will add to just the related .copies element instead of to all .copies as your code does now. A similar approach can be used for all other elements as well.

Element is not defined jQuery $(element).remove()

I have this JavaScript that adds a form field, along with a link to remove that field:
var fieldCount = 0;
function addField() {
var name = 'file' + fieldCount;
var row = 'row' + fieldCount;
var str = '<p id="' + row + '"><label for="' + name + '">File to upload: <input type="file" name="' + name + '" id="' + name + '" />(100MB max size) <a onclick="removeRow(' + row + '); return false;">[-]</a></label></p>';
fieldCount++;
$("#fields").append(str);
};
function removeRow(id) {
$(id).remove();
};
Here is the markup:
<form id="ajaxUploadForm" action="<%= Url.Action("AjaxUpload", "Upload")%>" method="post" enctype="multipart/form-data">
<fieldset id="uploadFields">
<legend>Upload a file</legend>
<div id="fields"></div>
<input id="ajaxUploadButton" type="submit" value="Submit" />
</fieldset>
<a onclick="addField(); return false;" id="add">Add</a>
<div id="resultBox">
<p id="status" style="margin:10px;"></p>
</div>
</form>
The addFields works as expected, but when I click the remove link firebug tells me that row# is not defined, where # is any number of the added fields.
Any help would be appreciated!
You need to pass a valid selector expression for an ID selector (#ID), either in the removeRow call (also note the quotes surrounding the ID selector):
'<a onclick="removeRow(\'#' + row + '\'); return false;">'
Or in the removeRow function itself:
function removeRow(id) {
$("#" + id).remove();
};
You need to have quotes around it, since it's a string.
You also need the "#" to make it into a selector:
var str = '... <a onclick="removeRow(\'#' + row + '\'); return false;">...';
A better way would be to assign the onclick as a function (not sure of the jQuery way to do this but in plain Javascript):
var a = document.createElement('a');
a.onclick = (function(row)
{
return function()
{
removeRow(row);
return false;
};
})();
You are passing in the string value of row12, but the selector should be:
$('#'+row).remove()
The # specifies that you are looking for an ID. I agree with what I think one of the other answers was about to say, you should just use the onclick events natural this keyword instead:
<p onclick="remove(this)">something</p>
function remove(what) {
$(what).remove()
}
Or, maybe just forget the whole thing all together and switch to behavior for those kinds of rows:
$('.removableRow').live('click', function() {$(this).remove()});
Then you just specify that the row is removable, and never have to worry about binding events at all:
<p><a class="removableRow" href="#">Remove</a></p>

Categories