I'm trying to use AJAX to dynamically generate a JquerUI Accordion based on what is selected in a box. Currently I have
<div style="display:none" id="testselect">
</div>
With JS
$("#courseselect").change(function () {
$("#testselect").html(""); // Empty any previous data
$("#testselect").css("display", "block"); // Display it if it was hidden
$.getJSON('json.php?show=tests&courseid=' + $(this).val(), function(data) {
for(x in data)
{
$("#testselect").append("<h3 value=\"" + data[x].uno + "\">" + data[x].name + "</h3>");
$("#testselect").append("<div>Foo</div>");
}
$("#testselect").accordion({ change:function(event, ui) { courseid = ui.newHeader.attr("value");
} });
});
});
Now this works the first time I change my selection, but after that it reverts to plain old unformatted HTML. As if the call to .accordion() was never done. I'm guessing this has something to do with JQuery not wanting me to format something twice, but I really have no idea.
Try to destroy the accordion before you empty the div and start again:
$("#courseselect").change(function () {
$("#testselect")
.accordion("destroy")
.empty() // equivalent to .html("");
$.getJSON(...
More info here.
Good luck!
Related
in jQuery i'm using ajax and after getting data from that i create simple table with this data, for example
$.ajax({
method: 'GET',
url: '/analyzePage/searchTag/' + tagName,
contentType: false,
processData: false,
success: function (data) {
console.log(data);
setTimeout(function () {
if (data.state == 'error') {
...
}
else {
let table = '<div class="table-responsive pre-scrollable">';
...
$.each(data.tags, function (key, value) {
...
table = table + '<button type="button" class="btn btn-warning btn-icon btn-rounded legitRipple" id="searchTag-' + value.name + '">';
table = table + '<i class="icon-file-plus"></i>';
table = table + '</button>';
table = table + '</td>';
table = table + '</tr>';
});
...
$('.data').html(table);
}
}, 800);
},
error: function (data) {
console.log(data);
}
});
in this code and into $.each i add simple <button> with this id id="searchTag-"' + value.name + '.
now my question is how can i get this id with jquery? parent .data class is div with searchHashTag id as:
my below jquery code doesn't work and i can't get id from added buttons
$("[id^='searchTag']").on('click', function () {
alert($(this).attr("id").split("-")[1]);
});
Your buttons are loaded dynamically. Most likely, you are declaring the click event handler before the elements actually exist on the page, therefore, it does not find them. You can solve this in two ways.
Method 1
Add the click handler only when the elements exist:
// Inside your ajax callback (every time new buttons are added)
$('.data').html(table);
$("[id^='searchTag']").on('click', function () {/*...*/});
Method 2 (I would recommend this one)
Use event delegation. It will bind the click event on an existing ancestor element, and work on any button you add later:
// Anywhere you want, but it needs to be executed only once
$(document).on('click', "[id^='searchTag']", function(){/*...*/});
Method 2 is preferred, because with method 1, for example if you have a Load more button which adds new buttons while keeping the ones loaded before, the latter ones will execute the click handler multiple times.
Note that using document as the ancestor element is safe because we know it always exist when your code is executed, but it would be better (perfomance wise) if you used a more precise container which already exists in your HTML. If that is the case for your .data container, then you should use $('.data').on('click', '[id^.... (Again, only execute this once).
For this I am dynamically recoloring each option in the select. I have tried both open and opening and when they are called the menu that is being created yet exists.
$(document).on("select2:opening", function () {
console.log('Here', $('#select2-SELECTNAME-results li').length);
$('#select2-SELECTNAME-results li').each(function(k,ele){
console.log(k, $(ele).text());
$(ele).css('background-color', COLOROBJECT[k]).addClass('text-shadow');
});
});
If I run the code after it has created the menu, it works great. I need a callback that would tell me when the menu has been created. Does this exist and I am missing it, or is this a feature that is missing from, or outside the scope of, select2?
Select2 has the templateResult configuration that allows you to change the appearance of the dropdown. See here: https://select2.org/dropdown
An example:
$("#select2-SELECTNAME-results").select2({
...
templateResult: function(data) {
return '<li class="text-shadow" style="background-color:' + COLOROBJECT[k] + '" >' + data.text + '</li>';
}
...
})
I have been having problems with deep-linking when I want to make a back or forward recall to some php script that involves a query to my data base.
I think that whats happening is that when a link requires a php script that is on a deeper level it doesn't makes the callback to the server. It just works when it uses the same php script that uses the link that was displayed right back or after it.
This is my JS function:
function loadload(loc) {
$("document").ready(function(){
function loadURL(url) {
console.log("loadURL: " + url);
$(loc).load(url);
}
// Event handlers
$.address.init(function(event) {
console.log("init: " + $('[rel=address:' + event.value + ']').attr('href'));
}).change(function(event) {
$(loc).load($('[rel=address:' + event.value + ']').attr('href'));
console.log("change");
})
$('a').click(function(){
loadURL($(this).attr('href'));
});
});
};
This is my php echo line:
echo "<li><a onclick='loadload("."""."#txtHint".""".")' href="."'php/getdaimler.php?q=".$row['Program']."'"."rel="."'address:/Daimler/".$row['Program']."'>". $row['Program']. "</a></li><br>";
Also it makes my page become slower when several links have been triggered.
If there are some better functions or methods to use it would be great.
I'll appreciate your answers.
The posted jQuery Code can't work like this. First you use an inline event handler (onclick) inside the html code.
echo "<li><a onclick='loadload("."""."#txtHint".""".")' href="."'php/getdaimler.php?q=".$row['Program']."'"."rel="."'address:/Daimler/".$row['Program']."'>". $row['Program']. "</a></li><br>";
The method you call is loadload, the parameter is "#txtHint" which is used as a jQuery selector, but will never match any DOM Element. My best guess is, you want to load the server answer to an element with the id 'txtHint', in that case the selector would be: #txtHint.
Now to the jQuery/ javascript function itself:
function loadload(loc) {
// this is wrong, you can not use the event handler for dom ready here...
$("document").ready(function(){
function loadURL(url) {
console.log("loadURL: " + url);
$(loc).load(url);
}
// Where does $.address come from?....
// Event handlers
$.address.init(function(event) {
console.log("init: " + $('[rel=address:' + event.value + ']').attr('href'));
}).change(function(event) {
$(loc).load($('[rel=address:' + event.value + ']').attr('href'));
console.log("change");
})
// and here you'll define another click handler - inside the click handler
// will never be executed...
$('a').click(function(){
loadURL($(this).attr('href'));
});
});
};
Either you use the inline event handler, or a general bind logic, do not mix it.
Variant a: inline event handler
function loadload(loc,url) {
console.log("loadURL: " + url);
$(loc).load(url);
}
echo "<li><a onclick='loadload(\"#txtHint\",\"php/getdaimler.php?q=".$row['Program']."\")' href='php/getdaimler.php?q=".$row['Program']."' rel='address:/Daimler/".$row['Program']."'>". $row['Program']. "</a></li><br>";
Variant b: general binding:
$("document").ready(function(){
$('a.loadload',function() {
$('#txtHint').load($(this).attr('href'));
});
});
echo "<li><a class='loadload' href='php/getdaimler.php?q=".$row['Program']."' rel='address:/Daimler/".$row['Program']."'>". $row['Program']. "</a></li><br>";
So far for your javascript / html code. To be honest I have no idea if this fits your 'deep link' question, or the db-query you talked about, but it might be a starting point.
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.
REVISED QUESTION (SEE BELOW FOR ORIGINAL):
Here is an example of a simple ajax load with an event binding on an element within the loaded content:
soTest.htm
<!DOCTYPE html>
<html>
<head>
<script language="JavaScript" type="text/javascript" src="http://code.jquery.com/jquery-1.6.min.js"></script>
<script>
function changeBG(obj)
{
alert('Color 1: Should Turn Red');
jQuery(obj).css('background-color','red');
alert('Color 2: Should Turn Green');
jQuery('#' + jQuery(obj).attr('id')).css('background-color','green');
}
jQuery(document).ready(
function() {
jQuery('.loadedContent').load('soTest2.htm');
jQuery('body').delegate("#theElem","click",
function(){
var obj = this;
jQuery('.loadedContent').load('soTest2.htm',
function(){
changeBG(obj);
}
);
});
}
);
</script>
</head>
<body>
<div class="loadedContent">
</div>
</body>
</html>
Ajax loaded content, soTest2.htm:
<div id="theElem" >
Hello
</div>
So why is it that this doesn't work:
jQuery(obj).css('background-color','red');
But this does:
jQuery('#' + jQuery(obj).attr('id')).css('background-color','red');
++++++++++ORIGINAL QUESTION:++++++++++
I have a table that I want to sort when specific table headings are clicked (those with the class "sort").
For instance:
Location
To do that I have this code:
jQuery('body').delegate("click", ".sort", function(event) {
event.preventDefault();
jQuery('.searchResults').html('<div align="center" style="margin-top:35px;"><img src="/common/images/ajax-loader_big.gif" /></div>');
var TimeStamp = new Date().getTime();
var sortItem = this;
jQuery('.searchResults').load('modules/configSearchResultsOutput.cfm?' + TimeStamp + '&sortby=' + jQuery(this).attr('sortby') + '&direction=' + jQuery(this).attr('direction'), {
data: jQuery('#results').val()
}, function() {
sortCallback(sortItem);
});
});
So on the click event for one of these sortable column headings I'm storing the entire 'this' scope in a var to pass through to this function.
To simplify the question I'll just say that we're trying to change the background color of the clicked element based on the custom attr 'direction' I'm using:
function sortCallback(obj) {
//Returns correct attribute value
alert('In Callback: ' + jQuery(obj).attr('direction'));
//Does not return correct attribute value -- almost like it's cached or something
alert('Long hand reference: ' + jQuery('.sort[sortby="' + jQuery(obj).attr('sortby') + '"]').attr('direction'));
//Must reference value via (obj) to get correct updated value
if (jQuery(obj).attr('direction') == 'asc') {
//Changing a value within the element via this longhand approach works
jQuery('.sort[sortby="' + jQuery(obj).attr('sortby') + '"]').css('background-color', 'red');
//Changing a value within the element via this shorter approach does not work
jQuery(obj).css('background-color', 'red');
}
else {
//Works
jQuery('.sort[sortby="' + jQuery(obj).attr('sortby') + '"]').css('background-color', 'green');
//Doesn't work
jQuery(obj).css('background-color', 'green');
}
}
I'm assuming I'm not understanding some aspect of javascript scoping (understanding 'this' has been very elusive to me).
Question summarized:
If I'm passing a var'd 'this' scope to a function why can't I change the aspects of the 'this' element, why must I drill down using the long way to change them?
A tricky question for me to articulate, hopefully I did a good enough job.
Thanks!
This is happening because your ajax call replaces the DOM element. obj refers to a DOM element that was in the DOM before you called .load, but was replaced. Another element with the same ID does exist, though! That's the one you're referring to with your 'longhand' method.
I think your problem is because that load call is asynchronous, causing jQuery to get confused. Put your code inside a callback for load and it should work:
jQuery(document).ready(function() {
jQuery('.loadedContent').load('soTest2.htm',
function(resp, status, xhr){
jQuery("#theElem").bind('click',
function(){
changeBG(this);
});
});
});