I have a jQuery jsTree populated from the server via an ajax call. When I add a new node I make an ajax call then make a call to refresh the tree with tree.jstree("refresh"). After the refresh I want to select the node I just added. Unfortunately there doesn't seem to be a callback that can be passed to this command. Is there any clean way to do this?
oh, such a long time since this post ... and still couldn't find an answer on internet.
So after a few hours of ... no no no, not this, came up with a solutin
var jsTreeId = '#jstree'; // or whatever name the jstree has
var jsTreeSelectedItemId = 5; // just an example
var selectedNode = $('#node_'+jsTreeSelectedItemId);
var parentNode = $.jstree._reference(jsTreeId)._get_parent(selectedNode);
// now lets say that you add a new node from server side, you get the new id of the created node by an ajax call, and next you want to refresh the tree in order to display it, and also select it
var newSelectId = 9; // or from ajax call
// call the refresh function, which is asnyc
$.jstree._reference(jsTreeId).refresh(parentNode);
// set the magic "to_select" variable with an array of node ids to be selected
// note: this must be set after refresh is called, otherwise won't work
$.jstree._reference(jsTreeId).data.ui.to_select = ['#node_'+newSelectId];
$('#tree').jstree("select_node", '#1', true);
//other node are deselected if pass last argument as true.
$('#tree').jstree("select_node", '#1', false);
//other node are selected and new one also selected.
Related
In my website I'm Showing my database after user has given the database name, Is there any way I can constantly update the web shown databasebase without refreshing the page . I've tried using setInterval but it's not working for some reason .
function c(){
setInterval(beta, 1000);
}
function beta(){
var d = document.getElementById("opopo").value;
var firebaseRefff= firebase.database().ref('LOCATION/'+d);
firebaseRefff.on('child_added', snap=> {
var slot=snap.getKey();
var alloted=snap.child("ALLOTED").val();
var date=snap.child("DATE").val();
var limit=snap.child("LIMIT").val();
var time=snap.child("TIME").val();
$("table tbody").append(""+slot+""+alloted+""+date+""+limit+""+time+"Null");
});
}
You do not need, and should not use, setInterval to trigger the queries. What you have in your beta() function looks pretty good.
firebaseRefff.on('child_added', snap => {}) means "whenever a child is added under this location, trigger the callback function (empty in my example) with the parameter 'snap'". It will also be called once, initially, for each child that is already at that database reference location.
You need to make sure you've called beta() once to setup this trigger.
If you're still having problems, you might want to insert logging to make sure beta() is being called, what the full reference path is, if the callback is ever triggered, and if your jquery string is correct.
I'm trying to learn how to use KnockOut... never have before and I've been thrown into the fire on a site already using it. Everything here works fine:
function MasterViewModel() {
var self = this;
self.Supervisors = ko.mapping.fromJS(#Html.Raw(JsonConvert.SerializeObject(Model.Supervisors)));
self.AddSupervisor = function(request) {
var request = new Supervisor({
FullName: $('#SupervisorId option:selected').text(),
SupervisorId: $('#SupervisorId option:selected').val()
});
self.Supervisors.push(request);
// do server side call here
}
self.RemoveSupervisor = function(request) {
if (request.SupervisorID() > 0)
{
self.Supervisors.remove(request);
// do server side call here
}
}
}
Well. Everything almost works fine:
The initial data from the server loads and displays perfectly
I can remove existing items (that came from the server on the original page load)
I can add new items
But, when I try to remove an item that I just added, I get this:
Uncaught TypeError: request.SupervisorID is not a function
SupervisorId is a dropdown. The AddSupervisor call is made from a button. I can show the HTML if needed. Also, although I may not need this if:
if (request.SupervisorID() > 0)
Even without it, I am going to need the ID of the supervisor that was added.
I'm guessing the server side isn't case-sensitive, and is loading data with SupervisorID. When you add a new one, you're creating it with SupervisorId (lowercase d). The server must be accepting of that. JavaScript isn't.
You need to either change the newly created users to use SupervisorID, or have the RemoveSupervisor function use SupervisorId - whichever change makes more sense in your overall structure.
I'm trying to write a plugin-like function in jQuery to add elements to a container with AJAX.
It looks like this:
$.fn.cacheload = function(index) {
var $this = $(this);
$.get("cache.php", {{ id: index }).done(function(data) {
// cache.php returns <div class='entry'>Content</div> ...
$(data).insertAfter($this.last());
});
}
and I would like to use it like this:
var entries = $("div.entry"),
id = 28;
entries.cacheload(id);
Think that this would load another "entry"-container and add it to the DOM.
This is works so far. But of course the variable that holds the cached jQuery object (entries) isn't updated. So if there were two divs in the beginning and you would add another with this function it would show in the DOM, but entries would still reference the original two divs only.
I know you can't use the return value of get because the AJAX-call is asynchronous. But is there any way to update the cached object so it contains the elements loaded via AJAX as well?
I know I could do it like this and re-query after inserting:
$.get("cache.php", {{ id: num }).done(function(data) {
$(data).insertAfter($this.last());
entries = $("div.entry");
});
but for this I would have to reference the variable holding the cached objects directly.
Is there any way around this so the function is self-contained?
I tried re-assigning $(this), but got an error. .add() doesn't update the cached object, it creates a new (temporary) object.
Thanks a lot!
// UPDATE:
John S gave a really good answer below. However, I ended up realizing that for me something else would actually work better.
Now the plugin function inserts a blank element (synchronously) and when the AJAX call is complete the attributes of that element are updated. That also ensures that elements are loaded in the correct order. For anyone stumbling over this, here is a JSFiddle: http://jsfiddle.net/JZsLt/2/
As you said yourself, the ajax call is asynchronous. Therefore, your plugin is asynchronous as as well. There's no way for your plugin to add the new elements to the jQuery object until the ajax call returns. Plus, as you discovered, you can't really add to the original jQuery object, you can only create a new jQuery object.
What you can do is have the plugin take a callback function as a second parameter. The callback could be passed a jQuery object that contains the original elements plus the newly inserted ones.
$.fn.cacheload = function(index, callback) {
var $this = this;
$.get('cache.php', { id: index }).done(function(html) {
var $elements = $(html);
$this.last().after($elements);
if (callback) {
callback.call($this, $this.add($elements));
}
});
return $this;
};
Then you could call:
entries.cacheload(id, function($newEntries) { doSomething($newEntries); } );
Of course, you could do this:
entries.cacheload(id, function($newEntries) { entries = $newEntries; } );
But entries will not be changed until the ajax call returns, so I don't see much value in it.
BTW: this inside a plugin refers to a jQuery object, so there's no need to call $(this).
I have ddl(drop down list) which populates from database after change event of another ddl but I want to change the value of this ddl after it populated from database.
Example:
// This work very well
$("#ddlGroups").on('change',function(){
// Load data from database and populate ddlUsers
// response is loaded from database with $.ajax
// Query Example: SELECT User_ID, Username FROM tblUsers WHERE Group_ID = [Group_ID] (Just for undrestanding the question)
var Records = response.d;
$("#ddlUsers").empty();
$.each(Records, function(){
var _Key = this.User_ID;
_Value = this.Username;
$("#ddlUsers").append($("<option />").val(_Key).text(_Value));
});
});
// When button clicked then trigger ddlGroups change event and assign select option from ddlUsers
var _UserID = User_ID_From_Database; // Loaded from Database when button clicked
$("#ddlGroups").trigger('change'); // Users are loaded from database based on group ID
$("#ddlUsers").val(_UserID); // But this dosn't change
How do I check if ddlUsers is loaded or not, I tried while loop but it never stops.
With jquery there are two main ways (really the same underlying) to connect a ajax response from the database to a event or UI result. The first is promises and the second is a callback. Both these have 1 million examples and jquery documentation is quite robust.
In your case rather than "trigger", you callback calls the right function. The below is just junk code to show.
No: $("#ddlGroups").tigger('change');
Yes:
//Your code
$("#ddlGroups").on('change', updateDDL);
//I have just externalized this function to a scope/place where both the ajax and on change line of code can reference it.
function updateDDL(){
var Records = response.d;
$("#ddlUsers").empty();
$.each(Records, function(){
var _Key = this.User_ID;
_Value = this.Username;
$("#ddlUsers").append($("<option />").val(_Key).text(_Value));
}
};
$.ajax(...., function (data) {
// Update ddl, the existing function you have.
// You should already have something like this.
updateDDL(); //Like this
});
BTW: You could pass the data into the updateDDL directly use $(this) in the updateDDL to improve it etc but that is not key to your question/issue. It seems that you are new to jquery and some of the Javascript features it uses. Take a little time to learn about them and you will be WELL rewarded. I would start by reading examples around ajax/jquery and watch how then update the DOM.
I am modifying a third party - web client application in which I only have access to certain js files.
The search function is limited to search in one given server node at a time, and as a work around, I hardcoded all the server nodes and created a for loop, invoking the "search" several times, at different nodes.
The server response (in a form of FORM - without getters) are automatically handled by a callback, which then renders the view of the form. This means I am only able to display the last response and thus displaying only one set of result.
To handle this, I added $trs = $(tr).clone(true) on the callback function, saving all the rows from previous forms and then - I made the last loop to "search" to have another callback - which will then append the collected rows from $tr and display the last form complete with all the results from all nodes.
But the result is inconsistent. It sometimes just displays result from one server node. I would think this is caused by some delay in server response which caused that form to render last. I tried to put delay by setTimeout function, but that keeps me from getting any result at all
I am very new with all the web programming - JS and JQUERY both (well CSS and HTML even lol) and I would like to ask for your suggestions on a better way to handle this.
Thank you!
_handleConfigSubmit: function (form, error) {
//alert("_handleConfigSubmit");
if (form) {
var formView = new jabberwerx.ui.XDataFormView(form);
var that = this;
formView.event("xdataItemSelected").bind(function(evt) {
that.jq.find(".muc_search_button_join").removeAttr("disabled");
var resultTable = that.jq.find(".muc_search_results table.result_table");
resultTable.find("tr.selected").removeClass("selected");
that._selectedItem = evt.data.selected;
resultTable.find("tr#"+evt.data.selected._guid).addClass("selected");
});
var searchResultsDiv = jabberwerx.$(".muc_search_results", this.jq);
searchResultsDiv.empty();
this.update();
var dim = {
width: searchResultsDiv.width(),
height: searchResultsDiv.height()
};
formView.render().appendTo(searchResultsDiv);
formView.dimensions(dim);
$trs = $("table.result_table tbody>tr:not(:first)").clone(true);
if ($trList!=null){
$trList = $trList.add($trs);
}else{
$trList = $trs;
}
$("table.result_table tbody>tr:not(:first)").remove()
if (ctr<=3){
$("table.result_table tbody").append($trList);
}else{
ctr++;
}
} else {
this._showError(error);
}
}