JQuery Treeview not working with Ajax - javascript

I'm new to JQuery and web development in general. I'm trying to load some data from an XML file and build an unordered list. I've got that part working, now I'm trying to use the TreeView plugin so I can collapse/expand the data. The data is loaded like this:
$(document).ready(function(){
$.ajax({
type: "GET",
url: "solutions.xml",
dataType: ($.browser.msie) ? "text" : "xml",
success: function(data) {
var xml;
if (typeof data == "string") {
// Work around IE6 lameness
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = false;
xml.loadXML(data);
} else {
xml = data;
}
list = ""
$(xml).find("Group").each(function() {
group = $(this).attr("name");
list += "<li><span>" + group + "</span><ul>";
$(this).find("Solution").each(function() {
solution = $(this).attr("name");
list += "<li><span>" + solution + "</span></li>";
});
list += "</ul></li>";
});
$("#groups").html(list);
},
error: function(x) {
alert("Error processing solutions.xml.");
}
});
$("#groups").treeview({
toggle: function() {
console.log("%s was toggled.", $(this).find(">span").text());
}
});
});
and the HTML looks like this:
<html>
...
<body>
<ul id="groups">
</ul>
</body>
</html>
The unordered list shows correctly, but the little [+] and [-] signs don't show up and the sections aren't collapsible/expandable. If I get rid of my Ajax loading and insert an unordered list inside of #groups manually it works as expected.
What am I doing wrong? Is there any other plugins or Javascript libs that could make this easier? The solution needs to work on IE6 locally (i.e. webserver).
Update: I found a work-around: If I define my treeview stuff like this it works:
function makeTreeview() {
$("#container").treeview({
toggle: function() {
console.log("%s was toggled.", $(this).find(">span").text());
}
});
}
setTimeout('makeTreeview();', 50);
I think the problem is, when I create the treeview, the ajax stuff hasn't done it's work yet, so when treeview() is called, the unordered list hasn't been created yet. I haven't tested this with IE6 yet. Is there a nicer way to do this, without using SetTimeout()?

I made the same type of call for another project.
For other reasons you will probably want to wrap your ajax call in an anonymous function to create a closure so that your variables remain what you expect them to...
The success method is a callback function that happens after your call is complete , just create your treeview inside that method, or break it out into a seperate fumction if you need to for clarity.
in the example that you show - your treeview will still fail if the ajax call takes longer than 50ms - which could easily happen during initial load if more than two objects are being loaded from that same server.
This example used JSON, and concurrently loaded html data from a page method into a series of divs.
$(document).ready(function() {
for (i= 1;i<=4;i++)
{
(function (){
var divname ="#queuediv"+i;
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "test12.aspx/GetHtmlTest",
data: "{}",
error: function(xhr, status, error) {
alert("AJAX Error!");
},
success: function(msg) {
$(divname).removeClass('isequeue_updating');
$(divname).html(msg);
$("#somethingfromthemsg").treeview();
}
});
})();
}
});
Hope that helps!

You need to get FireBug (Firefox add-in) and then you can see in the console what is being returned, and make sure it matches what you expect (And that it is actually doing the request..).
Once you get it working in FF, you can support the ancient 10-year old IE6 browser.
There's also some other things you may want to consider:
The whole ActiveXObject("Microsoft.XMLDOM") jumps out as me as unnecessary. If you pass XML in a string to $(), jQuery turns it into a DOM object.
Additionally, .Find can be replaced by:
$('Element', this);
So for example:
var xmlDoc = '<Group><Solution name="foo" /><Solution name="bar" /></Group>';
$('Solution', xmlDoc).each(function() {
document.write( $(this).attr('name') );
});
would spit out:
foo
bar
Also, with firebug, stick a console.log(list); at the end, to be sure you're generating the HTML you think you are. If you're really stuck in IE6, alert(list) somewhat works as a poor man's equivalent (as long as your file isn't too big).
In short, I think you're on the right track, you just need the tools to debug properly.

For anyone who also finds their way to this post. I had this trouble with an ajax call.
If you want to wait for the ajax call to be returned, you need to set async as false.
$.ajax({
type: 'POST',
async: false,
........

Related

Trying to add simple notification.... not a function

When I launch the page, I fire up the chrome dev tools and look in the sources window, load my file and I see
Uncaught TypeError: $(...).kendoNotification is not a function
Im trying to modify an existing application ive been given which uses Kendo UI. I just want to add in a notification popup.
Referring to the docs, a common cause of this is not including all required javascript resources, but they all seem to be there. jquery, kendo.all.min and were also using kendo.modernizr
Its obviously its my problem, since all the other kendo widgets work fine.
Im trying to follow this example
http://code.tutsplus.com/tutorials/adding-application-notifications-with-kendo-ui-core--cms-20989
Something is getting initialized correctly, im just not sure where/what it could be.
The page itself is rather large, but the notification is just
<span id="popupNotification"></span>
... more html
<script>
....more stuff
$.ajax({
...
success: function (result) {
var popupNotification = $('#popupNotification').kendoNotification({
appendTo: "#SalesGrid", autoHideAfter: 5000, width: 400
}).data('kendoNotification');
var d = new Date();
popupNotification.show({ time: kendo.toString(d, 'HH:MM:ss.') + kendo.toString(d.getMilliseconds(), "000") }, "time");
}
})
</script>
[update]
I just realized i was trying to show the notification from within an ajax call, so I found a more relevant example here.
[update 2, full source of function being called ]
function postBatch(e) {
//alert('made it');
$.ajax({
url: '#Html.Raw(#Url.Action("SalesAction", "SalesController"))',
data: { batchID: e, status: "POSTED" },
async: false,
dataType: "json",
type: 'POST',
success: function (result) {
var statementBatchDS = $('#SalesGrid').data().kendoGrid.dataSource;
statementBatchDS.data(result.Data);
// *** FAILS HERE *** note: SalesGrid is a KendoUI grid
var popupNotification = $('#popupNotification').kendoNotification({
appendTo: "#SalesGrid", autoHideAfter: 5000, width: 400
}).data('kendoNotification');
var d = new Date();
popupNotification.show('Batch post error, please review', 'error');
}
});
}
Where/which script source within Kendo UI is the KendoNotificaiton widget defined? Im using kendo.all.min.js, so I was assuming that included everything. Yet, when I call the notificaiton show method (see above), the error seems to indicate it cant construct the notification..which leads me to think the source isnt being included, yet the kendo.all.min.js file is clearly being pulled in as I inspect the source in Chrome's dev tools.
So off to Telerik I go, and I read these
http://docs.telerik.com/kendo-ui/intro/installation/what-you-need
http://docs.telerik.com/kendo-ui/intro/supporting/scripts-general
Yet, the "all" version is whats in the reference
http://demos.telerik.com/kendo-ui/notification/index
I had this same problem and solved removing the kendo call from inside the AJAX snippet with a function:
success: function(data){
notify();// here i call a function to send the notification
clean();//another function to clear form data.
},
...
function notify(){
var popupNotification = $("#popupNotification").kendoNotification().data("kendoNotification");
popupNotification.show("Some notification", "success");
}
Turns out it was just a matter of upgrading the version of the Kendo libraries I was using. At least im past the point of the Notification widget not being loaded.

Why .html() method does not load data in the element?

$.get("progress.txt", null, function(data_aj){
if(data_aj.substr(0,14) == "<!-- MSG:: -->"){
$("#list").html("<li>"+data_aj+"</li>");
window.clearTimeout(timeOutId);
}else{
$("#list").html(data_aj);
}
});
I really have tried everything but can't figure out whats wrong. If I use alert(data_aj); it gives the desired output and just works fine but HTML(data_aj) just doesnt loads into a <ul> element #list using .html(). Can anyone tell me why?
Have you tried putting your code in a document ready, as your alert will fire fine but if your dom is not loaded then you cannot append to it. Also use .append() for lists not html
$(document).ready(function() {
$.get("progress.txt", null, function(data_aj){
if(data_aj.substr(0,14) == "<!-- MSG:: -->"){
$("#list").append("<li>"+data_aj+"</li>");
window.clearTimeout(timeOutId);
}else{
$("#list").append(data_aj);
}
});
});
Listen up...
$.get() is a shorthand for $.ajax().
So when you do this
$.get(uri, function(data){
//Your functionality
});
You're really doing this
$.ajax({
url: uri,
type: "GET",
success: function(data) {
//Your functionality
}
});
By default this returns the page as HTML. Or rather, by default, it first checks the MIME-type on the page, and if none is found, it returns HTML. As you are requesting a .txt file it will interpret it as a simple textfile. If you want to tell it what you would like to return (HTML), you can either do it in the MIME-type on the server page, or you could use $.getJSON().
An easy way to solve this is thus doing:
$.get(uri, function(data) {
//Your functionality
},
"html");
Which is the same as doing:
$.ajax({
url: uri,
type: "GET",
dataType: "HTML",
success: function(data) {
//Your functionality
}
});
Also it is not a good idea to use html() because you are replacing the existing html inside of your ul element every time you want to add an additional new node.
Try making use of:
$('#list').append('<li>' + data_aj + '</li>');
Basically you can just append the <li> to the <ul> itself.
Lastly make sure your dom has already been loaded by placing all your JQuery code into the
$(document).ready(function() {
//Your code...
});
Otherwise if your HTML is not fully loaded yet, your list might not exist yet so there is no way for JQuery to put some values into unexisting HTML.

Jquery script works only after opening new window in IE

The script below queries a PHP service that returns a JSON response. Buttons are created for each returned record, allowing the user to delete that record from the database. A link is also created below to refresh the data.
This all works fine in IE, Chrome, Safari...IE (tried 8 & 9), however, is having a strange issue.
When the page loads, I am able to refresh the data by clicking the 'refresh' link. After this, clicking has no effect UNLESS I open the same page in a different IE window, click the link in the new window, and return to the original window. The 'refresh' link then works on the new window ONE time. It then turns into a vicous cycle.
Your help is appreciated!
function getNew(){
$('#new').remove();
$.getJSON('service.php', function(data) {
var items = [];
items.push('<tr><th>EmplId</th><th>ExternalID</th><th>Name</th></tr>');
$.each(data, function(key, val) {
var indiv = val.toString().split(",");
items.push('<tr>');
var id = indiv[0];
$.each(indiv, function(index, value) {
items.push('<td align="center" id="' + index + '">' + value + '</td>');
});
items.push('<td class="updateButton" align="center" onclick=\'return update("'+id+'")\'>Update</td>');
});
items.push('<tr><td class="refreshButton" align="center" onclick=\'return getNew();\'>Refresh </td></tr>');
$('<table/>', {
'id': 'new',
html: items.join('')
}).appendTo('body');
});
}
function update (emplID){
$.ajax({
url: "service.php?emplID="+emplID,
context: document.body,
success: function(){
$('#new').remove();
getNew();
}
});
}
I have tried using .live and I get the same results.
$(".refreshButton").live("click" , function() {
getNew();
$.ajax({
url: "Service.php?emplID=",
context: document.body,
success: function(){
$('#new').remove();
getNew(); }
});
});
I have disabled the cache still to no avail. The ONLY way to make the link work is to open the same page in a separate window, click the link, and return to the original window. Is there any solution to this?
$(".refreshButton").live( "click" , function() {
getNewStudents();
$.ajax({
url: "studentService.php?emplID=",
cache: false,
context: document.body,
success: function(){
$('#newStudents').remove();
getNewStudents();
}
});
});
Thanks for your suggestions. I fixed the tr, but it seems that the solution was to use
$.ajaxSetup({ cache: false });
It seems all versions of IE treat ajax calls as normal web requests (cacheable), whereas other browsers consider ajax calls as non-cacheable.
Learned something new today, thanks guys!
Maybe it's because of cache, have you tried to clear your cache and try again? this may help http://kb.iu.edu/data/ahic.html#ie8
Perhaps IE is choking on the malformed HTML that getNew is generating; note that in your .each loop, you are not closing the tr element. Also, if you're getting a JavaScript error, JS execution may stop, so make sure your browser isn't configured such that it ignores JS errors. Check the error console.

jQuery selectors on an ajax response string that is a full html page

I'm trying to get some page details (page title, images on the page, etc.) of an arbitrarily entered URL/page. I have a back-end proxy script that I use via an ajax GET in order to return the full HTML of the remote page. Once I get the ajax response back, I'm trying to run several jQuery selectors on it to extract the page details. Here's the general idea:
$.ajax({
type: "GET",
url: base_url + "/Services/Proxy.aspx?url=" + url,
success: function (data) {
//data is now the full html string contained at the url
//generally works for images
var potential_images = $("img", data);
//doesn't seem to work even if there is a title in the HTML string
var name = $(data).filter("title").first().text();
var description = $(data).filter("meta[name='description']").attr("content");
}
});
Sometimes using $("selector", data) seems to work while other times $(data).filter("selector") seems to work. Sometimes, neither works. When I just inspect the contents of $(data), it seems that some nodes make it through, but some just disappear. Does anyone know a consistent way to run selectors on a full HTML string?
Your question is kind of vague, especially w/r/t what input causes what code to fail, and how. It could be malformed HTML that's mucking things up - but I can only guess.
That said, your best bet is to work with $(data) rather than data:
$.ajax({
type: "GET",
url: base_url + "/Services/Proxy.aspx?url=" + url,
success: function(data) {
var $data = $(data);
//data is now the full html string contained at the url
//generally works for images
var potential_images = $("img", $data);
//doesn't seem to work even if there is a title in the HTML string
var name = $data.filter("title").first().text();
var description = $data.filter("meta[name='description']").attr("content");
}
});

jquery .get/.post not working on ie 7 or 8, works fine in ff

I have basically this on a page:
<script type="text/javascript">
function refresh_context() {
$("#ajax-context").html("Searching...");
$.get("/ajax/ldap_search.php", {cn: $("#username").val()}, function(xml) {
$("#ajax-context").html($("display", xml).text());
$("#context").val($("context", xml).text());
}, 'xml');
}
$(document).ready(function() {
$("#username").blur(refresh_context);
});
</script>
<input type="text" name="username" id="username" maxlength="255" value="" />
<input type="hidden" name="context" id="context" value=""/>
<div id="ajax-context"></div>
What it should do (and does fine on Firefox) is when you type a username in to the #username field, it will run /ajax/ldap_search.php?cn=$username, which searches our company's ldap for the username and returns it's raw context and a formatted version of the context like this:
<result>
<display>Staff -> Accounting -> John Smith</display>
<context>cn=jsmith,ou=Accounting,ou=Staff,ou=Users,o=MyOrg</context>
</result>
The formatted version (display) goes to the div #ajax-context and goes to the hidden input #context. (Also, the -> are actually - "& g t ;" (without spaces)).
However, on IE the div stays stuck on "Searching..." and the hidden input value stays blank.
I've tried both .get and .post and neither work. I'm sure it's failing on the .get because if I try this, I don't even get the alert:
$.get("/ajax/ldap_search.php", {cn: $("#username").val()}, function() {
alert("Check");
});
Also, IE doesn't give me any script errors.
Edit: Added "$(document).ready(function() {", the .blur was already in it in my code, but I forgot to include that in my post.
Edit 2: The request is being sent and apache2 is receiving it:
10.135.128.96 - - [01/May/2009:10:04:27 -0500] "GET /ajax/ldap_search.php?cn=i_typed_this_in_IE HTTP/1.1" 200 69
Problem was in the ldap_search.php file.
I had this (based on an example I read on someone's blog):
header("content-type:application/xml-xhtml;charset=utf-8");
It actually needed to be this for IE to read it properly:
header("content-type:application/xml;charset=utf-8");
God, I hate IE.
Try changing:
$("#username").blur(refresh_context);
To:
$(function(){
$("#username").blur(refresh_context);
});
This will hold off on assigning the blur event until the entire page is loaded.
Edit:
Could it be the use of > in the text of the XML?
set your type to 'xml'
jQuery.get( url, [data], [callback], [type] )
$.get("/ajax/ldap_search.php", {cn: $("#username").val()}, function() {
alert("Check");
},'xml');
Can you find out if the Ajax request is even being fired?
You can use Web Development Helper or Fiddler to log Ajax requests.
As general good practice you should enclose any jQuery code that accesses the DOM in a $(document).ready function. This will ensure it doesn't execute until the entire DOM is loaded, although in this instance it doesn't look like that's causing the problem if the div is changing to 'Loading...'
<script type="text/javascript">
function refresh_context() {
$("#ajax-context").html("Searching...");
$.get("/ajax/ldap_search.php", {cn: $("#username").val()}, function(xml) {
$("#ajax-context").html($("display", xml).text());
$("#context").val($("context", xml).text());
}, "xml"); // As pointed out, you should specify the return type
}
$(document).ready(function() {
$("#username").blur(refresh_context);
});
</script>
You may want to change the $.get call to a $.ajax call, so you can set an error handler to see why it's erroring.
As I recall, this is done like this:
$.ajax({
type: 'GET',
url: "/ajax/ldap_search.php",
data: {cn: $("#username").val()},
success: function(response) { /* do something here */ },
error: function(xhr, type, exception) { alert("Error: " + type); }
})
The exception object should have more detail about the error as well.
I had same problem but not with xml - i had simple html as ajax-return. header("content-type:text;charset=utf-8"); was the solution.
Does not work:
$.post("/welcome/add_mail", function(data){
alert('ok');
});
Works fine with base url in IE7:
$.post("http://localhost/welcome/add_mail", function(data){
alert('ok');
});
Usually with $.get/$.post you have to specify the return type. This makes it easier for jquery to a) recognize what it looks for and b) decode it for you.
This may help.
Instead of $("display", xml).text()
Maybe try: $(xml).find("display").text()
Can you see what the response is or is it just timing out? Can you see what params are being sent in? If not, expand your:
function refresh_context() {
$("#ajax-context").html("Searching...");
$.get("/ajax/ldap_search.php", {cn: $("#username").val()}, function(xml) {
$("#ajax-context").html($("display", xml).text());
$("#context").val($("context", xml).text());
}, "xml"); // As pointed out, you should specify the return type
}
to
function refresh_context() {
$("#ajax-context").html("Searching...");
$.get("/ajax/ldap_search.php", {cn: $("#username").val()}, function(xml) {
var displayXml = $("display", xml).text();
$("#ajax-context").html(displayXml);
var contextXml = $("context", xml).text();
$("#context").val(contextXml);
}, "xml"); // As pointed out, you should specify the return type
}
and then debugging the script.
I had a similar problem, but loading JSON. The $.ajax fix worked for me but I also discovered that in my case it had to do with the URL. When I use:
$.getJSON('',{ ajax: "addressPicker",OID:pickIDNo,s:pickVal}, function(data) {
I would get a silent response, but when I replaced the empty URL '' with '?' it worked. In your case the URL was present, but it might be picky as to URL.

Categories