Jquery keyup event firing more than once - javascript

I'm trying to display some content from my database in a div, every time a user types a value into an input box. I'm using jquery to do this. But whenever I type something, once into the input box... the call-back function repeats, four times.
getProducts(){
$('.search-products').on('keyup', function(){
const searchProducts = new SearchProducts();
let search = $.trim($(this).val()); // get search text
if(search!==""){
// let data = {search: search};
let url = '/search-for-products/' + search;
$.ajax({
type: "GET",
url: url,
data: {},
success: function(response){
if(response.success){
searchProducts.showSearchProducts(response.products);
}
}
});
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="form-control search-products" placeholder="What are you searching for ?" aria-label="Username" aria-describedby="basic-addon1" style="color: light grey;">
I'd like your honest opinions on what could be wrong, with my code. Cos, I'm now confused about what to do.

If you've not found why it's added twice, a simple fix is you can remove the listener before adding it again:
$('.search-products').off('keyup').on('keyup', ...)
You can also use namespace events, to not remove other keyup events:
$('.search-products').off('keyup.search').on('keyup.search', ...)
Not many people know that jQuery supports namespace events.

Related

How to apply more than one JavaScript onchange for multiple image upload input fields

I have a page where users can upload up to 5 images to their post. For clarity for the user I have made it so that there are 5 empty boxes with separate input fields like this:
<span id="enableFileUpload_1" class="upload-image-svg-wrapper">
<input id="imageUploadID_1" type="file" accept="image/*"/>
</span>
<span id="enableFileUpload_2" class="upload-image-svg-wrapper">
<input id="imageUploadID_2" type="file" accept="image/*"/>
</span>
To handle these I have some JavaScript which looks for onchange event on the first field:
jQuery(function($) {
var imageNumber = 1;
$('body').on('change', '#imageUploadID_'+imageNumber, function() {
$this = $(this);
file_data = $(this).prop('files')[0];
form_data = new FormData();
form_data.append('file', file_data);
form_data.append('action', 'file_upload');
form_data.append('security', blog.security);
$.ajax({
url: blog.ajaxurl,
type: 'POST',
contentType: false,
processData: false,
data: form_data,
success: function (response) {
alert("ok");
}
});
});
});
This works fine for the first image but it seems like imageNumber is always 1 so the onchange event only fires for the first image/input and does nothing for the rest.
Questions
Do I have to write 5 different $('body').on('change', '#imageUploadID_1', function() for each input field and then have them call the same function?
Is there a smarter way of doing this?
You can use jQuery to assign the same onClick handler to every span with a class of upload-image-svg-wrapper. You've already written the code within the handler to work on any image that is clicked because you've used this to get the form data.
$('span.upload-image-svg-wrapper > input').on('change', function() {
Above, instead of selecting the entire body of the document we instruct jQuery to select all spans with the class upload-image-svg-wrapper that are inputs. And then we remove the selector from the on change handler.

How To Handle Event On Dynamic Parent Child Object

I am still not statisfy regarding Dynamic Child Inside Dynamic Parent where a lot of confusing for me and more worst how to know which once and how I can manipulate them to what I want.
For yours informations I am very very new on Javascript and Jquery, but I can catch up if someone give a right directions and a rights syntax. I love clean code where from that code I can learn more and understand.
Let say I have this structure html where it's same on firebugs:-
<div name="div0" class="div0">
<input name="txt0" class="txt0">
<br/><br/>
<div name="div1[]" class="divL1">
<button class="btn1"></button>
<button class="btn2"></button>
<input name="txtL1_a[]" class="cLtxt1">
<input name="txtL1_b[]" class="cLtxt1">
<br/><br/>
<div name="div2[]" class="divL2">
<div id="ui-widget">
<input name="txtL2_a[]" class="cLtxt2 autosuggest">
</div>
<input name="txtL2_b[]" class="cLtxt2">
</div>
<br/><br/>
<div name="div1[]" class="divL1">
<button class="btn1"></button>
<button class="btn2"></button>
<input name="txtL1_a[]" class="cLtxt1">
<input name="txtL1_b[]" class="cLtxt1">
<br/><br/>
<div name="div2[]" class="divL2">
<div id="ui-widget">
<input name="txtL2_a[]" class="cLtxt2 autosuggest">
</div>
<input name="txtL2_b[]" class="cLtxt2">
</div>
</div>
<br/><br/>
Actually on my head have a lot of question but let me ask a few question first.
1. I want to run .autosuggest where it's complicated for me because on normal form before this I can manage run it, but when .autosuggest inside dynamic parent div and located on dynamic input I cannot get a value and show a autocomplete.
By given id "txtL2_a[]" function SearchText cannot performance autocomplete and don't know which index are doing that.
function SearchText() {
$(".autosuggest").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "frmsetuptrip.aspx/GetAutoCompleteData",
minLength: 3,
data: "{'presearch':'" + document.getElementById('txtL2_a[]').value + "'}",
dataType: "json",
success: function (data) {
if ((data.d).length == 0) {
//$('#button9').show();
var result = [
{
label: 'No matches found',
value: response.term
}
];
response(result);
}
else {
response(data.d);
}
},
error: function (result) {
alert("Error");
}
});
}
});
}
2. Let say on
<div name="div1[]" class="divL1"> //index 1
I need some auto fill up - let say when I fill up
<input name="txtL2_a[]" class="cLtxt2 autosuggest"> //index :1
automatically value inside
<input name="txtL2_b[]" class="cLtxt2"> 'Index 1
will change only based parents index.
3. There is anyway a one function where I can catch all event and elaborate that by IF before go specific sub function or task like this pseudo code below:-
$("div.div0").each(function (event) {
if (event=="keyup" on child=="divL1"+index[0]){
//detect more spesific which object are doing that
if (whoisdoing=="txtL1_a[]"+index[0] {
//then do action etc: fill up parent input
$("div0.txt0").val($(txtL1_a.index[0]).val());
}
if (whoisdoing=="txtL1_b[]"+index[0] {
//then do action etc: fill up childs input
$("div2[index[0]].txtL2_b[index[0]].val( $(txtL1_b[index[0]]).val() );
}
}
//event - keypress
//event - click
//and many more
});
I cannot find on internet regarding all this matter I mention above. If anybody have a solution or already develop that function please sharing and I believe this is not easy to handle.
Anyway thanks on advance to you for reading and replying my question.
Best Regards.
I think and think again - it's should be have an solution!
Rights now I can handle KEYUP and Click on my dynamic child which specific input tag where I can do some task. I found on dynamic child inside dynamic parent I need use direct Class Name and Catch Parent Index first.
You cannot use this syntax below for my html structure:-
$(document).ready(function () {
var buttons = document.getElementsByTagName('button');
var buttonsLength = buttons.length;
for (var i = 0; i < buttonsLength; i++) {
buttons[i].addEventListener('keyup', clickResponse, false);
};
});
function clickResponse() {
// do something based on button selection here...
}
I found above syntax only can run on first level Parent only without dynamic child/parent add on run time.
What I do is using this syntax below to solve my problem number 2 and 3.
$("div.div0").on("keyup", "input", function () {
//detect name and val which input are doing keyup
handler = $(this).val();
name = $(this).attr('name');
parHandler = name;
//only this input I want do some task
if (name == "txtL1_a[]") {
dcAction = "FillUpOtherInput";
FillUp; //run functions
}
});
function FillUp() {
if (dcAction == "FillUpOtherInput") {
alert("Handler Name: " + parHandler + " Index Level :" + dc2);
//make sure right Parent Index before insert a value
//--should i loop
$("div.purchase-items").each(function (i) {
alert(i);
if (i == dc2) {
$(this).find("input[name='txtL1_b[]']").val("Hai");
}
i+1
});
parHandler = "";
dc2 = "";
dcAction = "";
}
}
Yes! I can fill up value to other input on same Parent Index.
If anybody have problem regarding Dynamic Child inside Dynamic Parent on do action like me, yours can refer this syntax to solve your problem.
If anyone have better solutions please share here to help other person like me as newbie on Jquery functions.
For question No 1 regarding autocomplete where is detect which dynamic child are doing I use this line syntax:-
function SearchText(pIndex,iValue) {
//alert(dc2 + "/" + iValue);
$("div.divL2").eq(pIndex).find(".autosuggest").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "frmsetuptrip.aspx/GetAutoCompleteData",
minLength: 3,
data: "{'presearch':'" + $("div.divL2").eq(pIndex).find("input[name='txtL2_a[]']").val() + "'}",
dataType: "json",
success: function (data) {
if ((data.d).length == 0) {
//$('#button9').show();
var result = [
{
label: 'No matches found',
value: response.term
}
];
response(result);
}
else {
response(data.d);
}
},
error: function (result) {
alert("Error");
}
});
}
});
}
Now my autocomplete can catch txtL2_a[] value and know which parent are to show a list.
What I learn and like to share to yours is a key
$("div.divL2").eq(pIndex).find(".autosuggest")
$(-what is parent name-).eq(-put parent index-).find(-class name on input-)
then it's should be run!.
I am new and must thanks to all who read this question and hope someone can get some idea from what I wrote up here.
Who's are trying intentionally to help me like #baao I really appreciate it and many thanks.
Yours are welcome to share if any better syntax/script on this matter to put on, maybe it's can help a thousand out there are search and face a problem same like me.
And I am glad and honest to share my code what I already know and solving a matter regarding my situations.
To make shorter syntax on fillup function follow this below:-
function FillUp() {
if (dcAction == "FillUpOtherInput") {
$(div.div0).eq(dc2).find("input[name='txtL1_b[]']").val("Hai");
parHandler = "";
dc2 = "";
dcAction = "";
}
}
I just know eq(***if you know the index*)** are direct go to specific element like dynamic parent/child based index given.

Form validation not working with progressButton js

I've been working on this website with an animated submit button with a 3d built-in proggress bar:
http://add.digital/contato.php
For the submit button, I used this plugin:
http://tympanus.net/codrops/2013/12/12/progress-button-styles/
Everything works beautifully, the loading bar runs smoothly and there are no problems with the form submission. The problem is the validation, which doesn't seem to work. The submit button ("Enviar") is a button tag. When I change it for an input tag, validation works, but the proggress bar doesnt, and vice-versa. I've tried reproducing the effect with an input tag, but it didn't work. So I tried to work on the form validation, which seemed more approachable. I've run quite a few solutions I found here on SO and on other websites regarding form validation with button tags, but I got pretty much the same result from all of them: when hitting the submit button, the error messages for empty fields are shown, but noe of them stops the progress bar animation and the form submission. I've also searched for queries related to Ladda.js, which is a similar plugin, but I can't find a way to validate the form and stop the animation and submission when necessary. I've checked the entire code (as a newbie), and tried many different solutions, but wasn't able to sort this matter, which is quite annoying. Any help or guidance on how to gou about with this would be much appreciated.
Below is the form:
<form action="envia_mail_a2.php" method="POST">
<div class="input-group">
<label for="nome" class="hidden"></label>
<input class="input-custom" type="text" placeholder="Nome" name="edtNome" id="edtNome" required>
</div>
<div class="input-group">
<label for="email" class="hidden"></label>
<input class="input-custom" type="text" placeholder="E-mail" id="edtEmail" name="edtEmail" required>
</div>
<div class="input-group">
<label for="telefone" class="hidden"></label><input class="input- custom" type="text" placeholder="Fone" id="edtTelefone" name="edtTelefone" required>
</div>
<div class="input-group">
<label for="mensagem" class="hidden"></label>
<textarea class="input-custom expanding" placeholder="Mensagem" rows="1" name="edtMensagem" id="edtMensagem"></textarea>
</div>
<div class="input-group text-right">
<button type="submit" id="btnEnviar" name="btnEnviar" class="submit progress-button" data-style="rotate-angle-bottom" data-perspective data-horizontal>Enviar</button>
</div>
</form>
And here the validation (original code, as it was when I took over the project, without my attempts):
<script>
$(document).ready(function(e) {
$("button#btnEnviar").click(function(e) {
var nome = $("#edtNome").val();
var mail = $("#edtEmail").val();
var fone = $("#edtTelefone").val();
var mensagem = $("#edtMensagem").val();
$.ajax({
type: 'POST',
url: "envia_mail_a2.php",
//context: document.body,
//dataType: 'text',
data: "nome="+nome+"&mail="+mail+"&fone="+fone+"&mensagem="+mensagem,
success: function(){
//alert('Enviado com sucesso')
setInterval(function(){
$("#edtNome").val('');
$("#edtEmail").val('');
$("#edtTelefone").val('');
$("#edtMensagem").val('');
}, 3000);
},
error: function () {
alert('Erro ao enviar');
}
});
});
});
</script>
Once again, thanks for all the attention
After looking at the code on the page, when calling new ProgressButton, there are two parameters passed to the constructor ... the button HTMLElement that will be turned into a progress button via the plugin, and a callback function that will determine what happens when the newly created progress button is clicked. Right now you have two click handlers on the progress button. One that is being passed into the new ProgressButton() call, and another one that you've pasted above that is created when the document is ready. The one being passed into the ProgressButton constructor is handling the animation of the button, and the additional click handler you've pasted above is taking care of validation. You need to move the validation code into the click handler that is being passed to the ProgressButton constructor so that the animation happens in-sync with validation. For instance, you could trigger the animation as the result of a success return from the validation service, or you could do something else to the button if there is an error. But all this should happen from a single handler since the validation is happening asynchronously, and right now, since the animation and validation are happening from two different handlers that are both triggered by clicks on the button, you're not able to sync those two processes up.
So I'm thinking something like this:
new ProgressButton( bttn, {
callback : function( instance ) {
var nome = $("#edtNome").val();
var mail = $("#edtEmail").val();
var fone = $("#edtTelefone").val();
var mensagem = $("#edtMensagem").val();
var animation = function() {
var progress = 0,
interval = setInterval( function() {
progress = Math.min( progress + Math.random() * 0.1, 1 );
instance._setProgress( progress );
if( progress === 1 ) {
instance._stop(1);
clearInterval( interval );
}
}, 200 );
}
$.ajax({
type: 'POST',
url: "envia_mail_a2.php",
//context: document.body,
//dataType: 'text',
data:"nome="+nome+"&mail="+mail+"&fone="+fone+"&mensagem="+mensagem,
success: function(){
//alert('Enviado com sucesso')
//call the animation
animation();
},
error: function () {
alert('Erro ao enviar');
//do another animation if there is an error
}
});
});
}
} );
To be honest, progress bars aren't great for AJAX calls when you're not able to really tell what the "progress" of the call is ... I guess you could do something that worked off the readyState of the XHR object using onreadystatechange events, but often times most AJAX progress indicators like this are some type of looping animation.

Ajax request stores old data

I have a litte problem with my ajax request and I haven't found a solution yet.
What I am trying to accomplish:
I have simple search form, when I submit I send the data to a PHP file which returns the result as json. Then I add the returned data in a clickable list and when I click on one list item I want to display the data in a new div. This actually works fine. Even if I start a new search I get the correct json objects and the list updates as expected but now I have following problem. If I start a new search without refreshing the whole page and again click on a list item, in the console log i see that the new but also the previous data is still kinda stored in the list or wherever and this is the problem because I then display the wrong data if I click on the list items.
I hope you understand my question and I am thankful for every hint. And btw, is my approach even possible or is there a better way to solve this?
Javascript code
$('#searchbar').submit(function(e){
e.preventDefault();
var query = $('#searchQuery').val();
if (query != ''){
loadData();
}else{
alert('Empty searchform!');
}
});
function loadData(){
var query = $('#searchQuery').val();
$.ajax({
type: "POST",
url: "search.php",
data: {'query': query},
dataType: 'json'
}).done(function(res) {
console.log(res);
resetInfos();
generateList(res);
$('.list-group').on('click', '.list-group-item', function(e){
var index = $(this).index();
console.log(res[index].Name);
$('#locationName').text(res[index].Name);
$('#locationAddress').text(res[index].Zip
+ ' '
+ res[index].State);
$('#locationContact').text(res[index].Internet);
init_map(res[index].Latitude, res[index].Longitude);
});
});
}
function resetInfos(){
$('.list-group').empty();
$('#listItems').remove();
$('#searchQuery').val('');
$('#locationName').text('');
$('#locationAddress').text('');
$('#locationContact').text('');
}
function generateList(result){
$.each(result, function(i){
$('.list-group').append('<li class="list-group-item" id="listItems">'
+ result[i].Name
+ ", "
+ result[i].Zip
+ " "
+ result[i].State);
});
}
HTML search form
<form id="searchbar">
<div class="input-group form-group-lg">
<input type="text" id="searchQuery" name="query" class="form-control" autocomplete="off" placeholder="Name, ZIP, State">
<span class="input-group-btn"><button class="btn btn-success btn-lg" id="searchButton" type="submit">Search</button></span>
</div>
<form>
Ok I solved it. I had to remove the click event handler with
$('.list-group').off('click');
in my resetInfos function.
You are using id selector to remove multiple elements.
$('#listItems').remove();
It will only remove the first matched reference. Please add some class to li element and then use class selector to remove.

Jquery php Live search text disappears in search bar

I am new to jquery and am trying to make a live search from my existing search page where you have to press enter.
This is the code I have made so far.
$( document ).ready(function() {
$('#searchhh').on("input", function() {
var searchquery = this.value;
$( "#searchform" ).submit();
});
});
This gets the input of the form and searches it every key stoke. The problem is the text that the user types resets every time the form submits. I tried to post the search value as a get variable and display it as the search bars value and auto focus into the the search bar every time the page reloads, this puts the typing bar at the beginning of the form before what the user has typed.
I feel like I am approaching this the wrong way please help. :)
You need to post your form via ajax. Here's a simple fiddle to demonstrate this:
http://jsfiddle.net/e76d09vw/
HTML:
<form id="searchform" method="post" action="some_url_here">
<input type="text" name="search" placeholder="Search..." />
</form>
Results:<br>
<div id="results"></div>
JS:
$('#searchform').on("keyup", "input", function() {
var form_data = $("#searchform").serialize();
var form_url = $("#searchform").attr("action");
var form_method = $("#searchform").attr("method").toUpperCase();
$.ajax({
url: form_url,
type: form_method,
data: form_data,
cache: false,
success: function(returnOutput){
// Your search results are outputted here
$("#results").html(returnOutput);
}
});
});

Categories

Resources