How to generate a button with its own js function? - javascript

Well I have data retrieved from ajax, I need to parse it in order to generate inputs with different <input> values. While clicking on <a> that should get near standing input value and go to ajax
<script type="text/javascript">
function proceed() {
var ID = document.getElementById('btnid').value;//probably that`s the wort way, because all of `<a>` buttons would have same id
//ajax with ID to proceed further
}
$.ajax({
async: false,
type: "POST",
url: "../api/",
data: {'data': "mydata"},
dataType: 'JSON',
complete: function (res) {
for(var i = 0; i < 10; i++) {
document.getElementById('nie').innerHTML = "
<ul class=\"somec\">
<li class=\"liclass\">
</input id=\"btnid\" value=\""+res.response[i].animal+"\" class=\"thatclass\" onclick=\"proceed();\"></input>//different values
<a id="clicker" onclick="proceed()"></a>//clickable link
</li>
</ul>
";
}
});
</script>
<html>
<div id="nie">
</div>
</html>
Any help or advises for solution ?

You cannot have more than one id in a single DOM -- only one unique id is allowed. Since jQuery is used here, you can take advantages of the other methods and API it provides.
First of all, I would move the loop to success handler of $.ajax because that ensures that I have data returned from the server.
As for "appending" input and anchor pairs, use $.append. What you're currently doing is just updating #nie with the last element's data in the loop.
For events, delegate the clicks on anchors. This is better because you might continue adding more elements, so you have to go through binding them to an event.
And please, don't set async to false in $.ajax settings. This has unexpected results and makes the browser slow to point that freezes and crashes. jQuery ajax async: false causes a strange warning?
$(function(){
var $nie = $('#nie');
// Delegate the click event
$(document).on('click', '.clicker' function(){
var id = $(this).siblings('input').val();
// Use id in upcoming AJAX request.
});
$.ajax({
type: "POST",
url: "../api/",
data: {'data': "mydata"},
dataType: 'JSON',
success: function (res){
$.each(res.response, function(i, r){
$nie.appeand('<ul class="somec">\
<li class="liclass">\
<input value="'+ r.animal+ '" class="thatclass"/>\
<a class="clicker"></a>\
</li>\
</ul>');
});
}
});
});

Related

AJAX request only executes on one checkbox, need it to execute on any

I have the following code, checkboxes are being generated by php based on the number of objects. There is one checkbox per object, and the code in the foreach that generates these is as follows (NOTE: this part is working fine, my problem is below):
"<input type='checkbox' name='markAsUnread' id='markRead' value='$sms->id' class='markAsUnread'>",
Here is the jQuery script that I am trying to use to mark any of the "clicked" boxes as "read". This particular script works when the first box is clicked at any time, but I need it to work for any of the boxes clicked (second, third, etc). I only need it to work on one at a time, but I need it to do so with any one selected.
<script type="text/javascript">
var myEl = document.getElementById('markRead');
myEl.addEventListener('click', function() {
var bloop = $('#markRead').val();
$.ajax({
type: 'POST',
url: '/link/to/route',
data: {sms: bloop},
success: function(data) {
window.location = '/foo/bar';},
contentType: "application/json",
dataType: 'json'
});
}, false);
</script>
I assume that it is not working because it is only grabbing the first box, so what needs to be changed to make it work with any of the selected checkboxes?
That should not work. If you repeatedly create elements with the same id, you violate html rules. There can only be one.
Instead of applying the function to only one element, identified with an ID, as
var myEl = document.getElementById('markRead');
ask for all elements with the name "markRead":
var myElements = document.getElementsByName('markRead');
which gives you an array to iterate over.
Additionally change your jquery-selector from
$('#markRead')
to
$("[name=markRead]")
Also, make sure that id-values are actually unique within one html document.
try following script and check
<script type="text/javascript">
$(function(){
var myElements = $('input[name=markAsUnread]');
myElements.click(function() {
var bloop = $('input[name=markAsUnread]:checked').val();
$.ajax({
type: 'POST',
url: '/link/to/route',
data: {sms: bloop},
success: function(data) {
window.location = '/foo/bar';},
contentType: "application/json",
dataType: 'json'
});
}, false);
});
</script>
Also, remove ID attribute from your generated checkboxes or make it Unique instead of having same value for all elements.
So I solved it, iterating over the elements and adding a click listener within the iterator seemed to do the trick:
$(function(){
var myElements = document.getElementsByName('markAsUnread');
$.each(myElements, function (index){
$(this).on("click", function(){
$.ajax({
type: 'POST',
url: '/foo/bar',
data: {sms: $(this).val()},
success: function(data) {
window.location = '/back/home';},
contentType: "application/json",
dataType: 'json'
});
});
});
});
I also removed IDs from the PHP generated checkboxes, as I wasn't using them.

Turning jquery into an includable, callable function

I'm so frustrated! As an ok PHP developer I can't get my head around the simplist of jquery problems!
I have recently moved my HTML jquery include to the end of the HTML body, instead of in the head to improve google pagespeed score.
This has broken some jquery which is used for simple comment voting. This was written badly as it repeats for every comment.
<div id="voterow-19907" class="commentfooter">UP</a> | <a id="comment-vote-down-19907" href="#" rel="nofollow">DOWN</a></div>
<script>
$("#comment-vote-up-19907").click(function() {
$.ajax({
type: "GET",
url: "/ajax.php",
data: "a=rv&v=19907&d=up",
success: function(data){
$("#voterow-19907").text("Thank you for your vote")
}
});
return false;
});
$("#comment-vote-down-19907").click(function() {
$.ajax({
type: "GET",
url: "/ajax.php",
data: "a=rv&v=19907&d=down",
success: function(data){
$("#voterow-19907").text("Thank you for your vote")
}
});
return false;
});
</script>
Since moving the jquery include to the bottom of the page this naturally doesn't work.
What I'm trying to do is turn the above code into a mini function I can include after the jquery include, then pass the ID and VOTE-DIRECTION to the function from the HTML a hrefs using the jquery DATA- attribute.
Any help would be greatly appreciated. I'm running out of hair!
I think, repeated codes will hurt your page than placement of JQuery file.
You can solve this problem using more general event listener. Remove all listeners inside code (all of them) and append the code below after Jquery include.
$('[id^=comment-vote]').click(function() {
var elementId = $(this).attr('id');
var elementIdParts = elementId.split("-");
var voteType = elementIdParts[2];
var id = elementIdParts[3];
$.ajax({
type: "GET",
url: "/ajax.php",
data: "a=rv&v="+id+"&d="+voteType,
success: function(data){
$("#voterow-"+id).text("Thank you for your vote")
}
});
return false;
});
$('[id^=comment-vote]") selects all elements which have id starting with "comment-vote". If user clicks one of these elements, event handler gets id of elements, split into parts like "comment", "vote", "up", "19900". 2nd part is voteType and 3rd part is ID of row. We can use these variables while generating/operating AJAX request.
I didn't try the code but the idea behind that would be beneficial for you.
To really give a great working answer, I would need to see your an example page / the exact structure of your html, but here's what I have for you.
In a script file that you include after jQuery, you can include something similar to the below code assuming your html is as follows:
<div id="voterow-1" class="voterow">
<p class="voteresult"></p>
<a class="upvote" href="#" rel="nofollow">UP</a>
<a class="downvote" href="#" rel="nofollow">DOWN</a>
</div>
<div id="voterow-2" class="voterow">
<p class="voteresult"></p>
<a class="upvote" href="#" rel="nofollow">UP</a>
<a class="downvote" href="#" rel="nofollow">DOWN</a>
</div>
Having the class of upvote and downvote makes it easy to target these elements in jQuery:
// After jQuery is loaded, the function passed to ready() will be called
$(document).ready(function () {
// bind a click event to every direct child with the upvote class of an element with the voterow class
$('.voterow > .upvote').click(function (event) {
// get the voterow parent element
var $parent = $(event.target).parent();
// use regex to strip the id number from the id attribute of the parent
var id = parseInt($parent.attr('id').match(/^voterow-(\d+)/)[1]);
// call your ajax function
vote(id, 'up', $parent.find('.voteresult');
});
$('.voterow > .downvote').click(function (event) {
var $parent = $(event.target).parent();
var id = parseInt($parent.attr('id').match(/^voterow-(\d+)/)[1]);
vote(id, 'down', $parent.find('.voteresult');
});
function vote(id, direction, $resultElement) {
$.ajax({
type: "GET",
url: "/ajax.php",
// here we have the id and the direction needed to make the ajax call
data: "a=rv&v=" + id + "&d=" + direction,
success: function(data){
$resultElement.text("Thank you for your vote")
}
});
}
});
Here is a demo: https://plnkr.co/edit/ECL376hZ3NOz8pBVpBMW?p=preview

How to call ajax again when user click back button to go back last webpage?

Below is my code..
HTML Code
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="body">
<div class="dropdown_div">
<select id="q_type" class="dropdown" onchange="getSubject(this.value)">
<option>Question1</option>
<option>Question2</option>
</select>
</div>
<div class="dropdown_div">
<select id="q_subject" class="dropdown">
<option>Subject1</option>
</select>
</div>
</div>
JS Code
function getSubject(val){
$("option", $("#q_subject")).remove();
var option = "<option>Subject</option>";
$("#q_subject").append(option);
$.ajax({
url: "api.path",
type: 'POST',
dataType: 'json',
data: {id: id},
async: true,
cache: false,
success: function(response) {
alert("Hi");
$("option", $("#q_subject")).remove();
var option = "<option>Subject1</option>";
option += "<option value=1234>Subject2</option>";
$("#q_subject").append(option);
}
});
}
How do I use pushState into my code and let user can click back button to return last page and then still see the ajax data?
First of all, you should save data received from ajax request to browser local storage. Afterwards, in order to show ajax result when browser "back" button was fired, you should bind statements that you are calling in ajax.success() method to window onpopstate event. To omit code duplication, it`s better to use a declared function instead of anonymous one.
function success(response) {
alert("Hi");
$("option", $("#q_subject")).remove();
var option = "<option>Subject1</option>";
option += "<option value=1234>Subject2</option>";
$("#q_subject").append(option);
}
Save data to localstorage and call success function:
$.ajax({
url: "api.path",
type: 'POST',
dataType: 'json',
data: {id: id},
async: true,
cache: false,
success: function(response) {
localStorage.setItem("response", response);
success(response);
}
});
Call success() when "back" button was fired:
window.onpopstate = function (e) {
var res = localStorage.getItem('response');
success(res);
}
I would rather suggest you to use sessionStorage which expires when the browser window is closed :)
$.ajax({
url: "api.path",
type: 'POST',
dataType: 'json',
data: {id: id},
async: true,
cache: false,
success: function(response) {
sessionStorage.setItem("DataSaved", response);
success(response);
}
});
And then
window.onpopstate = function (e) {
var res = sessionStorage.getItem('DataSaved');
success(res);
}
You can solve this using the local Storage or Session storage. You will also need to have a onload function callback, to check if there are any previous values that you stored in the local/session storage, if yes, then show that data in the select box.
I noticed this Back() issue when using Ajax to navigate an MVC-5 application from within a JavaScript generated diagram. All clicks in the diagram are handled by Ajax.
Above solutions do not replace the complete body, in the repaired cases a Back() would restore just the edit fields. In my case, I don't need that. I need to replace the entire page from the AJAX and also enable the Back button to return to my original diagram context.
I tried above solution to replace body, and I have to note, it would only trigger the window.pop event after
history.pushState({}, '')
But when the event triggered and it uses Ajax to fill the body, my Javascript would not properly re-initialize the diagram page.
I decided to use another pattern, to circumvent the the window.pop event and avoid the back-issue. Below code will not return into the Ajax code context, but instead simply replace current page, processing the Ajax return information from the server (=Controller) as a redirect link, like
var url = "/ProcessDiagram/MenuClick?command=" + idmenuparent+"_"+citem; // my Ajax
$.get(url,
function (data) {
window.location = data; // Server returns a link, go for it !
return true; // Just return true after going to the link
});
.. this will preserve the Back() context, because the browser will take care of things.
Controller side composes the redirect link, like
public ActionResult MenuClick(string command)
{
List<string> sl = command.Split(new char[] {'_'}).ToList();
var prId = int.Parse(sl[0].Substring(3));
if (sl[1] == "PU")
return Content("/ProductionUnitTypes/Details/" + UnitContextId(prId) );
if (sl[1] == "IR")
return Content("/ItemRoles/Details/" + RoleContextId(prId) );
// etcetera
}
I solved it by including the below code just before the $.get() function
$.ajaxSetup({cache: false});
It works! Try it :)

Making a function affect a element in another page

I made a function that is invoked for the lack of better words from a page, lets call it Page1, the function is called when a button is clicked, at the end of said function it calls another one that creates (or should seeing I haven't been able to test it) a html and appends it to a div with a #lista id.
The problem is that this div is another page (Page2), so I don't know if there is some syntax like in ajax where you specify where you want those values to go, so basically page 1 calls a function (on another file just in case) that function calls another and the result of that function goes on Page1 (another file, again just in case)
Here is my jQuery/JS code to further illustrate:
$("#btnAceptar").click(function() {
var idlab = $('#txtNumLab').val(),
capacidad = $('#txtCapacidad').val(),
carrera = $('#txtCarrera').val(),
ubicacion = $('#txtUbicacion').val();
var request = $.ajax({
url: "includes/functionsLabs.php",
type: "post",
data: {
'call': 'addLab',
'pIdLab':idlab,
'pCapacidad':capacidad,
'pCarrera':carrera,
'pUbicacion':ubicacion},
dataType: 'json',
success: function(response){
alert('exito')
agregar();
}
});
});
This function should affect a element with id #Lista on Page2.
function agregar(){
var div = $( "#lista" ).append( "<div class='box'>
<p>Lab #'numero'</p>
<p class='info'><a href='#' id='lnkInfo'>Info</p></a>
<p class='info'><a href='reservarLab.html'>Reservar</p></a>
</div>" );
div.id = querySelectorAll('#lista > div').length +1;
var numero = div.id;
$('#numero').append(div);
}
Thanks a lot in advance!
Yes you can get content from another page using jQuery:
Ajax request gets the entire file, but you can filter the content once it's retrieved:
$.ajax({
url:href,
type:'GET',
success: function(data){
$('#content').html( $(data).find('#IDofDivToFind') );
}
});
Second Approach (Untested)
You can use JQuery .load() method:
$( "#content" ).load( "ajax/test.html div#content" );
Reference:
http://api.jquery.com/load/

Javascript breaks when I update html with Ajax

Having a problem with a webapp i've been working on lately, and it has to do with ajax reloading breaking javascript.
I have the following Ajax Call
$.ajax({
type: "POST",
url: "/sortByIngredient/",
data: JSON.stringify(
{
selectedIngredients: tempDict
}),
contentType: "application/json; charset=utf-8",
success: function(data){
var curList = $("#drinkList").contents();
console.log(curList);
$("#drinkList").empty()
$("#drinkList").append(data)
and the following Html UL
<div id = "drinkList" class="d-list">
<ul>
<li id='someID'>some Item</li>
<li id='someID2'>some Item2</li>
</ul>
</div>
I also have a jQuery callback set to activate on clicked list items. On initial loading, all works well. Once the ajax call occurs, and replaces the contents of #drinkList with another list, formatted identically. In case anyone is curious, here is the onClick callback:
$("li").click(function()
{
window.currentDrink = $(this).attr("id");
console.log(window.currentDrink);
$.ajax({
url: "/getDrink/" + $(this).attr("id"),
type: "get",
success: function(data){
$("#ingDiv").html(data);
}
});
});
After I make that Ajax call, the list modifies correctly, but after that, no more javascript seems to work. For example,the console.log is not called when i click on a list item, and the proper view doesnt update(#ingDiv, as shown in the above call)
Is my changing the HTML through Ajax breaking the javascript somehow?
Am I missing something obvious? If it isn't clear already, I am not a web developer.
use event delegation like this -
$('#drinkList').on('click','li',function(){
// do your stuff here
});
As you are not a web developer - This is what your code should look after changes
$('#drinkList').on('click', 'li', function () {
window.currentDrink = $(this).attr("id");
console.log(window.currentDrink);
$.ajax({
url: "/getDrink/" + $(this).attr("id"),
type: "get",
success: function (data) {
$("#ingDiv").html(data);
}
});
});
http://learn.jquery.com/events/event-delegation/
http://api.jquery.com/on/

Categories

Resources