Javascript dynamic switch doubling Ajax calls - javascript

I am having a problem with a jQuery click function. When a user clicks a HTML button, my jQuery dynamically loads some styled checkbox's/toggle switches based upon their corresponding on/off state stored in a database.
I then added a click function to each dynamically loaded toggle switch so that when a user clicks it, it updates the database with the new state, it then, with Ajax, calls the GetAllSwitches function again loading the current state of the switches from the DB back into the resultScreen.
It works, updates the state in the DB correctly, but the program remembers previous 'clicks' and runs them all again followed by the new click state every time a user clicks. So on the first click it makes 1 http request, 2nd 2, 3rd 4, 4th 8 etc. The problem being after a few clicks the ajax calls become huge.
I'm not that experienced in Javascript so I am aware my code is verbose and I am clearly missing something, but are there any fixes or better approaches to this?
In summary what I want to achieve is:
User clicks allSwitches
Ajax call to a database which returns all objects with a toggle switch on screen
Have the toggle switch's clickable which updates the database with new state
Allow the switches to be clicked as many times as the user likes only making one update to the DB
HTML
<fieldset>
<legend> Get All Lights Dynamically</legend>
<input type="button" value="Show All" id="allSwitches"/>
</fieldset>
<fieldset>
<div id='resultScreen'></div>
</fieldset>
JavaScript
$(document).ready(function(){
$("#allSwitches").click(function(){
$.ajax({
url: 'GetAll',
type: 'GET',
dataType: 'text',
success: function(data) {
getAllSwitches(data)
});
});
});
function getAllSwitches(data){
var tr;
myData = $.parseJSON(data);
for(var i = 0; i < myData.length; i++){
tr = $('<tr/>');
if(myData[i].state=="On"){
tr.append('<div id="togs' + i + '">' + '<label class="switch">' +
'<input type="checkbox" class="' + myData[i].lightName +'" checked>' +
'<div class="slider round"></div>'
+'</label>' + '</div>');
tr.append("<td>" + myData[i].lightName +
" is " + myData[i].state + "</td>");
$('#resultScreen').append(tr);
var className = '.' + myData[i]lightName;
var lightName = myData[i].lightName;
var state = "Off";
upTog(className, lightName, state);
} else if (myData[i].state=="Off"){
tr.append('<label class="switch">' +
'<input type="checkbox" class="' + myData[i].lightName +'" >' +
'<div class="slider round"></div>'
+'</label>');
tr.append("<td>" + myData[i].lightName +
" is " + myData[i].state + "</td>");
$('#resultScreen').append(tr);
var className = '.' + myData[i].lightName;
var lightName = myData[i].lightName;
var state = "On";
upTog(className, lightName, state);
}
}
}
function upTog(className, lightName, state){
$(document).on('click', className, function() {
$.ajax({
url: 'UpdateLight?lightName=' + lightName + "&state=" + state,
type: 'POST',
dataType: 'text',
success:function(data){
$.ajax({
url: 'GetAll',
type: 'GET',
dataType: 'text',
success: function(data) {
$('#resultScreen').empty();
getAllSwitches(data);
}});
}
})
});
}
Many thanks.

The easiest way to do it is to unbind the previous click before set the new one.
Change upToge() body like this:
$(className).unbind( "click" );
$(className).on('click', function () {
/* Your ajax call here */
});

You're adding the click handler to the className, which is not changing when you empty the #resultsScreen div. You can see how the handlers pile up in this jsbin: http://jsbin.com/hizigutogi/edit?js,console,output (fill the div, click the red box, empty it, fill it again, and click it a few more times)
Try passing the reference to the jQuery object tr into upTog and adding the click handler onto it directly, instead of attaching it to the class name.

Related

How to pass/generate table with parameters from one page to another

Hi i having a scenario where i am generating a dynamic table along with the dynamic button and when ever user clicks that button it has to get that row value and it has generate another dynamic table by taking this value as parameter .Till now i tried generating a dynamic table and with button and passed a parameter to that function here i stuck how to pass /accept a parameter to that function so that by using ajax call it can generate another dynamic table.
$.ajax({
type: 'GET',
url: xxxx.xxxxx.xxxxx,
data: "Id=" + clO + Name_=" + cl+ "",
success: function (resp) {
var Location = resp;
var tr;
for (var i = 0; i < Location.length; i++) {
tr = tr + "<tr>
tr = tr + "<td style='height:20px' align='right'>" + Location[i].Amount + "</td>";
tr = tr + "<td style='height:20px' align='right'>" + Location[i].Name + "</td>";
tr = tr + '<td><input type="button" class="nav_button" onclick="test(\'' + Location[i].Amount + '\',\'' + Location[i].Name + '\')"></td>';
tr = tr + "</tr>";
};
document.getElementById('d').style.display = "block";
document.getElementById('Wise').innerHTML = "<table id='rt'>" + "<thead ><tr><th style='height:20px'>Amount</th>" + "<th style='height:20px'>Name</th>""</tr></thead>"
+ tr + "<tr><td align='left' style='height:20px'><b>Total:"+ TotBills +"</b></td><td style='height:20px' align='right'><b></b></td></tr>" +
"</table>";
document.getElementById('Wise').childNodes[0].nodeValue = null;
},
error: function (e) {
window.plugins.toast.showLongBottom("error");
}
function test(value,val1,val2) {
navigator.notification.alert(value + ";" + val1 + ";" + val2);
// here i have to pass the another ajax by basing on the the onclick
}
so here in the function i have to pass the parameters and have to display in the new page and how is it possible ?
To pass data from a page to another your best bet is localStorage and SessionStorage;
SessionStorage - Similar to a cookie that expires when you close the browser. It has the same structure as the localStorage, but there is no way to change its permanence time, whenever closing will be deleted.
LocalStorage - This is similar to a cookie, but it never expires, so while there were records in the AppCache for that domain, the variable will exist (unless the user creates a routine to remove it).
Both attributes were added by HTML5. The above items called web storage. But there are other forms of local storage through HTML5, such as WebSQL database, Indexed Database (IndexDB), as well as conventional files (File Access).
Ex:
// Store
localStorage.setItem("lastname", "Smith");
// Retrieve
document.getElementById("result").innerHTML = localStorage.getItem("lastname");
Is it what you meant ?
It's unclear what you're after, but I think I see where you're headed. From the code you included, it seems like you want something like this instead:
// This will take the user to a separate page, passing your parameters
function test(val1,val2) {
window.location.href("/UrlGoesHere?Amount=" + val1 + "&Name=" + val2);
}
Another option, based on what you've said, is to redraw the table. You could do that with something like this:
function test(val1,val2) {
$.ajax({
type: 'GET',
url: "/UrlGoesHere",
data: "Amount=" + val1 + "&Name=" + val2,
success: function (resp) {
// redraw table here
}
});
}

I have dynamically generated 2 <tr> and I want to get the data of the <tr> I click

The Question might be confusing but this is the exact situation..
I have dynamically generated few ( as per data fetched from database) and now I want to allow the user to select one of the radio buttons and I want to capture the details of the row clicked so please check my code and assist
My ajax code
$.ajax({
data: data,
url: url,
type: 'POST',
datatype: 'JSON',
success: function (response) {
console.log(response);
var result = $.parseJSON(response);
var count = result.length;
for (var i = 0; i < count; i++) {
var $row = $("<tr><input type='hidden' id='"+ result[i].objId + "' value='"+ result[i].objId+"'><td><input type='radio' name='dbRadio' id='dbRadio'></td><td>" + result[i].name + "</td><td> Murgency Global Network</td><td>" + result[i].number + "</td><td>" + result[i].city + "</td><td> 0.5 Km</td></tr>");
$('table.queriedResponder > tbody:last').append($row);
}
console.log($row);
}
});
my radio button detection code
$('input[name=dbRadio]').change(function(){
console.log('clicked');
});
Use an instance of this and get the closest tr:
$('input[name=dbRadio]').change(function(){
console.log($(this).closest("tr"));
});
Of course, if this handler isn't being hit, it's probably because your rows are being added dynamically - so delegate the handler:
$('table.queriedResponder').on('change', 'input[name=dbRadio]', function() {
console.log($(this).closest("tr"));
});

HTML submit text used for Javascript query with API

For a project, I am trying to make a HTML form that when a movie is searched it can access the Rotten Tomatoes API and queries the user's submitted text and returns with the movie.
The javascript* code from Rotten Tomatoes was provided
<script>
var apikey = "[apikey]";
var baseUrl = "http://api.rottentomatoes.com/api/public/v1.0";
// construct the uri with our apikey
var moviesSearchUrl = baseUrl + '/movies.json?apikey=' + apikey;
var query = "Gone With The Wind";
$(document).ready(function() {
// send off the query
$.ajax({
url: moviesSearchUrl + '&q=' + encodeURI(query),
dataType: "jsonp",
success: searchCallback
});
});
// callback for when we get back the results
function searchCallback(data) {
$(document.body).append('Found ' + data.total + ' results for ' + query);
var movies = data.movies;
$.each(movies, function(index, movie) {
$(document.body).append('<h1>' + movie.title + '</h1>');
$(document.body).append('<img src="' + movie.posters.thumbnail + '" />');
});
}
</script>
I have an API key, my question is how would I be able to create a form that would change out the value for var query = "Gone With The Wind"; as the user submitted an input search with a HTML form such as this:
<input id="search">
<input type="submit" value="Submit">
Also would this be able to lead to another HTML page once searched?
complete rewrite ...
You should wrap the supplied (and modified) code in a function which you can then call through an event binding, like a submit event on your input form.
Below you will find a complete and working example of how you could do it. I replaced the given URL with a publicly available one from spotify. As a consequence I had to modify the callback function a little bit and also the dataType paramater in the $.ajax() argument object was changed to 'json' (instead of originally: 'jsonp').
At the end of the lookformovie() function you will find return false;. This prevents the submit event from actually happening, so the user stays on the same page.
function lookformovie(ev){ // ev is supplied by the triggered event
console.log('go, look!');
// the following WOULD be important, if this function was triggered
// by a click on a form element and you wanted to avoid the event to
// "bubble up" to higher element layers like the form itself.
// In this particular example it is superfluous
ev.stopPropagation();
var apikey = "[apikey]";
var baseUrl = "http://api.rottentomatoes.com/api/public/v1.0";
// construct the uri with our apikey
var moviesSearchUrl = baseUrl + '/movies.json?apikey=' + apikey;
// --- start of spotify-fix ---
moviesSearchUrl="https://api.spotify.com/v1/search?type=track";
// --- end of spotify-fix -----
// the following gets the contents of your changed input field:
var query=$('#search').val();
$.ajax({
url: moviesSearchUrl + '&q=' + encodeURI(query),
dataType: "json", // spotify-fix, was: "jsonp"
success: searchCallback
});
return false; // this prevents the submit event from leaving or reloading the page!
}
// modified callback (spotify-fix!!):
function searchCallback(data){
console.log('callback here');
$('#out').html(data.tracks.items.map(
function(t){ return t.name;}).join('<br>\n'));
}
// original movie callback for Rotten Tomatoes:
function searchCallback_inactive(data) {var str='';
str+='Found ' + data.total + ' results.';
var movies = data.movies;
$.each(movies, function(index, movie) {
str+='<h1>' + movie.title + '</h1>';
str+='<img src="' + movie.posters.thumbnail + '" />';
});
$('#out').html(str);
}
$(function(){
$('form').on('submit',lookformovie);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input type="text" id="search" value="james brown">
<input type="submit" value="get tracks">
</form>
<div id="out"></div>
You might have noticed that I placed several console.log() statements at various places into the code. This helped me during debugging to see which part of the functionality actually worked, and where something got stuck. To see the output you need to have your developer console opened of course.
You can construct form, with input element named "q", then handle form submit event.
<form action="http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=API_KEY" method="get">
<input id="search" name="q">
<input type="submit" value="Submit">
</form>

jQuery: click() triggers twice with dynamic content

I'm basically loading contents from a database over ajax into a div. Then, clicking on of these content-pieces should reload new content.
The ajax request is initialized as a method in a class which I call at the beginning:
function Request(tag1, tag2, tag3) {
this.tag1 = tag1,
this.tag2 = tag2,
this.tag3 = tag3
}
Request.prototype = {
ajaxCategoryRequest: function () {
$.ajax({
type: "GET",
url: "request2.php",
data: "tag1=" + this.tag1 + "&tag2=" + this.tag2 + "&tag3=" + this.tag3,
success: function (data) {
var jdata = $.parseJSON(data);
//Frage ausgeben
$("h1.question").html(jdata[0]);
//Tiles ausgeben
for (var i = 1; i < jdata.length; i++) {
$("#tiles").append(
'<div class="category" id="' + jdata[i].type + '" data-owntag="' + jdata[i].owntag + '" data-description="' + jdata[i].description + '"><img src="' + jdata[i].imageurl + '" alt="' + jdata[i].name + '"/><div class="ctitle">' + jdata[i].name + '</div></div>'
);
}
}
});
}
};
var searchtype = new Request("", "", "");
searchtype.ajaxCategoryRequest();
Then clicking one of the above created div's should start a new request:
$("#tiles").on('click', '.category', function () {
var tag1 = "newtag";
var tag2 = "newtag";
var tag3 = "newtag";
//remove old content
$('.category').remove();
//start new request
var nextrequest = new Request(tag1, tag2, tag3);
nextrequest.ajaxCategoryRequest();
});
});
Basically everything's working, the content is loaded, and if I click on a div, it does trigger a new request, but here comes the error, it's triggered twice. So, every new loaded element appears twice.
I searched for it, and I think it's due to the printing-loop in the ajax request, binding the click function every time to the div. I read a lot about .unbind("click") and .bind() it or similar( .off() ), but nothing worked for me. Maybe there is another solution for this problem?
it's triggered twice
Actually, not really. Put your console.log("Mouseclick"); in the first line of the click listener and you will see it only once per click.
$("#tiles").on('click','.category',function(e){
// …
//remove old elements
$('.category').fadeOut(200,function(){
console.log("Mouseclick");
$(this).remove();
//start request when animation completed
var nextrequest = new Request(tag1,tag2,tag3);
nextrequest.ajaxCategoryRequest();
});
});
The animation is your problem. The callback to fadeOut is invoked for each of the .category elements - that's why your $(this).remove() works (as this is only a single <div> element).
So you are actually starting a new request for each of the categories you have removed, which is of course not what you want. What you could do is moving the request out of the animation callback, then it will start right away. There are no race conditions, but - when the ajax is faster than 200 ms - it could happen that the new categories appear while the old ones are still fading out.
If you want to prevent such a glitch, you will need to find a way to fire the ajax after all of the animation callbacks have completed. Fortunately, there is the .promise method which does exactly that - it returns a promise which is guaranteed to resolve only once, and you can add callbacks for the end of the event queue:
$("#tiles").on('click','.category',function(e){
console.log("Mouseclick");
// …
// remove old elements
$('.category').fadeOut(200,function(){
$(this).remove();
}).promise().done(function() {
// start request once when all animations completed
var nextrequest = new Request(tag1,tag2,tag3);
nextrequest.ajaxCategoryRequest();
});
});
If you want to shorten the time until the ajax requests is finished, with promises you even can run the animation and the request in parallel very easily, adding a callback for when both tasks are finished:
function categoryRequest(data) {
return $.ajax({
type: "GET",
url: "request2.php",
data: {tag1: tag1, tag2: tag2, tag3: tag3},
dataType: "json" // invokes $.parseJSON automatically
});
}
function outputData(jdata) {
//Frage ausgeben
$("h1.question").html(jdata[0]);
//Tiles ausgeben
for (var i = 1; i < jdata.length; i++) {
$("#tiles").append(
'<div class="category" id="' + jdata[i].type + '" data-owntag="' + jdata[i].owntag + '" data-description="' + jdata[i].description + '"><img src="' + jdata[i].imageurl + '" alt="' + jdata[i].name + '"/><div class="ctitle">' + jdata[i].name + '</div></div>'
);
}
}
//Erster Aufruf
categoryRequest("", "", "").done(outputData);
// Weitere Aufrufe bei click
$("#tiles").on('click','.category',function(e){
console.log("Mouseclick");
//define next request variables (tags)
var stage = $(this).attr('id');
var owntag = $(this).data("owntag");
var tag1 = "", tag2 = "", tag3 = "";
if (stage == 'searchtype')
tag1 = owntag;
else if (stage == 'category')
tag2 = owntag;
else if (stage == 'subcategory')
tag3 = owntag;
else
console.log("No valid (stage)type defined");
var removed = $('.category').fadeOut(200,function(){
$(this).remove();
}).promise();
var request = categoryRequest(tag1,tag2,tag3);
$.when(request, removed).done(function(requestResults) {
outputData(requestResults[0]);
});
});
Use one method to trigger the function only for once.
$("#tiles").one('click','.category',function(){
$("#tiles").off('click').on('click','.category',function(){
I solutioned it like this
$('.category').fadeOut(200).promise().done(function(){
//start request when animation completed
$(".category").remove();
var nextrequest = new Request(tag1,tag2,tag3);
nextrequest.ajaxCategoryRequest();
});

How to get the value value of a button clicked Javascript or Jquery

I'll try to be as straight to the point as I can. Basically I using jquery and ajax to call a php script and display members from the database. Next to each members name there is a delete button. I want to make it so when you click the delete button, it deletes that user. And that user only. The trouble I am having is trying to click the value of from one delete button only. I'll post my code below. I have tried alot of things, and right now as you can see I am trying to change the hash value in the url to that member and then grap the value from the url. That is not working, the value never changes in the URL. So my question is how would I get the value of the member clicked.
<script type="text/javascript">
$(document).delegate("#user_manage", "pagecreate", function () {
$.mobile.showPageLoadingMsg()
var friends = new Array();
$.ajaxSetup({
cache: false
})
$.ajax({
url: 'http://example.com/test/www/user_lookup.php',
data: "",
dataType: 'json',
success: function (data) {
$.mobile.hidePageLoadingMsg();
var $member_friends = $('#user_list');
$member_friends.empty();
for (var i = 0, len = data.length; i < len; i++) {
$member_friends.append("<div class='user_container'><table><tr><td style='width:290px;font-size:15px;'>" + data[i].username + "</td><td style='width:290px;font-size:15px;'>" + data[i].email + "</td><td style='width:250px;font-size:15px;'>" + data[i].active + "</td><td><a href='#" + data[i].username + "' class='user_delete' data-role='none' onclick='showOptions();'>Options</a></td></tr><tr class='options_panel' style='display:none'><td><a href='#" + data[i].username + "' class='user_delete' data-role='none' onclick='showId();'>Delete</a> </td></tr></table></div>");
}
}
});
});
</script>
<script>
function showId() {
var url = document.URL;
var id = url.substring(url.lastIndexOf('#') + 1);
alert(id);
alert(url);
}
</script>
IDEAS:
1st: I think it would be easier to concatenate an string an later append it to the DOM element. It's faster.
2nd: on your button you can add an extra attribute with the user id of the database or something and send it on the ajax call. When getting the attribute from the button click, use
$(this).attr('data-id-user');
Why don't you construct the data in the PHP script? then you can put the index (unique variable in the database for each row) in the button onclick event. So the delete button would be:
<button onclick = "delete('indexnumber')">Delete</button>
then you can use that variable to send to another PHP script to remove it from the database.
$('body').on('click', 'a.user_delete', function() {
var url = document.URL;
var id = url.substring(url.lastIndexOf('#') + 1);
alert(id);
alert(url);
});
<?php echo $username ?>
Like wise if you pull down users over json you can encode this attribute like so when you create your markup in the callback function:
'<a href="#'+data[i].username+'" data-user-id="'+ data[i].username + '" class="user_delete" data-role="none" >Options</a>'
So given what you are already doing the whole scenerio should look something like:
$(document).delegate("#user_manage", "pagecreate", function () {
$.mobile.showPageLoadingMsg();
var friends = new Array(),
$member_friends = $('#user_list'),
// lets jsut make the mark up a string template that we can call replace on
// extra lines and concatenation added for readability
deleteUser = function (e) {
var $this = $(this),
userId = $this.attr('data-id-user'),
href = $this.attr('href'),
deleteUrl = '/delete_user.php';
alert(userId);
alert(href);
// your actual clientside code to delete might look like this assuming
// the serverside logic for a delete is in /delete_user.php
$.post(deleteUrl, {username: userId}, function(){
alert('User deleted successfully!');
});
},
showOptions = function (e) {
$(this).closest('tr.options_panel').show();
},
userTmpl = '<div id="__USERNAME__" class="user_container">'
+ '<table>'
+ '<tr>'
+ '<td style="width:290px;font-size:15px;">__USERNAME__</td>'
+ '<td style="width:290px;font-size:15px;">__EMAIL__</td>'
+ '<td style="width:250px;font-size:15px;">__ACTIVE__</td>'
+ '<td>Options</td>'
+ '</tr>'
+ '<tr class="options_panel" style="display:none">'
+ '<td>Delete</td>'
+ '</tr>'
+ <'/table>'
+ '</div>';
$.ajaxSetup({
cache: false
})
$(document).delegate('#user_manage #user_container user_options', 'click.userlookup', showOptions)
.delegate('#user_manage #user_container user_delete', 'click.userlookup', deleteUser);
$.ajax({
url: 'http://example.com/test/www/user_lookup.php',
data: "",
dataType: 'json',
success: function (data) {
$.mobile.hidePageLoadingMsg();
var markup;
$member_friends.empty();
for (var i = 0, len = data.length; i < len; i++) {
markup = userTmpl.replace('__USERNAME__', data[i].username)
.replace('__ACTIVE__', data[i].active)
.replace('__EMAIL__', data[i].email);
$member_friends.append(markup);
}
}
});
});
Here's a really simple change you could make:
Replace this part:
onclick='showId();'>Delete</a>
With this:
onclick='showId("+data[i].id+");'>Delete</a>
And here's the new showId function:
function showId(id) {
alert(id);
}

Categories

Resources