Can't detect click on links generated by jQuery - jquery-selectors

I'm generating some links for pagination of some data.
Here's the function that generates the links:
function BuildPaginationNav(targetPage, pageSize) {
var numRecords = $('#movieListTable').children().length,
numPages = Math.ceil(numRecords / pageSize),
startRecord = ((targetPage - 1) * pageSize);
for (var i = startRecord; i <= startRecord + pageSize - 1; i++) {
$('div#movieListTable > div:eq(' + i + ')').fadeIn(200);
}
// Only use prev page and first page buttons/links if not on first page
if (targetPage > 1) {
$('#pagination').append('<br>First Page | Prev Page | ');
} else if (targetPage = 1) {
$('#pagination').append('<br>First Page | Prev Page | ');
}
// Add the current page label
$('#pagination').append('<label id="currentPage">' + targetPage + '</label>');
// Only use next page and last page buttons/links if not on last page
if (targetPage < numPages) {
$('#pagination').append(' | Next Page | Last Page');
} else if ( targetPage === numPages) {
$('#pagination').append(' | Next Page | Last Page');
}
}
The above works as intended and the function is called at the end of the success function in an $.ajax call that gets the data that the pagination is for.
Here's what the generated HTML looks like if it's not on the first or last page:
<div id="pagination">
<br>
First Page |
Prev Page |
<label id="currentPage">2</label> |
Next Page |
Last Page
</div>
What I need to do is get the ID of the link that is clicked on so I can take the appropriate action. I've tried this:
$('#pagination a').click(function() {
console.log(this.id);
});
and I've also tried this:
$('#pagination a').on('click', function() {
console.log(this.id);
});
But neither works - well, if I put the generated HTML and the above jQuery in a jsFiddle it does work, but it doesn't in the full code.
I am especially surprised that $.on() doesn't work in this case, as I use that function elsewhere in my code.
If I put the generated HTML as HTML in the page itself, the jQuery does work, so it's got to have something with the fact that the links are generated dynamically.
How can I get clicks on those links to be detected?

I figured it out:
I found the function $.delegate();
I added this code at the end of the BuildPaginationNav() function:
$('#pagination').delegate('a', 'click', function() { console.log(this.id); });
I'll just call a function from there (where the console.log() is) that will perform the necessary actions.
If there's a different (or even better) way, let me know!

Your links are not created yet when binding event. You need to bind live action on some existing element.
$(document).ready(function() {
$("#pagination").on('click', 'a', function() { .... });
});
The '#pagination' element is supposed to be available in time of binding event. It's called delegated event - http://api.jquery.com/on/

I would have done it in following way.
Your way:
// Only use prev page and first page buttons/links if not on first page
if (targetPage > 1) {
$('#pagination').append('<br>First Page | Prev Page | ');
} else if (targetPage = 1) {
$('#pagination').append('<br>First Page | Prev Page | ');
}
My Way:
// Only use prev page and first page buttons/links if not on first page
if (targetPage > 1) {
$FirstPage=$('First Page');
$FirstPage.click(function() { .... });
$('#pagination').append($FirstPage);
//same for Prev page...
} else if (targetPage = 1) {
// same as above..
}
This way...i'm able to locate my links behaviour at one place only i do not need to search in the whole page to know.. what click event for anchors..and many more !!

Related

CrossRider: What library method scope can be used in a popup?

I have saved data in the appAPI.db.async database. And now I want to display it in the popup page.
Here's what I have in the popup page:
function crossriderMain($) {
var db_keys = appAPI.db.async.getKeys();
db_keys.forEach(
function(key)
{
$("ul#id").append("<li>" + appAPI.db.async.get(key).url + "</li>");
});
}
</script>
</head>
<body>
<ul id="history">History</ul>
</body>
</html>
which doesn't give the intended result.
What I want to know is what's available for me when inside a popup page?.
Also, as an aside question: how do I open a browser tab from an HTML page in my resources directory, instead of a popup that won't take the whole screen space, in the browserAction.onClick handler?
Something like that in background.js:
appAPI.browserAction.onClick(
function()
{
appAPI.tabs.create("/Resources/templates/history.html");
}
);
Thanks (:->)
Answer to question 1
appAPI.db.async is asynchronous by design and hence you must use a callback to receive and use the values from the database. Additionally, it is not necessary to get the keys first and then their associated data; you can simply achieve your goal in one step using appAPI.db.async.getList.
Hence, using your example the code should be:
function crossriderMain($) {
appAPI.db.async.getList(function(arrayOfItems) {
for (var i=0; i<arrayOfItems.length; i++) {
$("ul#id").append("<li>" + arrayOfItems[i].value + "</li>");
}
});
}
Answer to question 2
To create a new tab that opens a resource page, use the appAPI.openURL method.
Hence, using your example the code should be:
appAPI.ready(function($) {
// When using a button, first set the icon!
appAPI.browserAction.setResourceIcon('images/icon.png');
appAPI.browserAction.onClick(function() {
appAPI.openURL({
resourcePath: "templates/history.html",
where: "tab",
});
});
});
[Disclaimer: I am a Crossrider employee]

How can I bind to jQuery UI tab event click/select/active?

I'm a beginner/intermediate level developer/programmer. I've got jQuery-UI-Tabs that I'm building in jQuery like so (they show up and function fine):
var paymentTabs = $('<div id="paytabs">');
...
var paymentTabList = $('<ul>');
paymentTabs.append(paymentTabList);
if($.inArray('check',options.methods) != -1){
paymentTabList.append('<li>Pay with an E-Check</li>');
paymentTabs.append(payByCheck);
}
if($.inArray('card',options.methods) != -1){
paymentTabList.append('<li>Pay with a Credit/Debit Card</li>');
paymentTabs.append(payByCard);
}
if($.inArray('code',options.methods) != -1){
paymentTabList.append('<li>Business Office Use Only</li>');
paymentTabs.append(payByCode);
}
paymentTabs.tabs({show: function(event, ui) {
item.currentMethod = ui.panel.id;
self._refreshCart();
}
});
paymentTabs.tabs({show: function(event, ui) {
item.currentMethod = ui.panel.id;
self._refreshCart();
}
});
Binding to them does not work:
$( "#paytabs" ).on( "tabsselect", function(event, ui) {
alert("tab has been clicked.");
});
Neither does this:
$( "#paytabs" ).bind( "tabsselect", function(event, ui) {
alert("tab has been clicked.");
});
I also tried tabsactivate instead of tabsselect. I tried selecting by class and by id. I tried selecting transverse and walking the DOM. Eventually, I'm going to use the function that I bind to the tab, to add a 3% fee to the billing total. I will also make this function change the JSON key, attribute "required" to "true" for a specified input element. This is critical for me to get this function bound... I really appreciate the help.
Look here: http://api.jqueryui.com/tabs/#event-activate
Bind to the tab 'activate' event. So when a tab is clicked the activate function is fired.
Like This:
$("#paytabs").tabs({
activate: function( event, ui ){
/* do something here */
}
});
or
$("#paytabs").on( "tabsactivate", function( event, ui ){
/* do something here */
});
Here is what worked for me. Aran's solution worked in part (thank you Aran).
Step One:
Bind to tabs activate as Aran described, but directly on the element as it is instantiated. There is no need for an element selector if you do this.
billing_div.append('<h3>Payment Information</h3>');
var paymentTabs = $('<div id="paytabs">').tabs({select: function( event, ui ) {alert("tab has been clicked.");}});
billing_div.append(paymentTabs);
Step Two:
Add classes manually/problematically. remember to include ui-tabs-selected only for the tab which tab is selected at page load.
var paymentTabList = $('<ul>').addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
paymentTabs.append(paymentTabList);
if($.inArray('check',options.methods) != -1){
paymentTabList.append('<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active">Pay with an E-Check</li>');
paymentTabs.append(payByCheck);
}
if($.inArray('card',options.methods) != -1){
paymentTabList.append('<li class="ui-state-default ui-corner-top">Pay with a Credit/Debit Card</li>');
paymentTabs.append(payByCard);
}
if($.inArray('code',options.methods) != -1){
paymentTabList.append('<li class="ui-state-default ui-corner-top">Business Office Use Only</li>');
paymentTabs.append(payByCode);
}

How to fire place_changed event for Google places auto-complete on Enter key

The click seems to fire the event and set the cookies but pressing enter to submit doesn't set the cookies and instead the page redirects without the cookies.
function locationAuto() {
$('.search-location').focus(function () {
autocomplete = new google.maps.places.Autocomplete(this);
searchbox = this;
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var thisplace = autocomplete.getPlace();
if (thisplace.geometry.location != null) {
$.cookie.raw = true;
$.cookie('location', searchbox.value, { expires: 1 });
$.cookie('geo', thisplace.geometry.location, { expires: 1 });
}
});
});
The .search-location is a class on multiple textboxes.
There is a submit button that takes the values from the cookies and redirects (server side)
Adapted from Jonathan Caulfield's answer:
$('.search-location').keypress(function(e) {
if (e.which == 13) {
google.maps.event.trigger(autocomplete, 'place_changed');
return false;
}
});
I've encountered this problem as well, and came up with a good solution. In my website I wanted to save the autocomplete.getPlace().formatted_address in a hidden input prior to submission. This worked as expected when clicking the form's submit button, but not when pressing the Enter key on the selection in the autocomplete's dropdown menu. My solution was as follows:
$(document).ready(function() {
// Empty the value on page load
$("#formattedAddress").val("");
// variable to indicate whether or not enter has been pressed on the input
var enterPressedInForm = false;
var input = document.getElementById("inputName");
var options = {
componentRestrictions: {country: 'uk'}
};
autocomplete = new google.maps.places.Autocomplete(input, options);
$("#formName").submit(function(e) {
// Only submit the form if information has been stored in our hidden input
return $("#formattedAddress").val().length > 0;
});
$("#inputName").bind("keypress", function(e) {
if(e.keyCode == 13) {
// Note that simply triggering the 'place_changed' event in here would not suffice, as this would just create an object with the name as typed in the input field, and no other information, as that has still not been retrieved at this point.
// We change this variable to indicate that enter has been pressed in our input field
enterPressedInForm = true;
}
});
// This event seems to fire twice when pressing enter on a search result. The first time getPlace() is undefined, and the next time it has the data. This is why the following logic has been added.
google.maps.event.addListener(autocomplete, 'place_changed', function () {
// If getPlace() is not undefined (so if it exists), store the formatted_address (or whatever data is relevant to you) in the hidden input.
if(autocomplete.getPlace() !== undefined) {
$("#formattedAddress").val(autocomplete.getPlace().formatted_address);
}
// If enter has been pressed, submit the form.
if(enterPressedInForm) {
$("#formName").submit();
}
});
});
This solution seems to work well.
Both of the above responses are good answers for the general question of firing a question when the user presses "enter." However - I ran into a more specific problem when using Google Places Autocomplete, which might have been part of the OP's problem. For the place_changed event to do anything useful, the user needs to have selected one of the autocomplete options. If you just trigger 'place_changed', the if () block is skipped and the cookie isn't set.
There's a very good answer to the second part of the question here:
https://stackoverflow.com/a/11703018/1314762
NOTE: amirnissim's answer, not the chosen answer, is the one to use for reasons you'll run into if you have more than one autocomplete input on the same page.
Maybe not the most user friendly solution but you could use JQuery to disable the enter key press.
Something like this...
$('.search-location').keypress(function(e) {
if (e.which == 13) {
return false;
}
});

jQuery - Refresh Contents of a DIV

I have a form in a jQuery popup on a webpage. The jQuery popup is a div named .vote-form and the form inside it has the name "#form".
When the form is submitted, the content inside the jQuery popup changes to a success message. I need to make it so that when the jQuery popup is closed, the success message is removed and the form is refreshed back to the original form, so that when the jQuery popup is opened again, the form is showing again and NOT the success message.
My feeble attempt to get this result involved refreshing the ENTIRE page when the jQuery popup is closed. This PARTLY has the desired result, but when the page is refreshed, most browsers get a popup asking if the user wants to resubmit the form content. I need to avoid this.
This was my code handling the closing of the .vote-form:
$('.vote-form-close').click(function(event) {
event.stopPropagation();
$(".vote-form").fadeOut("normal");
$("#the-lights").fadeTo("slow",0);
$("#the-lights").css({'display' : 'none'});
window.location.reload();
});
I suspect that its possible to refresh ONLY the div, and not the entire page, but I do not know how to accomplish it.
Can someone assist me?
EDIT: Based on one of the answers below, I modified my code. I also wanted to show the code used to open the form up too:
$('.vote').click(function() {
$(this).parent().find(".vote-form").fadeIn("normal");
$("#the-lights").css({'display' : 'block'});
$("#the-lights").fadeTo("slow",0.7);
});
$('.vote-form-close').click(function(event) {
event.stopPropagation();
$(".vote-form").fadeOut("normal");
$("#the-lights").fadeTo("slow",0);
$("#the-lights").css({'display' : 'none'});
$(".vote-form").load(window.location.href + " .vote-form-container");
});
Here is the problem - I have 3 forms on the page. When "vote-form-container" is loaded, its loading ALL THREE forms into the .vote-form box - how do I modify the code to only load the .vote-form-container that is part of the specific .vote-form - I suspect I have to use $(this) but I tried modifying the code to this and it didnt work:
$(".vote-form")(this).load(window.location.href + " .vote-form-container");
I am thinking I did it wrong.
EDIT 2: Now the "Close" button dosen't work after the form is reloaded the first time:
$('.vote').click(function() {
$(this).parent().find(".vote-form").fadeIn("normal");
$("#the-lights").css({'display' : 'block'});
$("#the-lights").fadeTo("slow",0.7);
});
$('.vote-form-close').click(function(event) {
event.stopPropagation();
$(".vote-form").fadeOut("normal");
$("#the-lights").fadeTo("slow",0);
$("#the-lights").css({'display' : 'none'});
var current_form = $(this).closest('.vote-form'),
index = $('.vote-form').index(current_form)
current_form.load(window.location.href + " .vote-form-container:eq(" + index + ")");
});
Don't reload the page but redirect your user:
window.location.href = window.location.href.toString()
Or load the new form with ajax:
$(".vote-form").load(window.location.href + " .vote-form");
For more information on the ajax approach see api.jquery.com/load/#loading-page-fragments
Update:
Using jQuery the index function you are able to replace only the current form.
// I asume your button is in the form
var current_form = $(this).closest('.vote-form'),
index = $('.vote-form').index(current_form)
current_form.load(window.location.href + " .vote-form:eq(" + index + ")");
... I need to make it so that when the jQuery popup is closed, the success message is removed and the form is refreshed back to the original form...
So, if I well understood:
$('.vote-form-close').click(function(event) {
event.stopPropagation();
var vf = $(".vote-form");
/* fadeout and remove inner content of the popup */
vf.fadeOut("normal", function() { vf.empty(); });
/* reset the form */
document.getElementById('form').reset();
...
});

Popup browser back to parent browser after a certain page is reached

I have a popup (which I used by necessity) that is opened on a link click. I have the user going through a series of pages picking attributes to then be sent to a shopping cart.
My problem: After the user reaches the end of the selection process i want to kill the open popup and send the request back to the original browser (parent) so the user can checkout.
Any idea how I would do this?
Javascript: in the child (popup) window.
window.opener.location = 'page.html";
window.close();
Is that what your looking for?
The parent window can be accessed using "opener" in JavaScript.
Example:
window.opener.title='hello parent window';
or
window.opener.location.href='http://redirect.address';
Script in my child form:
<script language="JavaScript" type="text/javascript">
function SetData() {
// form validation
// var frmvalidator = new Validator("myForm");
// frmvalidator.addValidation("name","req","Please enter Account Name");
// get the new dialog values
var str1 = document.getElementById("name").value;
var winArgs = str1;
// pass the values back as arguments
window.returnValue = winArgs;
window.close();
document.myForm.submit();
}
</script>
Script in my parent form:
<% #account_head= current_company.account_heads.find_by_name("Sundry Debtors")%>
<script type="text/javascript">
function OpenDialog() {
var winSettings = 'center:yes;resizable:no;help:yes;status:no;dialogWidth:450px;dialogHeight:200px';
// return the dialog control values after passing them as a parameter
winArgs = window.showModalDialog('<%= "/accounts/new?account_head_id=#{#account_head.id} #man" %>', winSettings);
if(winArgs == null) {
window.alert("no data returned!");
} else {
// set the values from what's returned
document.getElementById("to_account_auto_complete").value = winArgs;
}
}
</script>
This is work but not as i want, any one if found good solution please suggest.