jQuery event fires once, then never again - javascript

I've been wrestling with a simple JQuery event handler for hours.
My event handler fires exactly once, when the page loads, and never again no matter the event or the interaction with the select box.
When deferred, the alert (when I have one) shows the first select option. When not, the alert is blank.
All I want is for the select box to load from AJAX and for a user choice to trigger another AJAX call.
HTML:
<select id="connection" name="Connection"></select>
<div id="testme" style="background: #CCC; width:100%; height:50px;position:relative;color:red">testing</div>
Javascript:
$(document).ready(function () {
// Event handler. Tried as a separate function and as a parameter to $.on(...)
function connectionSelected() {
var str = $('#connection option:selected').text();
alert(str);
$("#testme").text(str);
}
var $connectionSelect = $('#connection');
//$connectionSelect.selectmenu(); // Tried enabling/disabling
// Tried this and all JS code inside and outside of $(document).ready(...)
$.when(
$.ajax({
dataType: "JSON",
url: '#Url.Content("~/API/ConnectionHint")', // The AJAX call (using ASP Razor) works fine
success: function(data) {
// This function is always called and works
var items = [];
$.each(data, function(key, val) {
items.push("<option value='" + key + "'>" + val + "</option>");
});
$connectionSelect.append(items.join(""));
// Tried setting up the event handler here
},
error: function() {
$connectionSelect.html('<option id="-1">none available</option>');
}
})
).then(function() {
//$("#connection option").blur(connectionSelected()).change();
$("#connection").on("change", connectionSelected());
});
});
Tried dozens of variations of the event handler, several events, inside and outside of a deferred.done and deferred.then, etc.. E.g.:
$connectionSelect.selectmenu({
change: function (event, data) {
$('#connection').change(function () {
var str = "";
$('#connection').each(function () {
str += $(this).text() + "<br>";
});
$("#testme").text(str);
});
}
});
I usually write back-end code and am familiar only with portions of JQuery, and this is driving me crazy. I've looked more than 30 related question on SO and elsewhere, e.g.
Jquery event fires once
Jquery .change() function not working with dynamically populated SELECT list
http://jqueryui.com/selectmenu/#product-selection
Any ideas are appreciated.

Instead of
$("#connection").on("change", connectionSelected());
try
$("#connection").on("change", connectionSelected);
Note that in the second one I'm passing your function handler by reference, instead of invoking it.

Related

How do I rebind jquery calls after ajax load?

Okay so I use a masonry script for arranging images in a grid, I placed it in a function arange_images() in an external script.
In my main script i call
$(document).ready(function(){
arange_images(); //<- Works lovely
});
Then i decide to load some other images with ajax. After that, my images stop being arranged.
function get_img(section_id) {
$.ajax({
type: 'GET',
url: './db/get_img.php',
data: {
section_id: section_id
},
success: function (data) {
var data_parsed = JSON.parse(data);
var images = '<div class="grid-sizer"></div><div class="gutter-sizer"></div>';
$.each(data_parsed, function (i, picture) {
images += '<div class="member">';
images += ' <img src="img/pictures/' + picture.path + '" alt="' + picture.alt + '"/>';
images += '</div>';
});
$('.grid').html(images);
arange_images(); //<- Does not work
}
});
}
$('.section_selector').click(function () {
get_img($(this).attr('data-section_id'));
arange_images(); //<- Does not work either
});
Searching similar errors did not help me.
Most of the problems with jquery after ajax are .click replaced with .on('click').
I read that I need to rebind jquery calls, but I don't really understand how to do it in this situation.
Your .click() handler will only bind elements that exist within the DOM at the time the document is ready. Since you need to bind to the elements after the ajax call, use .on().
Keep Calm and Call .on
$(document).on('click', '.section_selector'), function () {
get_img($(this).attr('data-section_id'));
});

JS: Make a callback return the output of another callback

I am using the Javascript magicsuggest plugin.
This plugin has a callback selectionRenderer that allows you to change the html of a selection before it's inserted.
What I'm trying to do, is to change that selection html based on user input.
So the way I have it setup, the selectionRenderer callback opens a Bootstrap modal which has a form inside it. Then another submit callback is created for when that form is submitted.
I can't figure out how to pass the data that is collected in the submit callback into that selectionRenderer callback.
$(function() {
var modal = $('#exampleModal');
$('#magicsuggest').magicSuggest({
selectionRenderer: function(data){
modal.modal('show');
var color = 'red';
modal.find('#color-form').submit(function(e) {
e.preventDefault();
color = $(this).find('#color-input').val();
console.log(color);
modal.modal('hide');
});
return '<span style="color: '+color+';">' + data.name + '</span>';
},
allowFreeEntries: false,
data: data
});
});
JSFiddle
As you can see, the color in this example is collected in the submit callback, but since that callback is fired asynchronously, there is no way to pass that data to the selectionRenderer callback, because that function has already returned.
In a perfect world I could obviously just make the code stop and wait for a callback to continue, but since it's a plugin I'd rather not fork and butcher it.
Change the event that opens the modal to the selection event and in the submit handler look for the last tag to change it's color
var ms = $('#magicsuggest').magicSuggest({
selectionRenderer: function(data) {
return '<span class="my-tags">' + data.name + '</span>';
},
allowFreeEntries: false,
data: data
})
$(ms).on('selectionchange', function(e, m) {
modal.modal('show');
});;
$('#color-form').submit(function(e) {
e.preventDefault();
var color = $('#color-input').val();
$('.my-tags:last').css('color', color);
modal.modal('hide');
});
DEMO

Jquery addClass -- Function for New Class

I have a issue in my js file.
This is my Js Code.
<script type="text/javascript">
$(document).ready(function()
{
$(".abc").click(function()
{
$(this).addClass('testingClass');
});
$(".testingClass").click(function()
{
alert("hiiiiiiiiiiiiiiiiii")
});
});
</script>
My HTML :
<button class="abc">Demo</button>
When i load this page in Browser, The addClass function is successfully executing and adding new class named "testingClass".
But When Try to click again t that button (meens : class="testingClass") the alert function does not working. What is the error.
Is JS is not supporting frequent execution of an element ?
Anybody Please help me.
Steps..
One Button has class named abc
When click on it an ajax function will storing current time in database.(ajax function not in stack-code).
after successful ajax response the button class changed to testingClass.
now the class name of the button is testingClass
After some time Click on the Button again (class named:testingClass), i want to call a ajax function with current time of click and store the values in database.
Then the Button class name will changed to old ( abc).
You need to event delegation for dynamic added element
$(document).on("click",".testingClass",function()
{
alert("hiiiiiiiiiiiiiiiiii")
});
Event delegation
Update
For the changed question, you are looking for something like this.
Here is a demo.
$('body').on('click', '.abc', function () {
// event attached to .abc
// updateTime is a method that takes context (this), current timestamp and a function
// we need to send the context so that we have access to the current
element inside the below function which is executed outside the scope
updateTime.call(this, new Date().getTime(), function (data) {
$(this).addClass('testingClass').removeClass('abc');
$('#log').append('Time: ' + data + 'from abc <br/>');
});
}).on('click', '.testingClass', function () {
// event attached to .abc
updateTime.call(this, new Date().getTime(), function (data) {
$(this).addClass('abc').removeClass('testingClass');
$('#log').append('Time: ' + data + ' from testingclass <br/>');
});
});
function updateTime(currentTime, successCallback) {
$.ajax({
context: this, // the context sent from the above methods is used here
url: '/echo/html/',
data: {
html: currentTime
},
method: 'post',
success: successCallback
});
}
Using .one() will help you attach event only once upon multiple clicks.
This handler is executed at most once per element per event type.
I think this is what you are looking for. Adding a handler after the class is added.
$(".abc").click(function(){
$(this).addClass('testingClass');
$(".testingClass").one('click', function() {
alert("hiiiiiiiiiiiiiiiiii");
});
});
$(document).ready(function() {
$(".abc").click(function() {
$(this).addClass('testingClass');
$(".testingClass").one('click', function() {
alert("hiiiiiiiiiiiiiiiiii");
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="abc">Demo</button>

Call jquery function when one function completes

So I have a jquery click function assigned to an on/off toggle. Very simple script:
$('.on-off').on('click', function(e) {
e.preventDefault();
var $this = $(this);
$this.find('.slider').toggleClass('active');
});
We have two versions of this toggle. One toggles instantly when clicked and then we submit the value when clicking next(aka submit).
Our other one calls a jquery ajax function that toggles on success and upon success if it is a specific message code that is defined on the backend.
jQuery.ajax({
url: url,
type: 'POST',
dataType: 'json',
cache: false,
data: {'requestType': requestType},
success: function(message) {
if(message.STATUS=='2000'){
if(currentButtonClicked=='dashboardChargingButton'){
if($('#dashboardChargingButton').html()==startCharge)
$('#dashboardChargingButton').html(stopCharge);
else
$('#dashboardChargingButton').html(startCharge);
}
if(currentButtonClicked=='invokeChargingButton'){
$( "#invokeChargingButton .slider" ).toggleClass( 'active');
}
}
},
error: function(xhr, ajaxOptions, thrownError) {
alert(xhr.status + " - " + xhr.statusText);
}
});
}
As you can see I have to toggle the class again using the same code but with direct targeting.
The on off toggles of this type have an onclick inside the actual html calling the function that handles this ajax.
My goal is to have my first set of code the one that targets the element and toggles the class to do all of this, but dynamically to where we don't have to call a function everytime.
Conceptually what I thought is:
$('.on-off').on('click', function(e) {
e.preventDefault();
var $this = $(this);
if (!$this.attr('onclick')) {
$this.find('.slider').toggleClass('active');
} else {
var clickFunction = $this.attr('onclick');
call the clickFunction
if (clickfunction = true) {
$this.find('.slider').toggleClass('active');
}
}
});
What this would do is grab the onclick, but not call it until I specify. And inside the ajax request instead of toggling I would just return true.
This might not be the best method. I am just trying to ecapsulate everything to limit the amount of code as well as make all the dom changes for those elements in one spot for any potential defects.
Here is a link to a basic fiddle of the on/off toggle.
Fiddle
I hope I explained everything in good enough detail.

jQuery elements inside a jQuery dialog stop working after ajax call

<div id="divItems"><div id="divItemsContent"></div></div>
I think i know what the problem is, just don't know how to solve it. Here is the code:
function SplitOrder() {
var SplitTable = $.ajax({
url: 'AjaxActions/SplitTable.aspx?FromObjectID=' + $('#hidObjectID').val() + '&ToObjectID=' + ObjectID[1],
async: false
}).responseText;
var dialog = $('#divItems').dialog({
autoOpen: false,
height: 500,
width: 600,
title: 'פיצול שולחן'
});
var content = $("#divItemsContent");
content.html("");
content.html(SplitTable);
dialog.dialog("open");
//הפעולות על החשבונות
/************************************************/
$('#imgLeftArrow').click(
function() {
$(this).css("background-color", "white");
//AJAX הבאת נתוני רשומת ההזמנה מהשרת ב
var SplitTable = $.ajax({
url: 'AjaxActions/SplitUpdate.aspx?FromObjectID=' + $('#hidObjectID').val() + '&ToObjectID=' + ObjectID[1] + '&ItemID=' + $('#hidItemID').val() + '&ItemAmount=' + $('#hidItemAmount').val(),
async: false
}).responseText;
content.html("");
content.html(SplitTable);
});
$('#imgRightArrow').click(
function() {
//AJAX הבאת נתוני רשומת ההזמנה מהשרת ב
var SplitUpdate = $.ajax({
url: 'AjaxActions/SplitUpdate.aspx?FromObjectID=' + $('#hidObjectID').val() + '&ToObjectID=' + ObjectID[1] + '&ItemID=' + $('#hidItemID').val() + '&ItemAmount=' + $('#hidItemAmountTo').val(),
async: false
}).responseText;
});
/************************************************/
$('div[id^="Item_"]').hover(
function(e) {
$(this).css("cursor", "pointer");
$(this).css("background-color", "blue");
},
//כשיוצאים מהשולחן DIVהעלמת ה
function() {
$(this).css("background-color", "white");
});
/************************************************/
//טיפול בבחירת פריט להוספה/הורדה מהחשבון
$('div[id^="Item_"]').click(
function() {
$('#imgLeftArrow').css("background-color", "yellow");
//הוספת הפריט לשדה הנסתר
$('#hidItemID').val($(this).children().html());
$('#hidItemName').val($(this).children().next().html());
$('#hidItemAmount').val($(this).children().next().next().html());
});
}​
I am trying to display one page using the ajax call and put the result in the dialog...This is working great!!!
Next, if someone choses an item and press the left arrow pic, I am doing another ajax call that updates the database and returns the new HTML (using XML/SXL) and I am getting the right result from that also.
I am getting the first hover and click working great, but after I'm updating the data and getting the result the hover stops working and also the click event on the arrow. I think it is because i'm rendering the data inside the click event function but I don't know how to solve it.
If you are returning HTML and you expect to have click events and hover events happen on elements within the new returned html then you need to use the .live() jQuery keyword.
Update: As of jQuery 1.7, the .live() method is deprecated (and no longer exists starting in 1.9!). Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().
I think I understand what you're trying to do...
If any of the HTML is in these statements:
$('#hidItemID').val($(this).children().html());
$('#hidItemName').val($(this).children().next().html());
$('#hidItemAmount').val($(this).children().next().next().html());
Contains jQuery, it will be rendered as plain HTML because they are being added to the DOM after event binding. What Griegs suggested willwork.
You'll need something similar to:
$('div[id^="Item_"]').live('hover', function(event) {
// do something on hover
});
$('#imgLeftArrow').live('click', function(event) {
// do something on click
});
$('#imgRightArrow').live('click', function(event) {
// do something on click
});
This way new elements will also trigger the handlers.

Categories